Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用所需要的组件?

方法一:

把所有的组件都编译进内核文件,即Zlmage或bzlmage,但会导致两个问题:一是生成的内核文件过大;二是如果要添加或删除某个组件,需要重新编译整个内核。

有没有一种机制能让内核文件(zlmage或bzlmage)本身不包含某个组件,而是在该组件需要被使用的时候,动态地添加到正在运行的内核中呢?

有,Linux“内核模块”机制。

方法二:

linux内核模块机制。

内核模块特点:

模块本身并不被编译进内核文件(zlmage或bzlmage),仅以.o或其它形式存在。

可以根据需求,在内核运行期间动态地安装或卸载。

下面写一个内核模块的例子:

1. 编写hello.c文件

#include

#include

static int hello_init(void){

printk(KERN_WARNING"hello world\n");

return 0;

}

static void hello_exit(void){

printk(KERN_INFO"Goodbye,wold\n");

}

module_init(hello_init);

module_exit(hello_exit);

与应用程序相比,内核模块没有main函数,输出使用printk,而不是printf。

程序结构:

1)模块加载函数(必需)

安装模块时被系统自动调用的函数,通过module_init宏来指定。

2)模块卸载函数(必需)

卸载模块时被系统自动调用,通过module_exit宏来指定。

2. 编写Makefile文件

模块的编译,通常使用makefile。

1)如果内核模块仅由一个源文件构成,该如何编写Makefile?

ifneq ($(KERNELRELEASE),)

obj-m:=hello.o

else

KDIR:=/lib/modules/$(shell uname -r)/build

all:

make -C $(KDIR) M=$(PWD) modules

clean:

rm -f *ko *.o *.mod.o *.mod.c *.symvers

endif

说明:KDIR模块依赖的内核源代码路径

KDIR:=/lib/modules/2.6.18-53.e15/build

-C进入后面的路径中,使用该路径中的Makefile编译。

生成的内核模块为.ko文件。

2)由多个源文件组成,main.c add.c

main.c调用了add.c中的函数,main.c和add.c构成内核模块hello.

ifneq ($(KERNELRELEASE),)

ojb-m:=hello.o

hello-objs:=main.o add.o

else

后面不变

3. 安装与卸载模块

加载:insmod hello.ko(加载后使用lsmod | grep hello查看)

卸载:rmmod hello

查看:lsmod

加载:modprobe hello

modprobe如同insmod,也是加载一个模块到内核,不同之处在于它会根据文件/lib/modules/

模块可选信息:

1)许可证申明

宏MODULE_LICENSE告诉内核,该模块带有一个许可证,否则加载内核时内核会报错。有效的许可证有”GPL”,”GPL v2”,”GPL and additional rights”,”Dual BSD/GPL” ,”Dual MPL/GPL” “proprietary”

hello.c:

#include

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("David");

2)作者申明 MODULE_AUTHOR(“…..”);

3)模块描述 MODULE_DESCRIPTION(“….”);

4)模块版本 MODULE_VERSION(“V1.0”);

5)模块别名 MODULE_ALIAS(“a simple module”);

6)模块参数 通过宏module_param指定模块参数,用于在加载模块时传递参数给模块。

module_param(name, type, perm)

name:参数名称

type: bool、int、charp(字符串)

perm:访问权限,常见值:

S_IRUGO:任何用户都对/sys/module中出现的该参数具有读写权限。

S_IWUSR:允许root用户修改/sys/module中出现的参数。

例子:声明成模块参数。

int a=3;

char * st;

module_param(a, int, S_IRUGO);

module_param(st, charp, S_IRUGO);

param.c:

#include

#include

static char * name="David";

static int age=30;

module_param(age, int, S_IRUGO);

module_param(name, charp, S_IRUGO);

static int hello_init(void){

printk(KERN_EMERG"Name:%s\n", name);

printk(KERN_EMERGE"Age:%d\n", age);

return 0;

}

static void hello_exit(void){

printk(KERN_INFO"Goodbye,wold\n");

}

module_init(hello_init);

module_exit(hello_exit);

编译出param.ko模块,

不传值加载: insmod param.ko

输出 Name:David Age: 12

传值加载: insmod param.ko age=12

输出 Age:12

内核符号导出:

/proc/kallsyms记录了内核中所有导出的符号的名字与地址。

为什么要导出内核符号?

一个内核模块实现了一些函数,为了让其他模块使用,必须将符号导出(函数、变量)

使用EXPORT_SYMBOL导出:

比如在.c文件中定义了两个函数:

EXPORT_SYMBOL(add_integar);

EXPORT_SYMBOL(sub_integer);

常见问题:版本不匹配

内核模块的版本由其依赖的内核代码版本所决定,在加载内核模块事,insmod会将内核模块版本与当前正在运行的内核版本比较,不一致会报错。

解决方法:

1. 使用modprob –force -modversion强行插入

2. 确保编译内核模块时,所依赖内核代码版本与正在运行的内核版本相同。(可通过uname -r查看当前内核版本)

内核程序 VS 应用程序

应用程序是从头(main)到尾执行,执行结束后从内存中消失。

