阅读Linux内核启动代码的直接动力是我想编写RTL8019AS的网卡驱动程序(2.4.18内核只支持了CS8900A)。既然要写驱动,我就想知道它是怎么样被加载的,好奇心驱使我先去搞定这个问题。 拿到2.4.18的软件包,一万多个文件,我不知怎么下手。所幸手头有这么三件工具助我入门: 1,一块移植好Linux的开发板,通过它可以看到Linux启动过程打印的消息。 2, google,网上关于Linux的资料真是太多了!!! 3, Windows文件搜索引擎,通过它可以知道在那些文件中打印出那些消息。 很快,我就找到了Linux启动的总的入口,/arch/arm/boot/compressed/head.s。 head.s完成的工作主要是底层寄存器、MMU的一些设定以及kernel的解压缩。汇编文件中调用的C代码大多位于该目录下misc.c文件,比如decompress_kernel。 当然,这部分不是重点,head执行完毕以后就跳到start_kernel(),这才是我们的重点所在,这个函数位于文件/init/main.c中。这个文件是启动的主线!!! 在start_kernel中,依次执行各个初始话函数,这里具体我没有看,一直到最后rest_init(),在这个函数里启动了一个init线程,而主线程自己则进入了IDLE状态。所以我们关心一下init线程做了什么事情,看文件最后init函数。 在这个函数里面,先lock_kernel,然后调用do_basic_setup,在这个函数里面又是一堆的初始化,有一个函数要引起我们的注意:do_initcalls。看看它干了什么:(这之后的东西在下文文件系统中讲解)以下是代码片段:
static void __init do_initcalls(void)
{
initcall_t *call;
call = &__initcall_start;
do {
(*call)( );
call++;
} while (call < &__initcall_end);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_tasks();
}
很难相信,我们关心的外围模块的驱动就是被这一段程序加载的。怎么回事?我们慢慢来看: 首先看__initcall_start和__initcall_end,找遍了所有C代码,没有它们的定义。后来在vmLinux-armv.lds.in文件中找到了它们:以下是代码片段:
__initcall_start = .;
*(.initcall.init)
__initcall_end = .;
Teamviewer:支持 Linux 的远程协助工具谁说Linux下无游戏 Ubuntu下DOTA实战相关资讯 Linux内核
- IT人员必须了解的六项Linux内核变 (今 12:05)
- Linux 内核更新:3.10.98、3.14.62 (02月26日)
- Linux:让手机运行主线内核 (11/26/2015 22:16:17)
| - Linux内核自防护项目 (05月24日)
- Linux 内核架构的理解 (12/09/2015 09:01:01)
- Linux内核被指缺乏安全性 (11/07/2015 08:28:47)
|
本文评论 查看全部评论 (0)