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 페이지에서 설명하는 내용이다.
받은 트랙백이 없고,
댓글이 없습니다.


글
댓글을 달아 주세요
댓글 RSS 주소 : http://www.cipher.pe.kr/tt/cipher/rss/comment/12댓글 ATOM 주소 : http://www.cipher.pe.kr/tt/cipher/atom/comment/12