__init, __initdata等属性标志,是要把这种属性的代码放入目标文件的.init.text节,数据放入.init.data节──这一过程是通过编译内核时为相关目标平台提供了xxx.lds链接脚本来指导ld完成的。

对编译成module的代码和数据来说,当模块加载时,__init属性的函数就被执行;

对静态编入内核的代码和数据来说,当内核引导时,do_basic_setup()函数调用do_initcalls()函数,后者负责所有.init节函数的执行。

在初始化完成后,用这些关键字标识的函数或数据所占的内存会被释放掉。

1)所有标识为__init的函数在链接的时候都放在.init.text这个区段内,,"__init"仅告诉kernel,此函数仅在初始化阶段使用,使用后所占用的内存资源会释放

在这个区段中,函数的摆放顺序是和链接的顺序有关的,是不确定的。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

(参见include/linux/init.h和vmlinux.lds )当需要把函数fn放到.initcall1.init区段时,只要声明core_initcall(fn);即可。其他的各个区段的定义方法分别是:

core_initcall(fn) --->.initcall1.initpostcore_initcall(fn) --->.initcall2.initarch_initcall(fn) --->.initcall3.initsubsys_initcall(fn) --->.initcall4.initfs_initcall(fn) --->.initcall5.initdevice_initcall(fn) --->.initcall6.initlate_initcall(fn) --->.initcall7.init

而与2.4兼容的initcall(fn)则等价于device_initcall(fn)。各个子区段之间的顺序是确定的,即先调用.initcall1.init中的函数指针再调用.initcall2.init中的函数指针,等等。而在每个子区段中的函数指针的顺序是和链接顺序相关的,是不确定的。在内核中,不同的init函数被放在不同的子区段中,因此也就决定了它们的调用顺序。这样也就解决了一些init函数之间必须保证一定的调用顺序的问题。

2. Linux Kernel源代码中与段有关的重要宏定义

A. 关于__init、__initdata、__exit、__exitdata及类似的宏

打开Linux Kernel源代码树中的文件:include/init.h,可以看到有下面的宏定议:

#define __init __attribute__ ((__section__ (".init.text"))) __cold

#define __initdata __attribute__ (( __section__ (".init.data")))

#define __exitdata __attribute__ (( __section__ (".exit.data")))

#define __exit_call __attribute_used__ __attribute__ (( __section__ (".exitcall.exit")))

#define __init_refok oninline __attribute__ ((__section__ (".text.init.refok")))

#define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))

#define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok")))

.........

#ifdef MODULE

#define __exit __attribute__ (( __section__ (".exit.text"))) __cold

#else

#define __exit __attribute_used__ __attribute__ ((__section__ (".exit.text"))) __cold

#endif

对于经常写驱动模块或翻阅Kernel源代码的人,看到熟悉的宏了吧:__init, __initdata, __exit, __exitdata。

__init 宏最常用的地方是驱动模块初始化函数的定义处,其目的是将驱动模块的初始化函数放入名叫.init.text的输入段。当内核启动完毕后,这个段中的内存会被释放掉供其他使用。

__initdata宏用于数据定义,目的是将数据放入名叫.init.data的输入段。其它几个宏也类似。

另外需要注意的是,在以上定意中,用__section__代替了section。还有其它一些类似的宏定义,这里不一一列出,其作用都是类似的。

模块加载分为动态加载和静态加载。

所谓静态加载就是,开机加载系统时将模块加载上去,这就是编译进内核。

而动态加载就是在开机以后将模块加载上去,这就是编译成模块!

init_module是默认的模块的入口,如果你想指定其他的函数作为模块的入口就需要module_init函数来指定,比如

module_init (your_func);

其中your_func是你编写的一个函数的名称.

init_module()是真正的入口,module_init是宏,如果在模块中使用,最终还是要转换到init_module()上。

如果不是在模块中使用,module_init可以说没有什么作用。总之,使用module_init方便代码在模块和非模块间移植。

