一. 摘要

这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程。主要从模块开发中的常用指令、内核模块程序的结构、模块使用计数以及模块的编译等角度对内核模块进行介绍。在Linux系统开发过程中,以模块的形式开发其重要性不言自明,而在嵌入式设备驱动开发中将驱动程序以模块的形式发布,更是极大地提高了设备使用的灵活性——用户只需要拿到相关驱动模块,再插入到用户的内核中,即可灵活地使用你的设备。

二. 文章提纲

1. 摘要

2. 文章提纲

3. 概述

4. 模块开发常用的指令

5. 内核模块程序结构

6. 模块使用计数

7. 模块的编译

8. 使用模块绕开GPL

9. 总结

三.概述

Linux内核整体结构已经很庞大,包含了很多的组件,而对于我们工程师而言,有两种方法将需要的功能包含进内核当中。

一:将所有的功能都编译进Linux内核。

二:将需要的功能编译成模块,在需要的时候动态地添加。

上述两种方式优缺点分析:

第一种:

优点:不会有版本不兼容的问题,不需要进行严格的版本检查

缺点:生成的内核会很大;要在现有的内核中添加新的功能,则要编译整个内核

第二种:

优点:模块本身不编译进内核,从而控制了内核的大小;模块一旦被加载,将和其它的部分完全一样。

缺点:可能会有内核与模块版本不兼容的问题,导致内核崩溃;会造成内存的利用率比较低。

四.模块开发常用的指令

在内核模块开发的过程中常用的有以下指令。

1)  insmod: 将模块插入内核中,使用方法:#insmod XXX.ko

2)  rmmod: 将模块从内核中删除,使用方法:#rmmod XXX.ko

3)  lsmod: 列表显示所有的内核模块,可以和grep指令结合使用。使用方法:#lsmod | grep XXX

4)  modprobe: modprobe可载入指定的个别模块,或是载入一组相依赖的模块。modprobe会根据depmod所产生的依赖关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。依赖关系是通过读取 /lib/modules/2.6.xx/modules.dep得到的。而该文件是通过depmod 所建立。

5)  modinfo: 查看模块信息。使用方法:#modinfo XXX.ko

6)  tree –a: 查看当前目录的整个树结构。使用方法:#tree -a

五.内核模块程序结构

1)  模块加载函数(一般需要)

在用insmod或modprobe命令加载模块时,该函数被执行。完成模块的初始化工作。

Linux内核的模块加载函数一般用__init标识声明,模块加载函数必须以module_init(函数名)的形式被指定。该函数返回整型值,如果执行成功,则返回0,初始化失败时则返回错误编码,Linux内核当中的错误编码是负值,在<linux/errno.h>中定义。

在Linux中,标识__init的函数在连接时放在.init.text这个区段,而且在.initcall.init中保留一份函数指针,初始化的时候内核会根据这些指针调用初始化函数,初始化结束后释放这些init区段(包括前两者)。

代码清单:

 1 static int __init XXX_init(void)
2
3 {
4
5 return 0;
6 }
7
8
9
10 moudle_init(XXX_init);

2)  模块卸载函数(一般需要)

在用rmmod或modprobe命令卸载模块时,该函数被执行。完成与加载相反的工作。

模块的卸载函数和模块加载函数实现相反的功能,主要包括

  1. 若模块加载函数注册了XXX,则模块卸载函数注销XXX
  2. 若模块加载函数动态分配了内存,则模块卸载函数释放这些内存
  3. 若模块加载函数申请了硬件资源,则模块卸载函数释放这些硬件资源
  4. 若模块加载函数开启了硬件资源,则模块卸载函数一定要关闭这些资源

代码清单:

1 static void __exit XXX_exit(void)
2
3 {
4
5 }
6
7
8
9 moudle_exit(XXX_exit);

3)  模块许可证声明(必须)

如果不声明,则在模块加载时会收到内核被污染的警告,一般应遵循GPL协议。