内核模块先在内核中注册自己以便服务于将来的某个请求,然后它的初始化函数结束,此时模块仍然存在于内核中,直到卸载函数被调用。

printk函数有优先级

c需要实现安装卸载Linux模块,Linux内核模块编译与加载相关推荐

  1. linux 内核驱动模块的编译及加载

    主机:Windows 7旗舰版,VMware7.1.2,Fedora9 编译环境:arm-linux-gcc 4.4.3 Linux版本:linux-2.6.32.2 busybox版本:busybo ...

  2. 【转】Linux如何在系统启动时自动加载模块

    1.Linux安装驱动程序 tar zxf ixgbe-<x.x.x>.tar.gz cd ixgbe-<x.x.x>/src/ make install modprobe & ...

  3. linux nginx 安装stream,Centos7-64bit-编译安装配置Nginx stream四层负载均衡 动态加载

    Centos7-64bit-编译安装配置Nginx stream四层负载均衡 动态加载 2018-08-10 17:12 分享人:老牛 yum install screen -y && ...

  4. 在Linux系统中实现一个可加载的内核模块

    Intro 坐标成都电讯大专, 某操作系统课老师在PPT上草草写下3个内核线程API后就要求编程, 感受一下: include/linux/kthread.h,你就看到了它全部的API,一共三个函数. ...

  5. linux u盘 慢_u盘加载较慢 建议优化 - 卡饭网

    U盘加载速度十分缓慢的原因及解决方法 U盘加载速度十分缓慢的原因及解决方法 很多朋友在使用U盘的时候都遇到过电脑接入U盘后,加载读取文件的速度十分的缓慢,总是要等上一段时间才能完全读取,这是怎么回事呢 ...

  6. Linux下C/C++程序编译链接加载过程中的常见问题及解决方法

    Linux下C/C++程序编译链接加载过程中的常见问题及解决方法 1 头文件包含的问题 报错信息 该错误通常发生在编译时,常见报错信息如下: run.cpp:2:10: fatal error: dl ...

  7. 解决Ubuntu自动更新Linux内核导致显卡驱动无法加载,致使循环在登录界面

    解决Ubuntu自动更新Linux内核导致显卡驱动无法加载,致使循环在登录界面 关闭unattended-upgrade 在/etc/apt/apt.conf.d目录下,查找包含Unattended- ...

  8. Linux编译mplayer播放badapple及编译fbv加载图片(基于V3S预告板子要开源了)

    Linux编译mplayer播放badapple及编译fbv加载图片(基于V3S预告板子要开源了) 1.编译前准备: 1.linux5.10内核 2.2018.02bulidroot 3.v3s板子 ...

  9. 怎么设置uboot从u盘启动linux,rt5350使用uboot从u盘启动linux成功含从u盘加载镜像与rootfs...

    <rt5350使用uboot从u盘启动linux成功含从u盘加载镜像与rootfs>由会员分享,可在线阅读,更多相关<rt5350使用uboot从u盘启动linux成功含从u盘加载镜 ...

最新文章

  1. struts2 过滤器和拦截器
  2. 哈佛图书馆墙上的训言
  3. Linux系统下安装phpmyadmin方法
  4. devexpress 中的checkboxlist怎么设置间距_HTML中怎么设置h1的字体样式你知道吗?关于设置h1标签的样式详解
  5. 二 jQuery 语法
  6. 求无向图中某顶点的度 (有注释)
  7. 栈的应用 - 就近匹配
  8. I/O操作不占用CPU的任何线程
  9. [Java] 蓝桥杯ALGO-42 算法训练 送分啦
  10. python 传递带参数的函数_Python 函数的参数传递
  11. android nfc读写cpu卡,react-native调用nfc读写cpu卡、m1卡-android篇
  12. 如何设置Word自动检查语法错误
  13. 【C++ 程序】 TVJ Complex Calculator (v 2.1) 复数计算器
  14. OSChina 周一乱弹 —— 无双什么都好,但不是芙妹
  15. 百度hacked事件看谷歌real-time search
  16. 关于Java的位移运算
  17. 如何用java写一个年日历
  18. 前端项目更换鼠标样式
  19. 怎样在PS中使用渐变功能对图片调色?原来还有这样的调色模式!
  20. 推广营销人员的秘密武器:太阳动态ip代理

热门文章

  1. 关于Unity中GrabPass截屏的使用和Shader的组织优化
  2. 20155310 《Java程序设计》实验三(敏捷开发与XP实践)实验报告
  3. HDU1086You can Solve a Geometry Problem too(判断线段相交)
  4. Ora-00942:表或视图不存在
  5. 流媒体技术笔记(协议相关)
  6. 服务器运维硬件,服务器硬件运维巡检报告模板
  7. python矩阵所有元素取整_Python中如何对一个数值进行取整操作呢?
  8. syslog传到服务器日志文件,将supervisor产生的日志通过syslog上传到服务端
  9. 显卡风扇不转电脑黑屏_笔记本电脑开不了机是什么原因及常见解决办法
  10. 加速收敛_引入Powerball 与动量技术,新SGD优化算法收敛速度与泛化效果双提升 | IJCAI...