Compiler  --> Tool chain
  - compiler
  - compile utility
  - library
를 제공 해 준다.

교재 8페이지 참고

일반 라이브러리가 아니고 커널의 서비스를 이용하기 위해서 사용하는 것이 S/W interrupt이다. S/W interrupt가 걸리면 프로그램의 실행 권한이 바뀌어서 커널의 system call을 사용할 수 있게 된다.

Virtual File System은 함수 포인터를 사용하여 다양한 파일 시스템을 공통된 하나의 이름으로 같은 동작을 하도록 만들 수 있는 방식이다.

http://lxr.post-tech.com

http://www.kelp.or.kr
박철 강사님이 지금 강의 하고 계신분...

http://kelp.or.kr/korweblog/stories.php ··· pic%3D13
여기에 있는 내용 중
http://kelp.or.kr/korweblog/upload/13/2 ··· io_o.jpg
위 파일에 대한 설명

교재 페이지 9

insmod sk.o 를 하게 되면
1. sys_create_module()
2. sys_get_kernel_syms()
3. sys_init_module()
세개의 함수로 메모리에 적재 하게 된다.

Kernel 내부에 module이 저장되는 부분이 sk.o 내부에 있는 init_module() 함수를 가리키고(init()함수) 있어서 위 세개의 함수를 부른 후에 mod->init() 하게 된다.

init_module()
{
  register_chardevs();  --> 문자 장치에 등록
}

linux command 상에서 일어 나는 일을 순서대로 이해해 보자
shell       <---- 부모
-------------------------------
> insmod sk.o         <----- 자식


시스템 콜 호출(insmod 명령어를 실행했을때)   <------ 모듈을 메모리에 적재
-----------------------------------------
sys_create_module()
- 모듈 구조체를 할당
- 모듈의 사이즈 정보 및 각종 정보를 전달
sys_get_kernel_syms()
- 모듈과 커널간에 symbol(함수명, 전역 변수) 를 상호 참조 할 수 있도록 등록
sys_init_module()
- 모듈(sk.o)을 메모리에 적재한다.
- mod->init() 함수 호출, 여기서 mod는 sys_create_module()에서 할당한 구조체
  * 모듈내의 init_module() 함수가 호출되어 진다.


문자 장치로 등록
-----------------------
init_module()
{
  ret = register_chrdev(0, "SK", &sk_fops); // Kernel function
        // 0 -> major, "SK" -> 모듈이름, sk_fops -> 함수 묶음   
}


Kernel에서 chardevs[] 배열 구조체에 문자 장치를 등록한다.
-------------------------------------------------------


이 밑으로는 소스 코드 분석을 시작...
http://lxr.post-tech.com/
에서

pxa255_kernel2.4.18-rmk7  선택
identifier search  선택
찾기에서 sys_create_module

287 /*
288 * Allocate space for a module.
289 */
290
291 asmlinkage unsigned long
292 sys_create_module(const char *name_user, size_t size)
293 {
294         char *name;
295         long namelen, error;
296         struct module *mod;
297         unsigned long flags;
298
299         if (!capable(CAP_SYS_MODULE))
300                 return -EPERM;
301         lock_kernel();
302         if ((namelen = get_mod_name(name_user, &name)) < 0) {
303                 error = namelen;
304                 goto err0;
305         }
306         if (size < sizeof(struct module)+namelen) {
307                 error = -EINVAL;
308                 goto err1;
309         }
310         if (find_module(name) != NULL) {
311                 error = -EEXIST;
312                 goto err1;
313         }
314         if ((mod = (struct module *)module_map(size)) == NULL) {
                            // module 구조체를 할당 받음
315                 error = -ENOMEM;
316                 goto err1;
317         }
318
319         memset(mod, 0, sizeof(*mod));
320         mod->size_of_struct = sizeof(*mod);
321         mod->name = (char *)(mod + 1);
322         mod->size = size;
323         memcpy((char*)(mod+1), name, namelen+1);
324
325         put_mod_name(name);
326
327         spin_lock_irqsave(&modlist_lock, flags);
328         mod->next = module_list; // 링크드 리스트의 앞쪽에 붙인다
329         module_list = mod;      /* link it in */
330         spin_unlock_irqrestore(&modlist_lock, flags);
331
332         error = (long) mod;
333         goto err0;
334 err1:
335         put_mod_name(name);
336 err0:
337         unlock_kernel();
338         return error;
339 }

위의 소스에서 module 구조체 클릭