代码清单:

1 MODULE_LICENSE("GPL");

4)  模块参数(可选)

模块在被加载时传递给模块的值,本身应该是模块内部的全局变量。

示例程序book.c

 1 #include <linux/init.h>
2
3 #include <linux/module.h>
4
5
6
7 static char *bookName = "Good Book.";
8
9 static int bookNumber = 100;
10
11
12
13 static int __init book_init(void)
14
15 {
16
17 printk(KERN_INFO "Book name is %s\n", bookName);
18
19 printk(KERN_INFO "Book number is %d\n", bookNumber);
20
21 return 0;
22
23 }
24
25
26
27 static void __exit book_exit(void)
28
29 {
30
31 printk(KERN_INFO "Book module exit.\n");
32
33 }
34
35
36
37 module_init(book_init);
38
39 module_exit(book_exit);
40
41 module_param(bookName, charp, S_IRUGO);
42
43 module_param(bookNumber, int, S_IRUGO);
44
45
46
47 MODULE_LICENSE("GPL");

在向内核插入模块的时候可以用以下方式,并且可以在内核日志中看到模块加载以后变量已经有了值。

5)  模块导出符号(可选)

使用模块导出符号,方便其它模块依赖于该模块,并使用模块中的变量和函数等。

在Linux2.6的内核中,/proc/kallsyms文件对应着符号表,它记录了符号和符号对应的内存地址。对于模块而言,使用下面的宏可以导出符号。

1 EXPORT_SYMBOL(符号名);

1 EXPORT_GPL_SYMBOL(符号名);

6)  模块信息(可选)

模块信息则是指模块的作者信息等。

六.模块使用计数

Linux内核提供了MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT宏来管理模块使用计数。但是对于内核模块而言,一般不会自己管理使用计数。

七.模块的编译

将下面的Makefile文件放在book.c同级的目录下,然后使用#make命令或者#make all命令编译即可生成book.ko模块文件。

对应的Makefile:

 1 ifneq ($(KERNELRELEASE),)
2
3 mymodule_objs := book.o
4
5 obj-m := book.o
6
7 else
8
9 PWD := $(shell pwd)
10
11 KVER ?= $(shell uname -r)
12
13 KDIR := /usr/src/linux-headers-2.6.38-8-generic
14
15
16
17 all:
18
19 $(MAKE) -C $(KDIR) M=$(PWD)
20
21 clean:
22
23 rm -rf *.mod.c *.mod.o *.ko *.o *.tmp_versions *.order *symvers
24
25 endif

八.使用模块绕开

如果功能不编译成模块,则无法绕开GPL,编译成模块后公司发布产品则只需要发布模块,而不需要发布源码。为了Linux系统能够支持模块,需要做以下的工作:

  1. 内核编译时选择“可以加载模块”,嵌入式产品一般都不需要卸载模块,则可以不选择“可卸载模块”
  2. 将我们的ko文件放在文件系统中
  3. Linux系统实现了insmod、rmmod等工具
  4. 使用时可以用insmod手动加载模块,也可以修改/etc/init.d/rcS文件,从而在系统启动的时候就加载模块。

九.总结

本文主要介绍内核模块的概念和基本编程方法,内核模块主要由加载、卸载函数功能函数等一系列声明组成。它可以被传入参数,也可以导出符号,供其它的模块使用。

