쓰기 중심의 과정, 입구 기능과 우리가 그들을 수정할 수있는 단어를 사용합니다 출구 함수에서 : 무엇을 수정 한 후 module_init ()라는와 module_exit ()에, 즉, 커널은 우리가 쓰기 개 항목 기능과 종료 함수를 호출 할 수 있습니까? 여기에서 커널 호출은 다른 세그먼트의 커널 함수를 호출하는 과정을 이해하기 위해 예를 들어 처리를 (동적으로로드 된 모듈을 포함하지 않는, 커널로 컴파일 일시적 분석 모듈 여기) 분석 module_init ()라는한다.
커널에서 다음 기능 분석을 시작 start_kernel, 다음과 같은 절차가 호출된다 :
start_kernel
rest_init
kernel_init
do_basic_setup
do_initcalls ()
직접 do_initcalls 함수를 참조 첫번째 사이클 라인 6을 참조가 종료 __initcall_end 처음부터 __initcall_start하고,이 범위 내에서 기능을 호출 기능이 어디를 정의?
1 정적 공극 __init의 do_initcalls ( 공극 ) 이 { 3 initcall_t * 전화; 4 INT의 개수 = preempt_count (); 5 6 대 (__initcall_start = 전화, 전화 <__initcall_end; 호출 ++) { / * 调用__initcall_start到__initcall_end内的函数* / 7 ktime_t에서 T0, T1, 델타; 8 문자 * MSG = NULL; 9 숯 msgbuf에 [ 40 ]; 10 INT의 결과; (11) (12) 의 경우 (initcall_debug) { 13 의 printk는 ( " P 0X %를 initcall 호출 " *, 전화); 14 print_fn_descriptor_symbol ( " % S () " , 15 (부호 길이 ) * 호); 16 의 printk ( " \ n을 " ); 17 T0 = ktime_get (); 18 } 19 20 결과 = (* 호) (); (21) (22) 의 경우 (initcall_debug) { 23 T1 = ktime_get (); (24) 델타 = ktime_sub (T1, T0); (25) (26) 의 printk ( " initcall 0X %의 P " * 호); 27 print_fn_descriptor_symbol ( " % S () " , 28 (부호 길이 ) * 호); 29 에는 printk ( " . \ n % d의 반환 " , 결과); (30) (31) (의 printk " 0X %의 P를 initcall은 %의 LD의 밀리 초에 대해 실행 : " , 32 * 호, (부호 길이 긴) delta.tv64 >> 20 ); 33 print_fn_descriptor_symbol ( " % S () \ n을 " , 34 (부호 길이 ) * 호); 35 } 36 37 경우 (결과가 초래 && = -ENODEV &&! initcall_debug) { 38 의 sprintf (msgbuf에, " 에러 코드 % D " , 결과); 39 MSG = msgbuf에; (40) } (41) 의 경우 (preempt_count ()! = 카운트) { 42 MSG = "선점 불균형 " ; 43 preempt_count는 () = 카운트; 44 } 45 의 경우 (irqs_disabled ()) { 46 MSG = " 인터럽트가 비활성화 " ; 47 local_irq_enable (); (48) } (49) 의 경우 (MSG) { 50 의 printk (KERN_WARNING " 0X에서 initcall %의 P " * 호), 51 print_fn_descriptor_symbol ( " % S () " , 52 (서명길이 ) * 전화); 53 에는 printk ( " % S \ n을 반환 " , MSG); 54 } 55 } 56 57 / * 보류중인 물건이 initcall 시퀀스로부터이없는 것을 확인 * / 58 ) (flush_scheduled_work는; 59 }
읽기에, 우리는 전체 커널 소스 코드를 검색, 당신은 정의 __initcall_start를 찾을 수 있고, 커널 컴파일 시간에 생성되는 사실,이 두 변수가 아치 / 팔 / 커널 / vmlinux.lds에 정의되어 발견 __initcall_end 커널 링커 스크립트의 전체 소스 코드, 우리는 코드의 핵심 부분에서왔다. 그것은 __initcall_start의 __initcall_end 사이에 볼 수 있습니다 및 섹션의 번호로 세분화 경우 : * (Initcall0.init.) ~ * (Initcall7s.init.).
1 .init { / * 초기화 코드 및 데이터 * / 2 * (.init.text) 3 _einittext = .; 4 __proc_info_begin = .; 5 * (.proc.info.init) 6 __proc_info_end = .; 7 __arch_info_begin = .; 8 * (.arch.info.init) 9 __arch_info_end = .; 10 __tagtable_begin = .; 11 * (.taglist.init) 12 __tagtable_end = .; (13) . ALIGN = (16 ); 14 __setup_start = .; 15 * (.init.setup) 16 __setup_end = .; 17 __early_begin = .; 18 * (.early_param.init) 19 __early_end = .; 20 __initcall_start = .; 21 (*. initcall0.init) (*. initcall0s.init) (*. initcall1.init) (*. initcall1s.init) (*. initcall2.init) (*. initcall2s.init) (*. initcall3.init) * (. initcall3s.init) (*. initcall4.init) (*. initcall4s.init) (*. initcall5.init) (*. initcall5s.init) (*. initcallrootfs.init) (*. initcall6.init) * (.initcall6s.init) (*. initcall7.init) * (.initcall7s.init) 22 __initcall_end = .; 23 __con_initcall_start = .; 24 * (.con_initcall.init) 25 __con_initcall_end = .; 26 __security_initcall_start = .; 27 * (.security_initcall.init) 28 __security_initcall_end = .; (29) (30) . ALIGN = ( 32 ); 31 __initramfs_start = .; 32 USR / 내장 에 .o 인 (.init.ramfs) 33 __initramfs_end = .; 34 (35) . ALIGN = (4096 ); 36 __per_cpu_start = .; 37 * (.data.percpu) 38 __per_cpu_end = .; 39 40 __init_begin = _stext; 41 * (.init.data) 42 . ALIGN = ( 4,096 ); 43 __init_end = .; 44 (45) }
여기 분석, 우리는 돌아가서에서 리눅스 \의 init.h을 \ 포함에 정의되어 module_init ()라는 정의를 참조 계속 :
194 #DEFINE의 module_init ()라는 (X) __initcall (X); 135 #DEFINE의 __initcall (FN) device_initcall (FN) 130 #DEFINE device_initcall (FN) __define_initcall ( "6", FN, 6) 107 #DEFINE \ __define_initcall (레벨, FN, ID) (108) 의 정적 initcall_t __initcall _ ## ## FN ID __attribute_used__ \ 109 __attribute __ ((__ __ 부 ( " .initcall " 레벨 " .init " ))) = FN (76) 의 typedef의 INT (* initcall_t) ( 공극 );
상기 정의에 따라, 최종적으로 얻어지는 module_init ()라는을 확장 할 수있다 :이 긴 통화 module_init ()라는 (X)로서 기능 유형을 넣어 initcall_t로서, X가 정의되고,이 기능이 .initcall6에 저장된 함수라는 __initcall_x6 것을 의미한다. 초기화에서,이 부분은 오른쪽 __initcall_start __initcall_end 사이에 위치한다. 그래서 루프 do_initcalls에서 커널 함수를 호출 할 때입니다.
#DEFINE module_init ()라는 (X) 정적 initcall_t __initcall_x6 __attribute_used__ __attribute __ ((__ __ 절 ( ". initcall"6 ".init"))) = (X)의
다른 세그먼트의 경우, 유사하지만, 어딘가 순환에 사용하기 위해 다른 곳에서 정의 커널 세그먼트에 호출합니다.