以module_init(Demo_init);为例

定义文件:

include\linux\init.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结构体

linux驱动入口函数,你了解linux驱动的入口?相关推荐

  1. linux使用shell函数扩充命令,Linux Shell系列教程之(十五) Shell函数简介 | Linux大学...

    摘要 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高. 高级语言都支持函数,Shell也不例外.今天就为大家介绍下Shell中函数相关用法. 函数可以将一个复杂功能划 ...

  2. linux 创建线程函数吗,[笔记]linux下和windows下的 创建线程函数

    linux下和windows下的 创建线程函数 #ifdef __GNUC__ //Linux #include #define CreateThreadEx(tid,threadFun,args) ...

  3. linux驱动获取函数失败信息,linux驱动调试--段错误之栈信息分析

    接着上一篇来分析一下Oops的栈 s3c2440平台 关于调试源码和整个Oops信息请参考上一篇博文,这里只再次贴出关于栈的信息 Stack: (0xc3a61e30 to 0xc3a62000) 1 ...

  4. Linux系统常用函数,浅谈linux下的一些常用函数的总结(必看篇)

    1.exit()函数 exit(int n)  其实就是直接退出程序, 因为默认的标准程序入口为int main(int argc, char** argv),返回值是int型的. 一般在shell下 ...

  5. linux文件字节函数,各位大侠:linux/unix下有什么双字节的字符类型及其一整套处理函数? 高分送出,请帮帮小弟!!!!!!...

    linux/unix下小弟需要操作双字节,相对单字节char 有什么双字节的字符类型及其一整套处理函数,如strstr(),strcpy(),strchr等功能相同的双字节操作函数,它用到什么头文件? ...

  6. linux用Lseek函数 拷贝文件,linux系统下lseek函数的详细用法

    前面的文章里面,仔细讲了在linux系统对文件的读写操作以及文件管理,为今天要讲的内容作了铺垫(如果您是刚接触这方面的内容,可以先看我之前写的文章,有错误的地方,还望指出来,在这里先说一声谢谢).好了 ...

  7. linux c sync函数,怎么在Linux中调用fsync函数

    Linux中如何调用fsync函数?针对这个问题,本文详细介绍了相应的分析和解决方法,希望能帮助更多想解决这个问题的伙伴找到更简单易行的方法. 功能描述: 将内存中所有已修改的文件数据同步到存储设备. ...

  8. linux中read函数的用法,Linux中read命令的简介及使用方法

    Linux中read命令的简介及使用方法 发布时间:2020-08-17 16:40:04 来源:亿速云 阅读:107 作者:小新 这篇文章给大家分享的是有关Linux中read命令的简介及使用方法的 ...

  9. Linux中append函数的用法,linux C代码 open函数参数:O_APPEND问题求助

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 没有截图,直接上代码吧. 原代码是这样的: #include #include #include #include #include int main() ...

最新文章

  1. Upload Picture to application server
  2. 如何在ubuntu 12.04系统下开启nfs网络文件系统
  3. Touch Driver介绍
  4. linux新的API signalfd、timerfd、eventfd使用说明——eventfd
  5. 一篇英文文档中找出频数最多的10个单词
  6. php导出csv文件乱码问题解决方法
  7. Multi-thread--C++11中std::mutex的使用
  8. C++ 链表入门习题
  9. [xsy2282]cake
  10. 中国·哈尔滨国际友好城市冰雪汽车挑战赛开赛
  11. qq怎样发起临时会话(不加好友)
  12. 【面试常问】Redis的持久化机制是什么?各自的优缺点?
  13. 三星note10安装linux,三星Note10/Note10+新款Dex已支持Win10/macOS
  14. 修改计算机名无法共享打印机,打印机设置共享以及共享时无法连接,报错0X00000006解决方法...
  15. Linux 进程查看命令 ps top htop dstat
  16. NIO编程--聊天室Demo
  17. 【小程序】常见系统API | 页面分享 | 位置信息 | 本地存储
  18. 考研高危人群!你是否还在危险的边缘试探?
  19. 单链表的定义、特点、结构及其一些基本操作
  20. 自定义小部件Widget的探讨

热门文章

  1. PyQt5 按钮QSS美化集
  2. 【学习记录贴】Vue+Element-UI富文本编辑框及插入图片
  3. 生存危机,末日血战、末日危机攻略之英雄升级升星,每周活动详细说明
  4. 亚马逊Listing没有销量的这些原因卖家们知多少?
  5. Polyworks脚本开发学习笔记(二十)-补充几个常见操作指令的使用
  6. GY-MCU90615 非接触式体温传感器
  7. Beckhoff倍福EtherCAT IO端子类型简介
  8. 一篇还不错的介绍make的文章
  9. 布局优化工具Hierarchy Viewer
  10. 解题报告 之 SOJ3353 Total Flow