【Linux开发】内核模块简介的更多相关文章

  1. Linux内核分析(二)----内核模块简介|简单内核模块实现

    原文:Linux内核分析(二)----内核模块简介|简单内核模块实现 Linux内核分析(二) 昨天我们开始了内核的分析,网上有很多人是用用源码直接分析,这样造成的问题是,大家觉得很枯燥很难理解,从某 ...

  2. 迅为三星Exynos 4412开发板四核Cortex-A9ARM安卓linux开发板

    开发板光盘资料包含:原理图(PDF格式).底板PCB(Allegro格式).驱动程序源码.芯片和LCD数据手册.开发环境.产品使用手册. 4412开发板简介: iTOP-Exynos4412开发板采用 ...

  3. Hadoop开发环境简介(转)

    1.Hadoop开发环境简介 1.1 Hadoop集群简介 Java版本:jdk-6u31-linux-i586.bin Linux系统:CentOS6.0 Hadoop版本:hadoop-1.0.0 ...

  4. 《嵌入式Linux开发实用教程》

    <嵌入式Linux开发实用教程> 基本信息 作者: 朱兆祺    李强    袁晋蓉 出版社:人民邮电出版社 ISBN:9787115334831 上架时间:2014-2-13 出版日期: ...

  5. VS2015配置Linux开发远程调试

    # VS2015配置Linux开发远程调试 ### 简介-----------------------------vs2015支持跨平台开发 ### 软件环境--------------------- ...

  6. Linux嵌入式 -- 内核简介(x86)

    0. 嵌入式系统 以应用为中心,软硬件可裁剪,对功耗.对体积.对成本等都有严格要求的专用计算机系统. 1.  linux体系结构 2. 为什么 划分为 用户空间 和 内核控件 ?  分两级,内核和应用 ...

  7. 新一代 Linux 文件系统 btrfs 简介

    https://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/ Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3 ...

  8. Linux系统入门简介<1>

    linux系统入门简介 我们为什么要学习Linux? 在介绍Linux的历史前,我想先针对大家如何对Linux的发音说一下.我发现我身边的朋友对Linux的发音大致有这么几种: "里那克斯& ...

  9. 【Linux开发】Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇) 作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/beer ...

  10. 20145213《信息安全系统设计基础》实验一 Linux开发环境的配置

    北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:1452 姓名: 黄亚奇 祁玮 学号:20145213 20145222 成绩: 指导教师:娄嘉鹏 实验日期:2016 ...

随机推荐

  1. Java-ConnectDB工具类

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 功能描述: ...

  2. BZOJ 4032: [HEOI2015]最短不公共子串 (dp*3 + SAM)

    转博客大法好 第4个子任务中,为什么只转移最近的一个位置,自己YY吧(多YY有益身体健康). #include <bits/stdc++.h> using namespace std; t ...

  3. 【SQL Server】使用SQL比较版本号

    最近遇到这么一个场景,需要用SQL从表里取出版本号小于'10.2'的所有数据.目前表中以存在的数据中,版本号有两种格式,一个是'X.Y',另一个是'X'.对于SQL Server来说,其没有strin ...

  4. yii 上传视频(ajax)

    实现一个功能:提交表单的时候,需要上传视频,把视频上传到oss上,然后把url作为表单值传到后端保存到数据库.需要ajax异步实现. 遇到了一个这样报错:Bad Request: 您提交的数据无法被验 ...

  5. 【Java Web】IDEA如何创建及配置Web项目(多图)

    正文之前 在学习Java Web时,第一个遇到的问题就是如何创建或配置Web项目了,今天,就用IntelliJ IDEA 来进行Web项目配置: 创建Web项目 配置web项目 正文 创建Web项目 ...

  6. 【模板】OI常用模板(待补充)

    //PS:最近修改日期:2017-11-07 20:41:44 首先感觉这种模板类的东西写了还是很有意义的,毕竟时不时的可以拿出来借鉴一下. 现在因为刚开始写这一类的东西,所以说还不是很详细,若有读者 ...

  7. codevs3269 混合背包 x

    3269 混合背包  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond   题目描述 Description 背包体积为V ,给出N个物品,每个物品占用体积为 ...

  8. websocket 连接测试端口服务是否正常代码

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. java中MD5函数

    import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5U ...

  10. zabbix监控远端主机

    接着上一篇博客,zabbix监控搭建起来以后,怎么用来监控其他主机呢,这一篇就来简单讲一下,希望对大家有所帮助. 安装一些依赖包 [root@winter ~]# yum install curl c ...