Linu启动过程中硬件模块的加载

上传人:夏** 文档编号:498852077 上传时间:2023-04-05 格式:DOCX 页数:3 大小:13KB
返回 下载 相关 举报
Linu启动过程中硬件模块的加载_第1页
第1页 / 共3页
Linu启动过程中硬件模块的加载_第2页
第2页 / 共3页
Linu启动过程中硬件模块的加载_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

《Linu启动过程中硬件模块的加载》由会员分享,可在线阅读,更多相关《Linu启动过程中硬件模块的加载(3页珍藏版)》请在金锄头文库上搜索。

1、Linux 启动过程中硬件模块的加载Http:/www.fly-阅读Linux内核启动代码的直接动力是我想编写RTL8019AS的网卡驱动程序(2.4.18内核只 支持了 CS8900A)。既然要写驱动,我就想知道它是怎么样被加载的,好奇心驱使我先去搞 定这个问题。拿到2.4.18 的软件包,一万多个文件,我不知怎么下手。所幸手头有这么三件工具助我 入门:1,一块移植好linux的开发板,通过它可以看到linux启动过程打印的消息。2, google,网上关于linux的资料真是太多了!3, Windows文件搜索引擎,通过它可以知道在那些文件中打印出那些消息。很快,我就找到了 linux 启

2、动的总的入口,/arch/arm/boot/compressed/head.sohead.s完成的工作主要是底层寄存器、MMU的一些设定以及kernel的解压缩。汇编文件中 调用的C代码大多位于该目录下misc.c文件,比如decompress_kernel。当然,这部分不是重点,head执行完毕以后就跳到start_kernel(),这才是我们的重点所在, 这个函数位于文件/init/main.c中。这个文件是启动的主线!在start_kernel中,依次执行各个初始话函数,这里具体我没有看,一直到最后rest_init(), 在这个函数里启动了一个init线程,而主线程自己则进入了 IDL

3、E状态。所以我们关心一下 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

4、pending stuff from the initcall sequence */ flush_scheduled_tasks();很难相信,我们关心的外围模块的驱动就是被这一段程序加载的。怎么回事?我们慢慢来看:首先看initcall_start和_initcall_end,找遍了所有C代码,没有它们的定义。后来在 vmlinux-armv.lds.in文件中找到了它们:_initcall_start = .;*(.initcall.init)_initcall_end = .;这个文件是和link相关的文件,它决定代码在load环境中的位置,就好比ADS中的scf文件。我们还是先看.i

5、nitcall.init的含义吧,它在/include/linux/init.h中定义:#define _init_call _attribute_ (unused,_section_ (.initcall.init)参考GCC说明,这段话的意思就是说所有以_init_call前缀定义的函数在链接过程中都放到 名字为.initcall.init的段(section)里面。OK,有点味道了,也就是说,如果我们给一个函数 冠以init_call,那么它在编译链接的时候就会放到.initcall.init这个段里面。而上面这段循环 所做的事情就很清楚了,它从段的首地址开始,依次执行每一个函数,直到段

6、尾为止。这个时候,我们应该在想,那些要注册的外围模块的初始化程序是不是都是定义成_init_call 类型的呢?正如我们所料,查看各个模块我们会发现其初始化函数x会被定义成为 module_init(x),在/include/linux/init.h 中它定义如下:#define module_init(x) _initcall(x);#define _initcall(fn) static initcall_t _initcall_#fn _init_call = fn这段代码说modulenit(x)等价于initcall(x),而initcall(x)表示函数x是静态的具有init_ca

7、ll性质的函数(这里名字比较多,容易看乱),因此在链接时,它会被放在.initcall.init 段中。只要x函数运行起来了,那就可以注册设备、中断入口、中断服务函数了。接下来的事情就好办了搞清出设备如何被加载以后,我们还需要知道另外一个问题:怎样把一个模块的驱动程 序加载到内核里面呢? SO简单,make menuconfig,把对应设备打开。但是能不能再具体一 点呢,我们做这么一个改动,怎么映射到编译链接过程呢。我这个人就是喜欢找麻烦,因 此又在网上搜啊搜,而且用了最笨的方*,看看make menuconfig前后那些文件的修改日期 发生了变化。最终还是找到了一点,/scripts下的文件

8、是用来支持各种config模式的(当然 包括menuconfig),核心代码在Kconfig中。在每个驱动设备的文件夹下(比如net, mtd) 都有一个叫config.in的文件,这些文件定义了我们在menuconfig画面中看到的目录结构& 选项。眼睛看到的画面总归都是虚的,这些改动究竟反映到了哪里去了呢?两个文件:./config 和/include/linux/ autoconf.h。我们做完menuconfig以后,所有改动就反映到了这两个文件中, 这两个文件的内容是一致的。在我们做编译的过程中,顶层的makefile文件从autoconf.h文 件中读取各项宏定义然后传递给子一层的

9、makefile,这些makefile根据宏定义选择那些.o文 件被链接进来加到内核中。好了,知道这些我就知道怎么给8019添加驱动了, yy 一下:1, 首先要有驱动程序代码, 8019.c2, 修改 net 目录下的 config.in 文件中添加一项,dep_tristate RTL8019 support CONFIG_RTL8019 $CONFIG_ISA3, 打开menuconfig,将RTL8019 support选择y,保存推出后autoconf文件中应该就有了一个 宏定义: #define CONFIG_RTL80194, 打开net目录下的makefile,添加:obj-$( CONFIG_RTL8019) += 8019.o5, make dep; make zlmage;搞定!注:在menuconfig中选择m和y的区别:y:模块驱动编译到内核中,启动时自动加载m:模块会被编译,但是不会被编译到内核中,只是生成.o文件,我们可以收集这些.o文 件做到linux的文件系统中,然后用insmod实现动态加载。更多内容请登陆: http:/www.fly-

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号