의 다른 섹션에 저장된 기록을 읽는 함수 호출 리눅스 커널 소스 코드 분석

쓰기 중심의 과정, 입구 기능과 우리가 그들을 수정할 수있는 단어를 사용합니다 출구 함수에서 : 무엇을 수정 한 후 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)의

 

다른 세그먼트의 경우, 유사하지만, 어딘가 순환에 사용하기 위해 다른 곳에서 정의 커널 세그먼트에 호출합니다.

추천

출처www.cnblogs.com/andyfly/p/11332997.html