ZZ FROM:

http://blog.csdn.net/musein/article/details/742609

==================================================

The __init and __exit declarations are special kernel macros designed to tell the kernel to flag these

functions for special handling in cases where they are compiled in statically rather than included as

parts of modules.

 The __init declaration allows the kernel to reclaim the space used by initialization

functions, while the __exit declaration tells the kernel to just plain ignore the function altogether. If

you’re only going to write your device driver as a module, with no possibility that it will be included

statically, it is perfectly safe to leave these special declarations out.



1 __init:



/* These macros are used to mark some functions or

 * initialized data (doesn't apply to uninitialized data)

 * as `initialization' functions. The kernel can take this

 * as hint that the function is used only during the initialization

 * phase and free up used memory resources after

 *

 * Usage:

 * For functions:

 *



 * You should add __init immediately before the function name, like:

 *

 * static void __init initme(int x, int y)

 * {

 *    extern int z; z = x * y;

 * }

 *

 * If the function has a prototype somewhere, you can also add

 * __init between closing brace of the prototype and semicolon:

 *

 * extern int initialize_foobar_device(int, int, int) __init;

 *

 * For initialized data:

 * You should insert __initdata between the variable name and equal

 * sign followed by value, e.g.:

 *

 * static int init_variable __initdata = 0;

 * static char linux_logo[] __initdata = { 0x32, 0x36, ... };

 *

 * Don't forget to initialize data not at file scope, i.e. within a function,

 * as gcc otherwise puts the data into the bss section and not into the init

 * section.

 *

 * Also note, that this data cannot be "const".



其主要作用是初始化.



2)module_init:

/**

 * module_init() - driver initialization entry point

 * @x: function to be run at kernel boot time or module insertion

 *

 * module_init() will add the driver initialization routine in

 * the "__initcall.int" code segment if the driver is checked as

 * "y" or static, or else it will wrap the driver initialization

 * routine with init_module() which is used by insmod and

 * modprobe when the driver is used as a module.

 */

/**

 * module_exit() - driver exit entry point

 * @x: function to be run when driver is removed

 *

 * module_exit() will wrap the driver clean-up code

 * with cleanup_module() when used with rmmod when

 * the driver is a module.  If the driver is statically

 * compiled into the kernel, module_exit() has no effect.

 */

注意一下init和cleanup这两个函数定义的变化。__init宏使内建模块中的init函数在运行完毕后释放掉,只是可装载的模块不受影响。假设你关心init函数什么时候调用,这一点是非常实用的。

还有个__initdata,和__init的作用基本上一样,只是它是针对变量而不是函数的。

__exit宏会使那些内建到内核的模块省略掉cleanup函数,只是和__init一样,对loadable模块没影响。再说一遍,假设你关心cleanup执行的时机,这是重要的。Built-in的驱动不须要cleanup,反正它们也不能退出,只是loadable式的模块显然是须要一个的。

这些宏都定义在linux/init.h中,它们会释放内核的内存。你启动内核的时候会看到一些诸如Freeing unused kernel memory:236k freed,之类的信息,这多半就是它们干的。

_init修饰,以及.init开头的节,在模块插入完成执行之后,这一部分

的内存空间会被释放,因此dump的时候这些信息是无法得到的。

内核模块至少要有两个函数:一个叫做init_module()的“start”初始化函数供insmod的时候调用,一个叫clean_module()的“end”清除函数供rmmod的时候调用。实际上,2.3.13之后的内核这两个函数不再必须使用这两个名字了。你给它们起什么名字都能够,2.3节我会将详细怎么做。给这两个函数自己起名字事实上是个挺好的主意,只是还是有非常多人使用init_module和clean_module函数。L

非常经典的,init_module函数会向内核注冊一些什么东西,或者用自己的代码替换内核的一些什么功能(通常它们做点什么动作之后还是会调用原来的函数)。而clean_module函数则会把init_module干的事情做个了结,以便安全的卸载模块。

最后,每一个内核模块都要包括linux/module.h。只为了KERL_ALERT(2.1.1节会讲到它)还须要在这个样例中包括linux/kernel.h。

Linux内核中的宏:__init and __exit的更多相关文章

  1. 剖析linux内核中的宏---------container_of

    #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...

  2. linux内核中的宏ffs(x)

    linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...

  3. Linux内核中container_of宏的详细解释

    上一节拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)我们在分析Linux内核链表的时候注意到内核在求解结构体偏移的时候巧妙的使用了container_of宏定义,今天我们来详细剖 ...

  4. 剖析linux内核中的宏-----------offsetof

    offsetof用于计算TYPE结构体中MEMBER成员的偏移位置. #ifndef offsetof#define offsetof(TYPE, MEMBER) ((size_t) &((T ...

  5. 内核中的宏定义__init、__initdata和__exit、__exitdata

    __init.__initdata和__exit.__exitdata的定义位于<kernel/include/linux/init.h> /* These are for everybo ...

  6. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  7. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  8. Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  9. Linux内核中的常用宏container_of其实很简单【转】

    转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...

随机推荐

  1. Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock(转)

    本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...

  2. SQVI和SAP查询QUERY的区别和使用注意事项

    SQVI.SAP查询QUERY都适用于简单的表连接数据查询,但都不能打包传输到PRD,不同环境需要重复创建.可以生成报表程序供T-CODE调用,用se93指定事务码和程序名称. 区别1-权限: SQV ...

  3. Linux虚拟机与外面系统ping不通,或者连不上网

    很多其它具体文档:http://download.csdn.net/download/zml_2015/8843061 非常多人在做linux课程设计的时候,用的linux虚拟机与外面的系统ping不 ...

  4. 4种Java引用浅解

    近期研究Java Cache实现,发现使用到了软引用(SoftReference),不太理解,查阅了JDK文档.代码以及几篇文章.做个小结,如有错误,欢迎指正. 之所以想学习一下Java的几种引用类型 ...

  5. 记一次排查log4net 不输出日志的解决过程

    最近发现log4net 不输出日志了,重点排查几个地方,发现都没有问题. 1.[assembly: log4net.Config.XmlConfigurator(ConfigFile = " ...

  6. SQL中distinct的用法(转)

    原文:http://www.cnblogs.com/rainman/archive/2013/05/03/3058451.html 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...

  7. 「OC」类和对象

    一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能的类. 术语:OO ...

  8. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家( 平衡树 )

    按鲜嫩程度排个序, 从大到小处理, 用平衡树维护价值 ---------------------------------------------------------------------- #i ...

  9. android设置按钮按下的不同效果图

    <!-- 按钮设置按下去的不同效果的方式,设置android:background属性, 下面的 button_select实际上是button_select.xml --> <Bu ...

  10. ThinkPHP第六天(正则表达式)

    1.正则表达式:原子 ①a-z,A-Z,0-9,_ ②用(abc)圆括号括起来的单元符号,表示括号里面的作为一个完整的组合,必须完成匹配,不被拆分来 ③用方括号括起来[abc][^abc]称之为原子表 ...