注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

时间记录器

记录我的Linux、Android学习之路

 
 
 

日志

 
 

内核启动 之 [*] 选项的加载时机  

2010-08-16 16:02:18|  分类: Linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

 

\init\main.c中有函数static int init(void * unused)其中do_basic_setup();函数内容如下:

static void __init do_basic_setup(void)

{

         /* drivers will send hotplug events */

         init_workqueues();

         usermodehelper_init();

         driver_init();

#ifdef CONFIG_SYSCTL

         sysctl_init();

#endif

         do_initcalls();

}

 

其中的do_initcalls(void)所做的工作就是将在配置内核是标记为[*]的部分的初始化init函数全执行一遍

static void __init do_initcalls(void)

{

         initcall_t *call;

         int count = preempt_count();

         for (call = __initcall_start; call < __initcall_end; call++)

         {

                   char *msg;

                   if (initcall_debug)

                   {

                            printk(KERN_DEBUG "Calling initcall 0x%p", *call);

                            print_fn_descriptor_symbol(": %s()", (unsigned long) *call);

                            printk("\n");

                   }

                   (*call)();

                   msg = NULL;

                   if (preempt_count() != count)

                   {

                            msg = "preemption imbalance";

                            preempt_count() = count;

                   }

                   if (irqs_disabled())

                   {

                            msg = "disabled interrupts";

                            local_irq_enable();

                   }

                   if (msg)

                   {

                            printk(KERN_WARNING "error in initcall at 0x%p: ""returned with %s\n", *call, msg);

                   }

         }

         /* Make sure there is no pending stuff from the initcall sequence */

         flush_scheduled_work();

}

在写驱动的时候我们会使用module_init(sep4020fb_init);这种宏定义的形式,这其实就是告诉编译器,该初始化参数要被插入到__initcall_start和 __initcall_end间,__initcal__start之间是内核初始化函数指针列表,我们打开源码根目录下的System.map文件,找到__initcall_start和 __initcall_end

他们之间的就是初始化函数名,如下:

链接地址    初始化函数名

c001e7f8 T __initcall_start

c001e7fc t __initcall_consistent_init

………..

c001e8e0 t __initcall_init_nls_cp936

c001e8e4 t __initcall_init_nls_ascii

…….

c001e920 t __initcall_cfq_init

c001e924 t __initcall_fb_console_init

c001e928 t __initcall_sep4020fb_init

c001e92c t __initcall_rand_initialize

c001e930 t __initcall_tty_init

………

c001e994 t __initcall_init_mtd

c001e998 t __initcall_cmdline_parser_init

………

c001ea10 t __initcall_con_init

c001ea10 T __initcall_end

 

结论:

满足条件:

1、   使用module_init();宏定义了

2、   配置内核是标记为[*],即编译进内核

这时驱动初始化函数指针就会插入__initcall__start到__initcall_end段中,并在内核启动过程中,被/init/main.c文件中的do_initcalls()函数执行,从而实现启动内核驱动自动加载。

  评论这张
 
阅读(185)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017