53 struct module
54 {
55         unsigned long size_of_struct;   /* == sizeof(module) */
56         struct module *next;
57         const char *name;   // <-- 모듈의 이름 등록
58         unsigned long size; // <-- 모듈의 사이즈
59
60         union
61         {
62                 atomic_t usecount;  // <-- 유저 카운트를 해서 사용중인 경우 해제 못하도록
63                 long pad;
64         } uc;                           /* Needs to keep its size - so says rth */
65
66         unsigned long flags;            /* AUTOCLEAN et al */
67
68         unsigned nsyms;
69         unsigned ndeps;
70
71         struct module_symbol *syms;
72         struct module_ref *deps;
73         struct module_ref *refs;
74         int (*init)(void);  // <-- init와 아래의 clean 함수 포인터
75         void (*cleanup)(void);
76         const struct exception_table_entry *ex_table_start;
77         const struct exception_table_entry *ex_table_end;
78 #ifdef __alpha__
79         unsigned long gp;
80 #endif
81         /* Members past this point are extensions to the basic
82           module support and are optional.  Use mod_member_present()
83           to examine them.  */
84         const struct module_persist *persist_start;
85         const struct module_persist *persist_end;
86         int (*can_unload)(void);
87         int runsize;                    /* In modutils, not currently used */
88         const char *kallsyms_start;     /* All symbols for kernel debugging */
89         const char *kallsyms_end;
90         const char *archdata_start;     /* arch specific data for module */
91         const char *archdata_end;
92         const char *kernel_data;        /* Reserved for kernel internal use */
93 };


sys_get_kernel_syms

953 sys_get_kernel_syms(struct kernel_sym *table)
954 {
955         struct module *mod;
956         int i;
957         struct kernel_sym ksym;
958
959         lock_kernel();
960 for (mod = module_list, i = 0; mod; mod = mod->next) {
961                 /* include the count for the module name! */
962                 i += mod->nsyms + 1;
963         }
964
965         if (table == NULL)
966                 goto out;
967
968         /* So that we don't give the user our stack content */
969         memset (&ksym, 0, sizeof (ksym));
970
971         for (mod = module_list, i = 0; mod; mod = mod->next) {
972                 struct module_symbol *msym;
973                 unsigned int j;
974
975                 if (!MOD_CAN_QUERY(mod))
976                         continue;
977
978                 /* magic: write module info as a pseudo symbol */
979                 ksym.value = (unsigned long)mod;
980                 ksym.name[0] = '#';
981                 strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);
982                 ksym.name[sizeof(ksym.name)-1] = '\0';
983
984                 if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
985                         goto out;
986                 ++i, ++table;
987
988                 if (mod->nsyms == 0)
989                         continue;
990
991                 for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {
992                         ksym.value = msym->value;
993                         strncpy(ksym.name, msym->name, sizeof(ksym.name));
994                         ksym.name[sizeof(ksym.name)-1] = '\0';
995
996                         if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
997                                 goto out;
998                         ++i, ++table;
999                 }
1000         }
1001 out:
1002         unlock_kernel();
1003         return i;
1004 }

세번째로 불리는 sys_init_module 함수, 552 줄

