內核調用__init函數的順序

本文详细解析了Linux内核初始化过程中__init函数的作用与调用顺序。解释了这些函数如何根据不同的区段定义来确定其调用时机,并介绍了2.6内核中新引入的7个子区段及各自的用途。

參見include/linux/init.h和vmlinux.lds

1)
所有標識為__init的函數在鏈接的時候都放在.init.text這個區段內,
在這個區段中,函數的擺放順序是和鏈接的順序有關的,是不確定的。

2)
所有的__init函數在區段.initcall.init中還保存了一份函數指針,
在初始化時內核會通過這些函數指針調用這些__init函數指針,
並在整個初始化完成後,釋放整個init區段(包括.init.text,.initcall.init等),

注意,這些函數在內核初始化過程中的調用順序只和這裡的函數指針的順序有關,
和1)中所述的這些函數本身在.init.text區段中的順序無關。

在2.4內核中,這些函數指針的順序也是和鏈接的順序有關的,是不確定的。

在2.6內核中,initcall.init區段又分成7個子區段,分別是
.initcall1.init
.initcall2.init
.initcall3.init
.initcall4.init
.initcall5.init
.initcall6.init
.initcall7.init

當需要把函數fn放到.initcall1.init區段時,只要聲明
core_initcall(fn);
即可。

其他的各個區段的定義方法分別是:
core_initcall(fn) --->.initcall1.init
postcore_initcall(fn) --->.initcall2.init
arch_initcall(fn) --->.initcall3.init
subsys_initcall(fn) --->.initcall4.init
fs_initcall(fn) --->.initcall5.init
device_initcall(fn) --->.initcall6.init
late_initcall(fn) --->.initcall7.init

而與2.4兼容的initcall(fn)則等價於device_initcall(fn)。

各個子區段之間的順序是確定的,即先調用.initcall1.init中的函數指針
再調用.initcall2.init中的函數指針,等等。
而在每個子區段中的函數指針的順序是和鏈接順序相關的,是不確定的。

在內核中,不同的init函數被放在不同的子區段中,因此也就決定了它們的調用順序。
這樣也就解決了一些init函數之間必須保證一定的調用順序的問題。

3)
這些順序和make dep沒有關係。

`rte_eal_init` 是 DPDK(Data Plane Development Kit)中的一个核心函数,主要用于初始化 EAL(Environment Abstraction Layer,环境抽象层)。EAL 提供了一组统一的接口,屏蔽了底层操作系统的差异性,使得 DPDK 应用可以在多种平台上运行。该函数在任何 DPDK 应用程序中都必须被调用,并且通常作为程序启动时的第一个 DPDK API 调用[^1]。 ### 作用 - **初始化硬件资源**:包括 CPU、内存(尤其是大页内存 hugepages)、PCIe 设备等。 - **配置多进程支持**:通过命令行参数可以指定当前进程是主进程(primary)还是从进程(secondary),以支持共享内存和多进程通信[^2]。 - **设置日志系统**:为后续的日志输出提供基础。 - **注册信号处理**:确保在程序异常退出时能够正确释放资源。 - **初始化线程模型**:根据配置创建 lcore(逻辑核心)并绑定线程。 ### 使用方法 `rte_eal_init` 函数原型如下: ```c int rte_eal_init(int argc, char **argv); ``` 它接受标准的 `main` 函数参数,并返回处理后的参数数量。未被 EAL 处理的参数将传递给应用程序使用。 #### 示例代码 ```c #include <rte_eal.h> #include <rte_exit.h> int main(int argc, char *argv[]) { int ret; // 初始化 EAL ret = rte_eal_init(argc, argv); if (ret < 0) { rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); } argc -= ret; argv += ret; // 在此处添加其他 DPDK 初始化代码或业务逻辑 return 0; } ``` #### 常见命令行参数 - `-c COREMASK` 或 `--lcores=COREMASK`: 指定使用的逻辑核心掩码。 - `-n NUM` 或 `--socket-mem=NUM,NUM,...`: 分配每个 socket 上的大页内存大小。 - `--proc-type=auto|primary|secondary`: 设置进程类型,用于多进程场景。 - `--file-prefix`: 指定共享内存文件前缀,用于区分不同实例。 ### 注意事项 - 必须在调用任何其他 DPDK 函数之前调用 `rte_eal_init`。 - 应用程序应检查其返回值以确认是否成功初始化。 - 需要 root 权限来挂载大页内存并访问 PCIe 设备。 - 不同平台可能需要不同的内核模块加载和 BIOS 设置,如启用 VT-d/IOMMU 等功能。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值