当前位置: 首页 > 科技观察

Linux驱动挂载顺序分析

时间:2023-03-13 00:09:04 科技观察

本文转载自微信公众号《嵌入式Linux系统开发》,作者Jasonangel。转载本文请联系嵌入式Linux系统开发公众号。教你分析Linux的启动过程。由上可知,start_kernel函数最终调用了rest_init函数。事实上,rest_init函数不仅会产生最重要的kernel_init(PID=1)和kthreadd(PID=2)内核进程。kernel_init最终演变成用户空间init进程(PID=1)。rest_init函数还有一个重要的分支:加载驱动模块,调用过程如下:start_kernel|--->rest_init|--->kernel_init|--->kernel_init_freeable|--->do_basic_setup|--->driver_init|--->do_initcalls|--->do_initcall_level|--->do_one_initcall注意,这里是驱动的初始化和驱动模块的加载。我们知道在rest_init函数中,最重要的1号和2号进程已经启动了,也就是说系统真正启动了。在1号和2号进程启动之前,在调用rest_init函数之前挂载了文件系统,此时加载驱动是可能的。那么它是如何安装在这里的呢?进程中的driver_init函数对每个驱动入口函数进行初始化,即在内存中寻址驱动初始化函数。在do_initcalls函数中,驱动会根据驱动的优先级逐一挂载。linux4.14/init/main.c驱动的优先级:linux将系统中需要挂载的各种东西分为14个等级,分别是1--1s--2--2s--3--3s--4--4s--5--5s--6--6s--7--7s,数字越小优先级越高,定义在:linux4.14/include/linux/init.h一般我们对于自己写的驱动模块,文件最后会声明一个module_init和module_exit,实际上定义为device_initcall,优先级为6,低于架构初始化模块和文件系统模块。如果驱动模块之间存在依赖关系,则需要更改模块安装顺序。有3种方式:1.加一个优先级,比如8。或者声明自己的驱动模块为另一个优先级,即不用module_init来声明,可以用fs_initcall来声明。2、对于优先级相同的驱动模块,可以在Makefile中改变编译和链接的顺序,加载顺序就会调换。(静态编译)3、动态加载驱动模块:Linux系统启动后,手动执行insmod和rmmod来挂载和卸载驱动,顺序自行决定。测试成功后,会在内核中进行静态编译。虽然可以改变挂载顺序,但还是希望大家在写驱动模块的时候,能够做到高内聚、低耦合。自己的模块最好不要依赖其他模块,以免其他模块加载失败导致自己的模块不可用。如何查看驱动挂载顺序?有两种方法:1.找到编译好的Linux内核源码,根目录下有一个System.map文件,里面依次记录了Linux内核做的所有事情(也可能在其他输出目录)。共有三列:地址、区域、操作。在运行中我们可以看到我们声明的驱动的名称。2、如果你的驱动模块添加了一些打印,可以直接查看log。