346 sys_init_module(const char *name_user, struct module *mod_user)
347 {
348         struct module mod_tmp, *mod;
349         char *name, *n_name, *name_tmp = NULL;
350         long namelen, n_namelen, i, error;
351         unsigned long mod_user_size;
352         struct module_ref *dep;
353
354         if (!capable(CAP_SYS_MODULE))
355                 return -EPERM;
356         lock_kernel();
357         if ((namelen = get_mod_name(name_user, &name)) < 0) {
358                 error = namelen;
359                 goto err0;
360         }
361         if ((mod = find_module(name)) == NULL) {
362                 error = -ENOENT;
363                 goto err1;
364         }
365
366         /* Check module header size.  We allow a bit of slop over the
367           size we are familiar with to cope with a version of insmod
368           for a newer kernel.  But don't over do it. */
369         if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
370                 goto err1;
371         if (mod_user_size < (unsigned long)&((struct module *)0L)->persist_start
372             || mod_user_size > sizeof(struct module) + 16*sizeof(void*)) {
373                 printk(KERN_ERR "init_module: Invalid module header size.\n"
374                        KERN_ERR "A new version of the modutils is likely "
375                                 "needed.\n");
376                 error = -EINVAL;
377                 goto err1;
378         }
379
380         /* Hold the current contents while we play with the user's idea
381           of righteousness.  */
382         mod_tmp = *mod;
383         name_tmp = kmalloc(strlen(mod->name) + 1, GFP_KERNEL);  /* Where's kstrdup()? */
384         if (name_tmp == NULL) {
385                 error = -ENOMEM;
386                 goto err1;
387         }
388         strcpy(name_tmp, mod->name);
389
390         error = copy_from_user(mod, mod_user, mod_user_size);
391         if (error) {
392                 error = -EFAULT;
393                 goto err2;
394         }
395
396         /* Sanity check the size of the module.  */
397         error = -EINVAL;
398
399         if (mod->size > mod_tmp.size) {
400                 printk(KERN_ERR "init_module: Size of initialized module "
401                                 "exceeds size of created module.\n");
402                 goto err2;
403         }
404
405         /* Make sure all interesting pointers are sane.  */
406
407         if (!mod_bound(mod->name, namelen, mod)) {
408                 printk(KERN_ERR "init_module: mod->name out of bounds.\n");
409                 goto err2;
410         }
411         if (mod->nsyms && !mod_bound(mod->syms, mod->nsyms, mod)) {
412                 printk(KERN_ERR "init_module: mod->syms out of bounds.\n");
413                 goto err2;
414         }
415         if (mod->ndeps && !mod_bound(mod->deps, mod->ndeps, mod)) {
416                 printk(KERN_ERR "init_module: mod->deps out of bounds.\n");
417                 goto err2;
418         }
419         if (mod->init && !mod_bound(mod->init, 0, mod)) {
420                 printk(KERN_ERR "init_module: mod->init out of bounds.\n");
421                 goto err2;
422         }
423         if (mod->cleanup && !mod_bound(mod->cleanup, 0, mod)) {
424                 printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n");
425                 goto err2;
426         }
427         if (mod->ex_table_start > mod->ex_table_end
428             || (mod->ex_table_start &&
429                 !((unsigned long)mod->ex_table_start >= ((unsigned long)mod + mod->size_of_struct)
430                   && ((unsigned long)mod->ex_table_end
431                       < (unsigned long)mod + mod->size)))
432             || (((unsigned long)mod->ex_table_start
433                  - (unsigned long)mod->ex_table_end)
434                 % sizeof(struct exception_table_entry))) {
435                 printk(KERN_ERR "init_module: mod->ex_table_* invalid.\n");
436                 goto err2;
437         }
438         if (mod->flags & ~MOD_AUTOCLEAN) {
439                 printk(KERN_ERR "init_module: mod->flags invalid.\n");
440                 goto err2;
441         }
442         if (mod_member_present(mod, can_unload)
443             && mod->can_unload && !mod_bound(mod->can_unload, 0, mod)) {
444                 printk(KERN_ERR "init_module: mod->can_unload out of bounds.\n");
445                 goto err2;
446         }
447         if (mod_member_present(mod, kallsyms_end)) {
448             if (mod->kallsyms_end &&
449                 (!mod_bound(mod->kallsyms_start, 0, mod) ||
450                  !mod_bound(mod->kallsyms_end, 0, mod))) {
451                 printk(KERN_ERR "init_module: mod->kallsyms out of bounds.\n");
452                 goto err2;
453             }
454             if (mod->kallsyms_start > mod->kallsyms_end) {
455                 printk(KERN_ERR "init_module: mod->kallsyms invalid.\n");
456                 goto err2;
457             }
458         }
459         if (mod_member_present(mod, archdata_end)) {
460             if (mod->archdata_end &&
461                 (!mod_bound(mod->archdata_start, 0, mod) ||
462                  !mod_bound(mod->archdata_end, 0, mod))) {
463                 printk(KERN_ERR "init_module: mod->archdata out of bounds.\n");
464                 goto err2;
465             }
466             if (mod->archdata_start > mod->archdata_end) {
467                 printk(KERN_ERR "init_module: mod->archdata invalid.\n");
468                 goto err2;
469             }
470         }
471         if (mod_member_present(mod, kernel_data) && mod->kernel_data) {
472             printk(KERN_ERR "init_module: mod->kernel_data must be zero.\n");
473             goto err2;
474         }
475
476         /* Check that the user isn't doing something silly with the name.  */
477
478         if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod
479                                       + (unsigned long)mod_user,
480                                       &n_name)) < 0) {
481                 printk(KERN_ERR "init_module: get_mod_name failure.\n");
482                 error = n_namelen;
483                 goto err2;
484         }
485         if (namelen != n_namelen || strcmp(n_name, mod_tmp.name) != 0) {
486                 printk(KERN_ERR "init_module: changed module name to "
487                                 "`%s' from `%s'\n",
488                        n_name, mod_tmp.name);
489                 goto err3;
490         }
491
492         /* Ok, that's about all the sanity we can stomach; copy the rest.  */
493
494         if (copy_from_user((char *)mod+mod_user_size,
495                            (char *)mod_user+mod_user_size,
496                            mod->size-mod_user_size)) {
497                 error = -EFAULT;
498                 goto err3;
499         }
500
501         if (module_arch_init(mod))
502                 goto err3;
503
504         /* On some machines it is necessary to do something here
505           to make the I and D caches consistent.  */
506         flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);
507
508         mod->next = mod_tmp.next;
509         mod->refs = NULL;
510
511         /* Sanity check the module's dependents */
512         for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
513                 struct module *o, *d = dep->dep;
514
515                 /* Make sure the indicated dependencies are really modules.  */
516                 if (d == mod) {
517                         printk(KERN_ERR "init_module: self-referential "
518                                         "dependency in mod->deps.\n");
519                         goto err3;
520                 }
521
522                 /* Scan the current modules for this dependency */
523                 for (o = module_list; o != &kernel_module && o != d; o = o->next)
524                         ;
525
526                 if (o != d) {
527                         printk(KERN_ERR "init_module: found dependency that is "
528                                 "(no longer?) a module.\n");
529                         goto err3;
530                 }
531         }
532
533         /* Update module references.  */
534         for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
535                 struct module *d = dep->dep;
536
537                 dep->ref = mod;
538                 dep->next_ref = d->refs;
539                 d->refs = dep;
540                 /* Being referenced by a dependent module counts as a
541                   use as far as kmod is concerned.  */
542                 d->flags |= MOD_USED_ONCE;
543         }
544
545         /* Free our temporary memory.  */
546         put_mod_name(n_name);
547         put_mod_name(name);
548
549         /* Initialize the module.  */
550         atomic_set(&mod->uc.usecount,1);
551         mod->flags |= MOD_INITIALIZING;
552         if (mod->init && (error = mod->init()) != 0) {
                    // 모듈내의 init_module() 호출
553                 atomic_set(&mod->uc.usecount,0);
554                 mod->flags &= ~MOD_INITIALIZING;
555                 if (error > 0)  /* Buggy module */
556                         error = -EBUSY;
557                 goto err0;
558         }
559         atomic_dec(&mod->uc.usecount);
560
561         /* And set it running.  */
562         mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;
563         error = 0;
564         goto err0;
565
566 err3:
567         put_mod_name(n_name);
568 err2:
569         *mod = mod_tmp;
570         strcpy((char *)mod->name, name_tmp);    /* We know there is room for this */
571 err1:
572         put_mod_name(name);
573 err0:
574         unlock_kernel();
575         kfree(name_tmp);
576         return error;
577 }

