linux kernel中的module_init/initcall代码导读
文章目录
- 1、initcall的分类
- 2、__initcall的调用
- 3、module_driver/module_i2c_driver
★★★ 友情链接 : 个人博客导读首页—点击此处 ★★★
1、initcall的分类
在kernel/include/linux/module.h中
#define module_init(x) __initcall(x);
在kernel/include/linux/init.h中,定义了一堆宏
#define pure_initcall(fn) __define_initcall(fn, 0)
#define core_initcall(fn) __define_initcall(fn, 1)
#define core_initcall_sync(fn) __define_initcall(fn, 1s)
#define postcore_initcall(fn) __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn) __define_initcall(fn, 3)
#define arch_initcall_sync(fn) __define_initcall(fn, 3s)
#define subsys_initcall(fn) __define_initcall(fn, 4)
#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)
#define fs_initcall(fn) __define_initcall(fn, 5)
#define fs_initcall_sync(fn) __define_initcall(fn, 5s)
#define rootfs_initcall(fn) __define_initcall(fn, rootfs)
#define device_initcall(fn) __define_initcall(fn, 6)
#define device_initcall_sync(fn) __define_initcall(fn, 6s)
#define late_initcall(fn) __define_initcall(fn, 7)
#define late_initcall_sync(fn) __define_initcall(fn, 7s)#define __initcall(fn) device_initcall(fn)
其实对应的就是就是".initcall0.init ~ .initcall7.init"的__section__段
#define __define_initcall(fn, id) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(".initcall" #id ".init"))) = fn; \LTO_REFERENCE_INITCALL(__initcall_##fn##id)
我们再总结下,module_init(xxx_init)其实就是在.initcall6.init的__section__段中分配一个地址,指向xxx_init函数
而__section__段的定义在vmlinux.ld.S的INIT_CALLS中
.init.data : {
INIT_DATA
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS
}
INIT_CALLS是定义在vmlinux.ld.h的一个宏
#define INIT_CALLS_LEVEL(level) \VMLINUX_SYMBOL(__initcall##level##_start) = .; \*(.initcall##level##.init) \*(.initcall##level##s.init) \
#define INIT_CALLS \VMLINUX_SYMBOL(__initcall_start) = .; \*(.initcallearly.init) \INIT_CALLS_LEVEL(0) \INIT_CALLS_LEVEL(1) \INIT_CALLS_LEVEL(2) \INIT_CALLS_LEVEL(3) \INIT_CALLS_LEVEL(4) \INIT_CALLS_LEVEL(5) \INIT_CALLS_LEVEL(rootfs) \INIT_CALLS_LEVEL(6) \INIT_CALLS_LEVEL(7) \VMLINUX_SYMBOL(__initcall_end) = .;
这些section段的地址是:
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
2、__initcall的调用
在kernel/init/main.c中:
依次循环调用了这些section段的函数
static initcall_t *initcall_levels[] __initdata = {__initcall0_start,__initcall1_start,__initcall2_start,__initcall3_start,__initcall4_start,__initcall5_start,__initcall6_start,__initcall7_start,__initcall_end,
};static void __init do_initcall_level(int level)
{initcall_t *fn;strcpy(initcall_command_line, saved_command_line);parse_args(initcall_level_names[level],initcall_command_line, __start___param,__stop___param - __start___param,level, level,NULL, &repair_env_string);for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)do_one_initcall(*fn);
}static void __init do_initcalls(void)
{int level;for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)do_initcall_level(level);
}int __init_or_module do_one_initcall(initcall_t fn)
{int count = preempt_count();int ret;char msgbuf[64];if (initcall_blacklisted(fn))return -EPERM;if (initcall_debug)ret = do_one_initcall_debug(fn);elseret = fn();msgbuf[0] = 0;if (preempt_count() != count) {sprintf(msgbuf, "preemption imbalance ");preempt_count_set(count);}if (irqs_disabled()) {strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));local_irq_enable();}WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf);return ret;
}
static bool __init_or_module initcall_blacklisted(initcall_t fn)
{struct list_head *tmp;struct blacklist_entry *entry;char *fn_name;fn_name = kasprintf(GFP_KERNEL, "%pf", fn);if (!fn_name)return false;list_for_each(tmp, &blacklisted_initcalls) {entry = list_entry(tmp, struct blacklist_entry, next);if (!strcmp(fn_name, entry->buf)) {pr_debug("initcall %s blacklisted\n", fn_name);kfree(fn_name);return true;}}kfree(fn_name);return false;
}
3、module_driver/module_i2c_driver
在device.h中:
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
在i2c.h中
#define module_i2c_driver(__i2c_driver) \module_driver(__i2c_driver, i2c_add_driver, \i2c_del_driver)
linux kernel中的module_init/initcall代码导读相关推荐
- linux kernel中local_irq_disable()、local_irq_enable()代码解读
在armv8-arch64架构下,控制cpu是否响应IRQ,FIQ,SERROR,DEBUG中断,是由PSTATUS(daif寄存器)控制的. 在armv8-arch32或armv7架构下,控制cpu ...
- Linux kernel 中模块化的平台驱动代码介绍
介绍 在linux kernel中通过module_platform_driver来实现模块化平台驱动.大量的设备驱动程序都基于该种方式来实现,使用频次非常的高,在linux kernel 5.4.1 ...
- linux kernel中的栈的介绍
目录 1.linux kernel中的中断irq的栈stack (1).arm32体系的irq的栈 (2).arm64体系的irq的栈 2.linux kernel中的栈stack (1).概念介绍: ...
- linux kernel中的进程栈
1.linux中的user mode的进程栈 在thread_info.h中,设置进程栈的大小为16k #define THREAD_SIZE 16384 #define THREAD_START_S ...
- Linux kernel中常见的宏整理
0x00 宏的基本知识 // object-like #define 宏名 替换列表 换行符 //function-like #define 宏名 ([标识符列表]) 替换列表 换行符 替换列表和标识 ...
- 内存访问顺序 - part2: 屏障及Linux kernel中屏障的使用
文章目录 屏障是什么 Linux Kernel 中的屏障 Linux 屏障 API 一般的屏障 强制性屏障 SMP 条件屏障 隐式屏障 其他屏障 屏障的开销 未来的文章 本文翻译自 Memory ac ...
- Linux Kernel中AEP的现状和发展
阿里 石洋内核月谈Yesterday AEP简介 AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP.在这之前也有类似的设备 ...
- linux kernel中的virt_to_phys代码解读
假设VA_BITS = 48 (虚拟地址有效位), 那么kernel space的虚拟地址是:0xffff_0000_0000_0000 - 0xffff_ffff_ffff_ffff, usersp ...
- linux kernel中cache代码解读
1. 在kernel中调用__dma_flush_range,底层是如何操作的呢? /* remove any dirty cache lines on the kernel alias */__dm ...
最新文章
- python中的类的成员变量以及property函数
- 网络推广软件介绍外链坚持七大原则助力网站排名“蹭蹭上涨”!
- PyTorch max()函数取最大值
- 用的fileupload组件实现的大文件上传
- CNN 手写数字识别
- 春节档总票房突破50亿元 《流浪地球》独占16亿!
- 基于selenium的钓鱼工具:关于ReelPhish神器的使用
- 1.13 Linux创建与删除用户
- php如何输入错误返回,php – 从函数返回“错误”的最佳做法
- 初中会考计算机flash,初中信息技术考试flash.doc
- 如何用一束激光欺骗神经网络
- cad里面f命令用不了_cad命令_CAD命令中 F 命令是什么作用?
- 弹幕游戏:Ryan 最近迷上了弹幕游戏。所谓弹幕游戏,指的是玩家操控一位角色对来袭的大量敌人进行攻击,并在过程中升级、强化自我的能力,最终打败 Boss 的一类游戏...
- Helm模版开发文档
- 智能空气净化器解决方案,飞睿科技无线WiFi芯片模块技术应用
- 如何保障微服务架构下的数据一致性
- mycat连接数据库8.0以上 处理程序连接query_cache_size报错信息 mycat升级数据库踩坑
- 【域渗透提权】CVE-2020-1472 NetLogon 权限提升漏洞
- windows防火墙开启后,设置准入端口
- BeyondCompare4 破解方法
热门文章
- 数据中心水冷系统备品备件管理新思路
- UPS远程监控系统的设计与实现
- 探讨计算机房的防火安全
- 成功解决matplotlib绘图的时候,自定义横坐标和纵坐标刻度数值(调整坐标轴刻度间隔)
- Python之pyecharts:利用pyecharts绘制地图十多个地区流动轨迹动态图
- 成功解决TypeError: 'float' object cannot be interpreted as an integer
- Funny:还是程序猿会玩——弹幕炸天学AI和区块链,玩起来!弹慕君,你也值得拥有!
- 自定义服务器控件ImageButton
- python3 获取cookie解决方案
- jQuery on()方法绑定动态元素的点击事件无效