在前面helloworld的编写里面,我们使用了两个宏分别是module_init和module_exit,这里分析下为什么使用这两个宏。

在写模块的时候有两个特殊的函数,分别是init_module和cleanup_module,这两个函数分别在insmod的时候和rmmod的时候调用,并且insmod和rmmod只识别这两个特殊的函数,可是我们前面的例子里面并没有这两个函数。怎么会这样呢,那就必须得说说module_init/module_exit了。

一个驱动可以作为一个模块动态的加载到内核里,也可以作为内核的一部分静态的编译进内核,module_init/module_exit也就有了两个含义:

一、动态编译成模块

在内核里有如下定义:
        /* Each module must use one module_init(). */
        #define module_init(initfn) \
                static inline initcall_t __inittest(void) \
                { return initfn; } \
                int init_module(void) __attribute__((alias(#initfn)));

/* This is only required 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 inline initcall_t __inittest(void) \

{ return initfn; }

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

typedef int (*initcall_t)(void);

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

2、定义别名

int init_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在静态编译的时候没有意义,因为静态编译的驱动无法卸载!

显然 对动态加载的模块是无效的;

驱动之module_init/module_exit的更多相关文章

  1. ⭐驱动之module_init/module_exit与系统启动关系

    在前面helloworld的编写里面,我们使用了两个宏分别是module_init和module_exit,这里分析下为什么使用这两个宏. 在写模块的时候有两个特殊的函数,分别是init_module ...

  2. linux驱动 之 module_init解析 (上)【转】

    转自:https://blog.csdn.net/Richard_LiuJH/article/details/45669207 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...

  3. module_init module_exit

    像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:#include <linux/init.h>#inc ...

  4. linux内核驱动module_init解析(2)

    本文转载自博客http://blog.csdn.net/u013216061/article/details/72511653 如果了解过Linux操作系统启动流程,那么当bootloader加载完k ...

  5. 嵌入式Linux驱动开发日记

    嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...

  6. Linux字符设备驱动解析

    1.驱动即是一个内核模块,需要模块初始化函数 module_init() module_exit() 2.分配cdev struct cdev dev; 3.初始化cdev并定义file_operat ...

  7. register_chrdev_region/alloc_chrdev_region和cdev注册字符设备驱动

    内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev_region().alloc_chrdev_region() 和 register_chrdev(). (1 ...

  8. linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

    原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...

  9. Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRjYXN0Y3Bw/font/5a6L5L2T/font ...

随机推荐

  1. struts2 标签字体大小

    <style type="text/css"> label{ font-size: 20px; } </style> <s:textfield nam ...

  2. Codeforce Round #226 Div2

    这次CF虽然,但是- - 第一题看了很久的题目意思额,虽然慢了点- -,但还算没出错,还学会了hack了- -,还+了100- - 第二题想了很久- -...后来发现可以暴力- -,哎 第三题本来也应 ...

  3. url组成部分

    协议  eg:http 主机IP地址  eg :端口号8080 项目资源地址  eg:目录名,文件夹名

  4. PHP上传图片时,如何判断上传的文件是否为可用的图片文件

    利用getimagesize函数: function isImage($filename){$types = '.gif|.jpeg|.png|.bmp';//定义检查的图片类型if(file_exi ...

  5. ajax基本用法

    ajax能做到无刷新数据交互,给用户体验带来好处的同时也减小了服务器的压力,所以运用ajax能使网站性能更强劲.更吸引用户. 大型网站少不了注册页面,而大多数情况下我们不想让用户有相同的注册ID,所以 ...

  6. Mysql索引总结(一)

    数据库开发中索引的使用占了很重要的位置,好的索引会使数据库的读写效率加倍,烂的索引则会拖累整个系统甚至引发灾难. 索引分三类: index ----普通的索引,数据可以重复 unique ----唯一 ...

  7. fault coverage enhancement

    在pseudo-random test中,由于random pattern resistant的特性,fault coverage不是sufficient的, 所以会有一些办法来进行coverage的 ...

  8. SIFT算法详解(转)

    http://blog.csdn.net/zddblog/article/details/7521424 目录(?)[-] 尺度不变特征变换匹配算法详解 Scale Invariant Feature ...

  9. 【py登陆】python模拟登录

    用Python模拟登录网站 前面简单提到了 Python 模拟登录的程序,但是没写清楚,这里再补上一个带注释的 Python 模拟登录的示例程序.简单说一下流程:先用cookielib获取cookie ...

  10. python生成数据库中所有表的DESC描述

    在数据库设计完成之后, 常常需要在 wiki 或其他文档中保存一份数据库中所有表的 desc 描述, 尤其是每个字段的含义和用途. 手动去生成自然是不可取的. 因此, 我编写了一个简单的 python ...