0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

Q4MP_gh_c472c21 2018-02-05 10:07 次阅读

__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
    +关注

    关注

    87

    文章

    11227

    浏览量

    208920

原文标题:嵌入式Linux内核中_init,_exit中的作用

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux内核源代码漫游

    Linux内核源代码漫游 本章试图以顺序的方式来解释Linux源代码,以帮助读者对源代码的体系结构以及很多相关的unix特性的实现有一个很
    发表于 02-09 15:27 26次下载

    Linux源代码简介

     Linux源代码简介欢迎进入Linux的世界!随着人们对开放源代码软件热情的不断高涨,Linux也受到了越来越多的关注。
    发表于 02-10 13:54 78次下载

    kernel 汇编实时运行核心的汇编源代码

    kernel 汇编实时运行核心的汇编源代码.rar /*Listing 1      Scheduling Algorithm(C
    发表于 02-25 15:48 6次下载

    Linux内核源代码漫游

    本章试图以顺序的方式来解释Linux源代码,以帮助读者对源代码的体系结构以及很多相关的unix特性的实现有一个很好的理解。目标是帮助对Linux不甚了解的有经验的C程序员对整个
    发表于 04-03 20:26 57次下载

    Linux0.11源代码0.11

    Linux0.11源代码配合《Linux 0.11 源代码完全分析0.11》一起学习,很好的资料
    发表于 10-30 17:14 24次下载

    怎样去读Linux内核源代码

    怎样去读Linux内核源代码
    发表于 10-25 10:15 13次下载
    怎样去读<b class='flag-5'>Linux</b>内核<b class='flag-5'>源代码</b>

    linux kernel工作队列及源码解析

    1. 前言 工作队列(workqueue)的Linux内核定义的用来处理不是很紧急事件的回调方式处理方法。 以下代码linux内核版本
    发表于 10-27 10:19 0次下载

    linux kernel工作队列及源码详细讲解

    1. 前言 工作队列(workqueue)的Linux内核定义的用来处理不是很紧急事件的回调方式处理方法. 以下代码linux内核版本
    发表于 11-30 17:43 588次阅读

    Linux操作的防火墙软件应用程序定义和配置设置及底层源代码

    虽然一般PC用户有许多免费的防火墙软件应用程序,但Linux操作系统的最大优势之一是它们能够自定义和配置设置和底层源代码
    的头像 发表于 07-17 10:19 5151次阅读

    Linux应用程序PING的源代码免费下载

    本文档的主要内容详细介绍的是Linux应用程序PING的源代码免费下载。
    发表于 10-18 17:46 13次下载

    ARM Linux中一些重要及地址定义

    ARM Linux中一些重要及地址定义
    的头像 发表于 06-22 17:02 2699次阅读

    基于Android的Linux内核的电源管理:概述

    1.电源管理的状态Android的Linux内核为系统提供了4种电源状态,内核的源代码为其中的3种定义了名字和对应的定义,名字
    发表于 01-07 11:14 6次下载
    基于Android的<b class='flag-5'>Linux</b>内核的电源管理:概述

    如何选择合适的工具来阅读源代码

    在做嵌入式 Linux 软件开发的时候,经常会阅读大型工程源码,比如 uboot 源代码Linux Kernel 源码等。
    的头像 发表于 03-30 14:01 1147次阅读

    linux内核源代码详解

     在安装好的Linux系统,内核的源代码位于/ust/src/linux.如果是从GNU网站下载的Linux内核的tar文件,则展开以后在
    发表于 09-06 17:01 4次下载

    SVdefine定义的用法

    SV中使用预处理指令`define来定义可以用来创建文本替换。根据场景不同,`define主要用来定义常量、简化复杂的表达式或代码
    的头像 发表于 10-21 14:22 303次阅读