모듈의 init_module() 함수 내에서 실제로 character device를 등록하는 함수인 register_chrdev() 함수

ret = register_chrdev(0, "SK", &sk_fops); 로 호출 되는 경우

chrdevs[] : 커널에서 문자 장치 디바이스 드라이버를 관리하는 배열 구조체
1. 구조체의 type define

33 struct device_struct {
34         const char * name;
35         struct file_operations * fops;
36 };
위 구조체의 size 는 8 바이트 이다.

2. 구조체의 record (메모리 할당) 및 초기화
15 #define MAX_CHRDEV      255

39 static struct device_struct chrdevs[MAX_CHRDEV];

전역 배열로 구조체를 record(메모리 할당)

3. 사용

98 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
99 {
100         if (major == 0) {
101                 write_lock(&chrdevs_lock);
102                 for (major = MAX_CHRDEV-1; major > 0; major--) {
-->103                         if (chrdevs[major].fops == NULL) {
-->104                                 chrdevs[major].name = name;
-->105                                 chrdevs[major].fops = fops;
106                                 write_unlock(&chrdevs_lock);
107                                 return major;
108                         }
109                 }
110                 write_unlock(&chrdevs_lock);
111                 return -EBUSY;
112         }
113         if (major >= MAX_CHRDEV)
114                 return -EINVAL;
115         write_lock(&chrdevs_lock);
-->116         if (chrdevs[major].fops && chrdevs[major].fops != fops) {
117                 write_unlock(&chrdevs_lock);
118                 return -EBUSY;
119         }
-->120         chrdevs[major].name = name;
-->121         chrdevs[major].fops = fops;
122         write_unlock(&chrdevs_lock);
123         return 0;
124 }


이 소스까지가 교재 10페이지 슬라이드 8 페이지에서 설명하는 내용이다.



크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.cipher.pe.kr/tt/cipher/rss/response/12

댓글+트랙백 ATOM :: http://www.cipher.pe.kr/tt/cipher/atom/response/12

트랙백 주소 :: http://www.cipher.pe.kr/tt/cipher/trackback/12

트랙백 RSS :: http://www.cipher.pe.kr/tt/cipher/rss/trackback/12

트랙백 ATOM :: http://www.cipher.pe.kr/tt/cipher/atom/trackback/12

댓글을 달아 주세요

댓글 RSS 주소 : http://www.cipher.pe.kr/tt/cipher/rss/comment/12
댓글 ATOM 주소 : http://www.cipher.pe.kr/tt/cipher/atom/comment/12
[로그인][오픈아이디란?]