Ubuntu下编译的第一个内核模块
2010-07-15 18:21
411 查看
内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。一、 什么是模块模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。应用程序与内核模块的比较为了加深对内核模块的了解,表一给出应用程序与内核模块程序的比较。表一 应用程序与内核模块程序的比较
从表一我们可以看出,内核模块程序不能调用libc库中的函数,它运行在内核空间,且只有超级用户可以对其运行。另外,模块程序必须通过module_init()和module-exit()函数来告诉内核“我来了”和“我走了”。二、 编写一个简单的模块模块和内核都在内核空间运行,模块编程在一定意义上说就是内核编程。因为内核版本的每次变化,其中的某些函数名也会相应地发生变化,因此模块编程与内核版本密切相关。以下例子针对Ubuntu 9.10 内核2.6.31-14-generic1.程序举例
C语言应用程序 | 内核模块程序 | |
使用函数 | Libc库 | 内核函数 |
运行空间 | 用户空间 | 内核空间 |
运行权限 | 普通用户 | 超级用户 |
入口函数 | main() | module_init() |
出口函数 | exit() | module_exit() |
编译 | Gcc –c | Makefile |
连接 | Gcc | insmod |
运行 | 直接运行 | insmod |
调试 | Gdb | kdbug, kdb,kgdb等 |
#include<linux/module.h> #include<linux/kernel.h> #include<linux/init.h> MODULE_LICENSE("GPL"); static int __init lkp_init(void) { printk(KERN_ALERT "Hello World!/n"); return 0; } static void __exit lkp_cleanup(void) { printk(KERN_ALERT "Bye World!/n"); } module_init(lkp_init); module_exit(lkp_cleanup); MODULE_AUTHOR("heyutao"); MODULE_DESCRIPTION("hello");说明
所有模块都要使用头文件module.h,此文件必须包含进来。 头文件kernel.h包含了常用的内核函数。 头文件init.h包含了宏_init和_exit,它们允许释放内核占用的内存。
lkp_init是模块的初始化函数,它必需包含诸如要编译的代码、初始化数据结构等内容。
使用了printk()函数,该函数是由内核定义的,功能与C库中的printf()类似,它把要打印的信息输出到终端或系统日志。
lkp_cleanup是模块的退出和清理函数。此处可以做所有终止该驱动程序时相关的清理工作。
module_init()和cleanup_exit()是模块编程中最基本也是必须的两个函数。
module_init()是驱动程序初始化的入口点。而cleanup_exit()注销由模块提供的所有功能。
2 编写Makefile 文件,与hello.c 放在同一个目录里[/code][/code]
obj-m := hello.oKERNELBUILD :=/lib/modules/$(shell uname -r)/builddefault:make -C $(KERNELBUILD) M=$(shell pwd) modulesclean:rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions(注意makefile里面要求的tab)KERNELBUILD :=/lib/modules/$(shell uname -r)/build是编译内核模块需要的Makefile的路径,Ubuntu下是/lib/modules/2.6.31-14-generic/buildmake -C $(KERNELBUILD) M=$(shell pwd) modules 编译内核模块。-C 将工作目录转到KERNELBUILD,调用该目录下的Makefile,并向这个Makefile传递参数M的值是$(shell pwd) modules。3. 编译模块#sudo make (调用第一个命令default)这时,在hello.c 所在文件夹就会有 hello.ko ,这个就是我们需要的内核模块啦#sudo make clean清理编译垃圾,hello.ko 也会清理掉。4. 插入模块,让其工作。注意必须是root权限#sudo insmod ./hello.ko我们用dmesg 就可以看到 产生的内核信息啦,Hello world!如果没有输出"hello from hello world",因为如果你在字符终端而不是终端模拟器下运行的话,就会输出,因为在终端模拟器下时会把内核消息输出到日志文件/var/log/kern.log中。#sudo rmmod ./hello再用dmesg 可以看到 Bye world!modutils是管理内核模块的一个软件包。可以在任何获得内核源代码的地方获取Modutils(modutils-x.y.z.tar.gz)源代码,然后选择最高级别的patch.x.y.z等于或小于当前的内核版本,安装后在/sbin目录下就会有insomod、rmmod、ksyms、lsmod、modprobe等实用程序。当然,通常我们在加载Linux内核时,modutils已经被载入。1.Insmod命令调用insmod程序把需要插入的模块以目标代码的形式插入到内核中。在插入的时候,insmod自动调用init_module()函数运行。注意,只有超级用户才能使用这个命令,其命令格式为:# insmod [path] modulename.ko2. rmmod命令调用rmmod程序将已经插入内核的模块从内核中移出,rmmod会自动运行cleanup_module()函数,其命令格式为:#rmmod [path] modulename.ko3.lsmod命令调用lsmod程序将显示当前系统中正在使用的模块信息。实际上这个程序的功能就是读取/proc文件系统中的文件/proc/modules中的信息,其命令格式为:#lsmod4.ksyms命令ksyms这个程序用来显示内核符号和模块符号表的信息。与lsmod相似,它的功能是读取/proc文件系统中的另一个文件/proc/kallsyms。这就是在2.6.xx下一个最简单的模块编写过程。
相关文章推荐
- 编译Ubuntu10.04的第一个内核模块
- Ubuntu下的第一个内核模块编译(转)
- ubuntu下编译第一个内核模块
- 编译、裁剪、安装、删除 Ubuntu内核和模块管理 分类: arm-linux-Ubuntu 2013-07-22 16:29 319人阅读 评论(0) 收藏
- ubuntu10.04成功编译内核模块
- 如何编译linux第一个模块 hellomod.ko 分类: arm-linux-Ubuntu 2013-07-22 16:30 286人阅读 评论(0) 收藏
- 编译、裁剪、安装、删除 Ubuntu内核和模块管理
- Ubuntu:编译Linux"内核源代码"和"内核模块"
- Ubuntu内核模块编译
- CentOS 5.6下将linux内核2.6.18升级到2.6.30,并编译动态加载linux下第一个模块
- ubuntu虚拟机下内核模块的编译和安装
- 在ubuntu上开发编译内核模块,并查看printk打印的消息
- Linux(Ubuntu)下编译内核模块
- Ubuntu 编译安装 Linux 4.0.5 内核,并修复 vmware 网络内核模块编译错误
- 编译、裁剪、安装、删除 Ubuntu内核和模块管理
- Ubuntu:编译Linux内核源代码和内核模块
- ubuntu下编译内核模块ko,并加载
- ubuntu内核模块编译环境
- Ubuntu12.10 内核源码外编译 linux模块--编译驱动模块的基本方法
- 第一个内核模块程序编译