打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
module_init和module_exit

在写模块的时候有两个特殊的函数,分别是init_modulecleanup_module,这两个函数分别在insmod的时候和rmmod的时候调用,并且insmodrmmod只识别这两个特殊的函数,可是我们前面的例子里面并没有这两个函数。怎么会这样呢,那就必须得说说module_init/module_exit了。一个驱动可以作为一个模块动态的加载到内核里,也可以作为内核的一部分静态的编译进内核,module_init/module_exit也就有了两个含义:

 一、动态编译成模块

 在内核里有如下定义:

        /* Each module must use onemodule_init(). */

        #define module_init(initfn)   \

                static inline initcall_t__inittest(void)       \

                { return initfn; }      \

                int init_module(void)__attribute__((alias(#initfn)));

 

/* This is onlyrequired if you want to be unloadable. */

        #define module_exit(exitfn)  \

                static inline exitcall_t__exittest(void)     \

                { return exitfn; }     \

                 void cleanup_module(void)__attribute__((alias(#exitfn)));

 

首先我们可以发现发现module_init有两个含义:

 

1、验证加载函数的格式

 static inlineinitcall_t __inittest(void)    \

 { return initfn; }

 这个函数的作用是验证我们传过来的加载函数格式是否正确,linux内核规定加载函数的的原型是:

 typedef int(*initcall_t)(void);

 所以我们写加载函数的时候必须是返回值为int参数为void的函数,这个在内核里要求比较严格,所以我们写加载函数的时候必须按照这个约定。

 2、定义别名

 intinit_module(void) __attribute__((alias(#initfn)));

 这段代码的作用是给我们的加载函数定义一个别名,别名就是我们前面提到的init_module,这样insmod就能够执行我们的加载函数了。module_exit的作用和module_init一样,同样也是验证函数格式和定义别名。

 

二、静态编译

 

在静态编译的时候module_init的定义如下:

        #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 __used \

               __attribute__((__section__(".initcall" level".init"))) = fn

 

通过这些段代码,我们能够看出最终的结果是将我们的使用module_init修饰的函数指针链接到一个叫.initcall的段里,也就是说最终所以的使用module_init修饰的函数指针都被链接在这个段里,最终内核在启动的时候顺序调用所有链接在这个段里的函数,实现设备的初始化。module_exit在静态编译的时候没有意义,因为静态编译的驱动无法卸载!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
驱动程序用到的头文件linux/include/linux/init.h(基于linux ...
Linux initcall的实现
linux kernel initcall 的顺序
代码编译到内核和编译成模块在代码中的区别
linux设备驱动归纳总结(二):模块的相关基础概念
Linux内核模块开发(笔记)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服