Linux内核代码宏定义,Linux Kernel源代码中与段有关的重要宏定义相关推荐

  1. Linux内核代码风格

    Linux内核代码风格 这是一个简短的文档,描述了linux内核的首选代码风格.代码风格是因人而异的,而且我不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望 ...

  2. linux内核源码只有makefile文件没有c文件,linux内核代码的编写初步以及makefile的配置...

    在linux内核代码开发中,头文件不能包含标准C头文件,只能采用GNC标准 而且内核开发中没有main函数,只有init 和 exit ,这是每个内核模块中必须要包含的函数模块. 在GNU C标准中, ...

  3. Ubuntu14.04搭建LXR本地服务器阅读Linux内核代码

    CSDN GitHub Ubuntu14.04搭建LXR本地服务器阅读Linux内核代码 AderXCoding/system/tools/lxr 本作品采用知识共享署名-非商业性使用-相同方式共享 ...

  4. Linux 内核代码行数达到 2700 万行量级

    来自:技术让梦想更伟大 截止到2020年1月1日09:00:10,Linux内核Git源码树中的代码达到了2780万行. phoronix网站统计了Linux内核在进入2020年时的一些源码数据并作了 ...

  5. linux 内核编号含义_如何阅读linux内核代码?

    阅读代码从来就是不可行的方法,有篇文章详细讲了这个事,很多人都觉得应该多读代码, 读好的代码,比如Donald Knuth. 但事实上, 只要简单让你描述一下最近读了什么代码,绝大多数人都说不上.文章 ...

  6. 最小的linux内核代码,带你阅读linux内核源码:下载源码、编译内核并运行一个最小系统...

    要学习linux内核,先要能够编译内核,还需要了解内核如何启动根文件系统.这样你才能在修改linux内核代码之后,完成验证的过程. 本文教你完成下列过程: 1.下载linux并编译linux内核源码 ...

  7. 谷歌喊话三星:别再搞 Linux 内核代码了,安卓安全也不保了

    聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 谷歌 Project Zero 团队表示,三星为阻止 Galaxy 手机遭攻击而修改了内核代码,但实际上引发了更多的安全漏洞. 谷歌安全 ...

  8. Linux内核代码华人贡献统计

    http://www.remword.com/kps_result/ 这个站点对Linux内核代码补丁进行了详细的统计,感兴趣的童鞋可以看一下. 在这里给大家看一下2005年4月16日至今各个国家贡献 ...

  9. linux内核 lts长期演进,Linux Kernel 4.19 将成为下一个LTS(长期支持)系列

    最近Linux内核开发人员和维护人员Greg Kroah-Hartman透露,Linux Kernel 4.19将下一个长期支持的Linux内核系列. 现在Linux Kernel 4.17已经达到使 ...

最新文章

  1. 所有机器学习项目都适用的检查清单
  2. layui如何集成文件服务器,layui使用upload组件实现文件上传功能
  3. Exception Handling Best Practices in .NET
  4. centOS安装java
  5. Spring Cloud 参考文档(Spring Cloud Context:应用程序上下文服务)
  6. Eclipse启动SpringCloud微服务集群的方法
  7. 浅谈APP与H5对比!优势都有哪些呢?
  8. 51c语言编程入门教程,51单片机C语言入门教程
  9. JAVA获取硬盘序列号
  10. Java编写MD5加密工具类,登录密码加密
  11. 人生没有退路,你所有遇到过的人,做过的事都不是偶然,一念天堂一念地狱
  12. 我的留英日记[转载]
  13. win11提示找不到gpedit.msc命令
  14. 如何制作全景图片,VR全景制作流程解析
  15. 获取Windows操作系统版本和位数
  16. Unity3D: 精灵更换图片脚本实现
  17. EasyRecovery是最好用的手机数据恢复工具
  18. 紧随小米2:LG Optimus G也用高通四核APQ8064
  19. C语言十个数中求出平均值
  20. 【转载】选择性搜索算法介绍——Selective Search

热门文章

  1. App数据统计分析:快速提升运营分析能力
  2. 未来十年计算机发展方向,笔记本电脑在未来十年的发展方向
  3. 陆奇首次出手投资量子计算
  4. 网易html5,可拖曳附件 网易邮箱国内首家支持HTML5
  5. 计算机接口中的shl,西门子200的PLC中SHL和ROL的区别,还...-卓优商学问答
  6. Android: 3G上网的基本原理及RILD进程的流程分析
  7. 使用colab训练faster-rcnn pytorch版(代码来源:霹雳吧啦Wz)
  8. 知乎宣布完成2.7亿美元融资 引入前蜜芽合伙人孙伟为CFO
  9. CnOpenData中国各省份工商注册企业分年份数量统计(含新增,注销企业数量)
  10. 领导给我一堆无序、杂乱的数据,我写了一个Python自动化脚本!