以module_init(demo_init);为例
定义文件:
includelinuxinit.h
#define module_init(x)__initcall(x);
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn)__define_initcall(6,fn,6)
#define __define_initcall(level,fn,id)
static initcall_t __initcall_##fn##id __attribute_used__
__attribute__((__section__(.initcall level .init))) = fn
展开为
static initcall_t __initcall_demo_init6 __attribute_used____attribute__((__section__(.initcall6.init))) =demo_init;
typedef int (*initcall_t)(void);
这里
typedef int (init_fnc_t)(void); 定义一种函数类型
typedef int (*init_fnc_t) (void); 定义一种类型的函数指针
所以展开的宏定义就是定义名为__initcall_demo_init6的函数指针
属性有两个:
1.
在gcc 3.4之前的编译器被展开成__attribute__((unused))来禁止编译器弹出有关函数没有被用到的的警告信息
在gcc 3.4之后被展开成__attribute__((used))功能一样
2.加载到段.initcall6.init,其地址为demo_init的地址
段的分布顺序在链接脚本中有
编译内核后,会有vmlinux.lds的打印信息,里面有各段位置
__initcall_start = .;
*(.initcallearly.init) __early_initcall_end = .;
*(.initcall0.init)
*(.initcall0s.init)
*(.initcall1.init)
*(.initcall1s.init)
*(.initcall2.init)
*(.initcall2s.init)
*(.initcall3.init)
*(.initcall3s.init)
*(.initcall4.init)
*(.initcall4s.init)
*(.initcall5.init)
*(.initcall5s.init)
*(.initcallrootfs.init)
*(.initcall6.init)
*(.initcall6s.init)
*(.initcall7.init)
*(.initcall7s.init)
__initcall_end = .;
当insmod的时候,内核从initcall6.init段中读取到驱动入口地址,然后跳转到该地址去执行入口函数,
一般入口函数会进行注册驱动,例如
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
usb_register(struct usb_driver * driver)
spi_register_driver(struct spi_driver * sdrv)
等等注册函数,再依次调用相应设备结构体中的ioctl或者直接调用file_operations结构体
整流与滤波电路
GBFC全球化金融生态是互联网时代的下个风口
智能传感器技术基于相应动作的生物移动
基于四相序列扩频传输系统设计与分析讲解
DALI2.1调光解码模块使用手册
你了解linux驱动的入口?
mc34063升压电路
村田制作所在智能LED照明领域的浅析
打游戏用什么蓝牙耳机比较好,高性价比游戏耳机的推荐
基于电磁涡流检测的远洋船舶冷水机组探伤检测与优化管理
高通正在寻求扩大苹果禁售令的范围以覆盖最新型号的iPhone
小鹏汽车第三季度净亏损11.49亿元
微星发布全新的GS75 Stealth游戏本 兼顾高性能和便携性
关于变压器油氧化安定性的简单说明
探析各大巨头的V2X技术研发进展
天津大学张雷、杨静教授团队成功研发出“全天候”自愈合材料
紫光推出P5160系列SSD,随机读取速度最高为320K IOPS
2019年电信行业整体增速放缓,未来创新电信业务拉动增长
芯片引脚的功能和用途
VME总线原理、特点、功能结构及发展分析