linux内核自己添加模块(内核版本:3.0.101)
做内核驱动第一步都是学习如何添加模块,这是基础,有了这个基础,剩下就是写代码了。
由于2.4到2.6内核版本的更新,无论是系统调用还是模块添加机制都有了巨大的变化,本人也因此饱经挫折,最后在3.0.101版本的内核下成功。作为开源运动的支持者,自认为有必要把自己的经历分享出来,以供后来学习者分享与交流。
再次声明,本博客只分享我遇到了的问题,没有交流的不代表不难或者不会遇到问题,只是我没遇到,如果有阅读本博客的朋友遇到了问题,非常欢迎大家一起讨论,技术就是这么成长的!
关于添加模块,步骤上还是那三步。
1.编写模块函数
编写内核模块时必须要有的两个函数 :
1> 加载 函数:
static int func1_init(void)
2> 卸载函数 无返回值
static void func2_exit(void)
这里值得注意的是三点,一是卸载函数必须是void,即无返回型,否则会报错。其二是推荐把加载函数改写成static int __init func1_init(void),卸载函数同理。这里使用__init是利用2.6内核以后的宏机制,具体机制。。。还在学习中。第三点就是人尽皆知的,加载函数的名字必须写成*_init的样子,卸载函数必须是*_exit的样子。
2.其次就是Makefile了。
这方面的文章比较多,网上也讲得非常详细,我就大概讲一下模板和每步的意义。
obj-m := hello.o
kernel_path=/usr/src/linux-headers-$(shell uname -r)
all:
make -C $(kernel_path) M=$(PWD) modules
clean:
make -C $(kernel_path) M=$(PWD) clean
obj -m:= hello.o // 产生 hello 模块的目标
kernel_path // 定义内核源文件目录
all :
make -C $(kernel_path) M=$(PWD) modules
// 生成内核模块参数为内核源代码目录以及模块所在目录
clean:
make -C $(kernel_path) M=$(PWD) clean
// 清除生成的模块文件以及中间文件
这里就要尤为注意了,在2.6版本以后,引入了如下机制。2.6中模块的编译需要配置过的内核源码;编译、连接后生成的内核模块后缀为.ko;编译过程首先会到内核源码目录下,读取顶层的Makefile文件,然后再返回模块源码所在目录。
接下来要讲得就是最折磨人的改变了。
2.4内核下, 执行`cat /proc/ksyms`可看到内核符号在名字后还跟随着一串校验字符串,此校验字符串与内核版本有关。在内核源码头文件linux/modules 目录下存在许多*.ver文件,这些文件起着为内核符号添加校验后缀的作用,如ksyms.ver 文件里有一行 #define printk _set_ver(printk)。linux/modversions.h 文件会包含全部的 ver文件 。所以当模块包含linux/modversions.h文件后,编译时,模块里使用的内核符号实质是带有校验后缀的内核符号。在加载模块时,如果模块中所使用内核符号的校验字符串与当前运行内核所导出的相应的内核符号的校验字符串不一致,即当前内核空间并不存在模块所使用的内核符号,就会出现"Invalid module format "的错误。
为内核符号添加校验字符串来验证模块的版本与内核的版本是否匹配是繁杂和浪费内核空间的;而且随着SMP(对称多处理器)、PREEMPT(可抢占内核)等机制在2.6内核的引入和完善,模块运行时对内核的依赖不仅取决于内核版本,还取决于内核的配置,此时内核符号的校验码是否一致不能成为判断模块可否被加载的充分条件。2.6 内核下,在linux/vermagic.h中定义有VERMAGIC_STRING,VERMAGIC_STRING不仅包含内核版本号,还包含有内核使用的gcc版本,SMP与PREEMPT等配置信息。模块在编译时,我们可以看到屏幕上会显示"MODPOST"。在此阶段, VERMAGIC_STRING会添加到模块的modinfo段。 在内核源码目录下scripts/mod/modpost.c文件中可以看到模块后续处理部分的代码。模块编译生成后,通过`modinfo mymodule.ko`命令可以查看此模块的vermagic等信息。2.6 内核下的模块装载器里保存有内核的版本信息,在装载模块时,装载器会比较所保存的内核vermagic与此模块的modinfo段里保存的vermagic信息是否一致,两者一致时,模块才能被装载。譬如Fedora core 4 与core 2 使用的都是2.6 版本内核, 在Fedore Core 2下去加载Fedora Core4下编译生成的hello.ko,会出现"invalid module format" 错误。
因此,细心的朋友注意到我给出的Makefile模板中编译目标是内核源码树。这里必须是这样,否则会出错。而且必须对应,即,如果你当前内核版本是3.0.101,就必须是以3.0.101的内核源码树为目标进行编译得到*.ko,否则会报错。反之亦然。两者必须一一对应,这一点希望朋友们务必注意,否则会痛不欲生。
以上就是我学习这部分最痛苦最值得分享的部分了,希望可以帮到大家。
由于2.6下各位朋友肯定希望自己的模块能兼容2.4下的模式,所以,我这里再提供一套Makefile,有IBM官方给出,值得学习。
# Makefile2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := file1.o file2.o
obj-m := mymodule.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
linux内核自己添加模块(内核版本:3.0.101)的更多相关文章
- 解析 Linux 内核可装载模块的版本检查机制
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-kernelmodules/ 为保持 Linux 内核的稳定与可持续发展,内核在发展过程中引进了可 ...
- linux内核添加模块
参考: http://blog.csdn.net/gaoguoxin2/article/details/50220665 动态添加模块不需要编译内核. LINUX的模块主要由6部分组成: 1.模块的加 ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
- linux 实现centos7在线升级最新版本内核
Kernel (内核)是操作系统的核心,掌握所有硬件设备的控制权,也就是说,你所希望计算机帮你完成的各项工作,都需要通过内核的帮助才能完成,当然,如果我们想完成的某个功能是内核没有的,则内核不会操控 ...
- Linux驱动之内核加载模块过程分析
Linux内核支持动态的加载模块运行:比如insmod first_drv.ko,这样就可以将模块加载到内核所在空间供应用程序调用.现在简单描述下insmod first_drv.ko的过程 1.in ...
- Linux内核开发之将驱动程序添加到内核
驱动程序添加到内核 一.概述: 在Linux内核中增加程序需要完成以下三项工作: 1.将编写的源代码复制到Linux内核源代码的相应目录 2.在目录的Kconfig文件中增加新源代码对应项目的编译配置 ...
- Linux内核的五大模块
Linux内核的五大模块 (转自)https://blog.csdn.net/huangjingbin/article/details/19396235 Linux内核的五大模块 1.进程调度模块 2 ...
- 在Linux内核中添加系统调用,并编译内核
1 环境准备 运行系统:vmware下安装的ubuntu10.10 32bit桌面版. 编译内核版本: linux-2.6.32.63 内核目录: /home/wanchouchou/linuxKer ...
- Linux内核@系统组成与内核配置编译
Linux系统由什么组成? 由用户空间(应用程序+GNU C标准库)和内核空间(系统调用接口+内核+内核架构代码)组成. Linux内核到底是什么?以及组成. ARM的七种操作级别? 内核网络协议栈( ...
随机推荐
- Node.js学习笔记(一) --- HTTP 模块、URL 模块、supervisor 工具
一.Node.js创建第一个应用 如果我们使用 PHP 来编写后端的代码时,需要 Apache 或者 Nginx 的 HTTP 服务器, 来处理客户端的请求相应.不过对 Node.js 来说,概念完全 ...
- No.4一步步学习vuejs之表单输入绑定
基础用法 你可以用 v-model 指令在表单控件元素上创建双向数据绑定.它会根据控件类型自动选取正确的方法来更新元素.尽管有些神奇,但 v-model 本质上不过是语法糖,它负责监听用户的输入事件以 ...
- shiro,基于springboot,基于前后端分离,从登录认证到鉴权,从入门到放弃
这个demo是基于springboot项目的. 名词介绍: ShiroShiro 主要分为 安全认证 和 接口授权 两个部分,其中的核心组件为 Subject. SecurityManager. Re ...
- 初步理解impress.js
1.认识impress.js impress.js 采用 CSS3 与 JavaScript 语言完成的一个可供开发者使用的表现层框架(演示工具). 现在普通开发者可以利用 impress.js 自己 ...
- jQuery知识点学习整理
零.jQuery中操作css的方法 1.$("p").css("background-color"); 返回首个匹配元素的background-color的值. ...
- mac 安装mysql-python
ln -s /usr/local/mysl/bin/* /usr/bin #建立软连接 sudo pip install mysql-python #安装 python ...
- ASP.NET MVC中,前台DropDownList传值给后台。
List<SelectListItem> ZH = new List<SelectListItem>(); ZH.Add(new SelectListItem { Text = ...
- org.springframework.beans.factory.NoSuchBeanDefinitionException
1. 问题描述 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxx ...
- 大规模WEB服务技术
CPU负载的扩展很简单,增加相同结构的服务器,通过负载均衡来分散. I/O负载的扩展很困难.要考虑局部性.
- Windows静态库和动态库的创建和使用
偶们在实际的编程开发中,经常会遇到运行时无法找到某个DLL文件或者链接时无法找到某个LIB文件.然后,我们就开始乱GOOGLE一下,然后将VS2005的设置改变一下,或许就Ok了,我们将别人开发的DL ...