内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。

一、 什么是模块

模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。

应用程序与内核模块的比较
为了加深对内核模块的了解,表一给出应用程序与内核模块程序的比较。
表一 应用程序与内核模块程序的比较

  C语言应用程序 内核模块程序
使用函数 Libc库 内核函数
运行空间 用户空间 内核空间
运行权限 普通用户 超级用户
入口函数 main() module_init()
出口函数 exit() module_exit()
编译 Gcc –c Makefile
连接 Gcc insmod
运行 直接运行 insmod
调试 Gdb kdbug, kdb,kgdb等

从表一我们可以看出,内核模块程序不能调用libc库中的函数,它运行在内核空间,且只有超级用户可以对其运行。另外,模块程序必须通过module_init()和module-exit()函数来告诉内核“我来了”和“我走了”。

二、 编写一个简单的模块

模块和内核都在内核空间运行,模块编程在一定意义上说就是内核编程。因为内核版本的每次变化,其中的某些函数名也会相应地发生变化,因此模块编程与内核版本密切相关。以下例子针对Ubuntu 9.10  内核2.6.31-14-generic

1.程序举例

  1. #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 放在同一个目录里
  1. obj-m := hello.o
  2. KERNELBUILD :=/lib/modules/$(shell uname -r)/build
  3. default:
  4. make -C $(KERNELBUILD) M=$(shell pwd) modules
  5. clean:
  6. 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/build

make -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.ko
2. rmmod命令
调用rmmod程序将已经插入内核的模块从内核中移出,rmmod会自动运行cleanup_module()函数,其命令格式为:
#rmmod  [path] modulename.ko
3.lsmod命令
调用lsmod程序将显示当前系统中正在使用的模块信息。实际上这个程序的功能就是读取/proc文件系统中的文件/proc/modules中的信息,其命令格式为:
#lsmod
4.ksyms命令

ksyms这个程序用来显示内核符号和模块符号表的信息。与lsmod相似,它的功能是读取/proc文件系统中的另一个文件/proc/kallsyms。

这就是在2.6.xx下一个最简单的模块编写过程。

转载于:https://www.cnblogs.com/int32bit/archive/2011/06/12/3187798.html

linux 第一个内核模块Hello World相关推荐

  1. linux如何卸载内核模块_如何加载或卸载Linux内核模块

    linux如何卸载内核模块 本文摘自Manning出版的< Linux in Action>第15章. Linux使用内核模块管理硬件外围设备. 这是这样的. 一个运行中的Linux内核是 ...

  2. linux第一章简答

    linux第一章简答题: 1.你在你的主机上面安装了一张网卡,但是开机之后,系统却无法使用,你确定网卡是好的,那么可能的问题出在哪里?该如何解决? 答:因为所有的硬件都没有问题,所以,可能出问题的地方 ...

  3. linux中生成内核模块时部分函数undefined的应对方法

    linux中生成内核模块时部分函数undefined的应对方法 在编译生成新的nfs.ko文件时,遇到undefined warning,因为在nfs的代码里调用linux内核提供的函数,刚好这个函数 ...

  4. Linux第一课 了解Linux

    Linux 第一课 了解Linux 了解Linux 1.Linux简介 2.Linux版本 3.Linux体系结构 4.系统启动 5.登录Linux 6.修改密码 7.查看目录和文件 8.查看当前用户 ...

  5. Linux学习之内核模块编程

    前言 之前成功编译了内核,这次学习如何修改增加删除内核模块,为了保证内核的纯净,我特意重新编译安装了一个新的5.11.8的内核,其他内核同理. 本文原创,创作不易,转载请注明!!! 本文链接 个人博客 ...

  6. N32-马哥Linux第一周学习

    1. 描述计算机的组成及其功能. 答: 计算机由运算器,控制器,存储器,输入设备和输出设备五大部件组成计算机,每一部件分别按要求执行特定的基本功能. 运算器 主要功能是对数据进行各种运算 控制器 控制 ...

  7. 投靠Linux第一步 Windows数据向Linux迁徙(1)

    作者: 雪影蓝风/译 出处:天极软件   阅读提示:你现在正要从Windows转向Linux的度量吗?很好,就像其他曾经冒险考试考试的用户组织一样,你将能够享遭到Linux开放尺度所带来的不乱性以及靠 ...

  8. Linux第一条指令地址,arm-linux 启动代码分析——stage1 (1)

    本文针对arm linux, 从kernel的第一条指令开始分析,一直分析到进入start_kernel()函数. 我们当前以linux-2.6.19内核版本作为范例来分析,本文中所有的代码,前面都会 ...

  9. 学习Linux第一天

    今天2019年3月8日,是我Linux学习的第一天,在这里也是和大家一块交流学习的第一天,希望日后和大家合作愉快. 首先说一下我对Linux的 了解与认识,我对Linux的认识最早是在我上初中的时候, ...

最新文章

  1. Matlab与线性代数 -- 矩阵的乘法
  2. vscode技巧、vscode教程、vscode使用技巧
  3. [IE技巧] 如何禁止用户关闭IE浏览器
  4. 学习搭建 Consul 服务发现与服务网格-有丰富的示例和图片
  5. python kivy ios_Kivy跨平台技术开发iOS
  6. 春天重试,因为冬天来了
  7. Android 使用SWIG生成Jni代码转
  8. 10个简单步骤,完全理解SQL
  9. php 6位邮政编码,php / mysql邮政编码邻近搜索
  10. oracle logical standby,Oracle Dataguard管理命令(logical standby)
  11. 图说Netty服务端启动过程
  12. php 的cookie设置时间,php cookie时间设置的方法
  13. ExcelApplication相关资料
  14. 杰克·韦尔奇的101条经典语录
  15. 开发一个软件需要哪些角色
  16. 纯C#实现的DHT爬虫和磁力搜索引擎 - btcherry.com
  17. 【自然语言处理】词性标注
  18. qpython3l表白编程_沫琼的喜欢 | LOFTER(乐乎) - 让兴趣,更有趣
  19. android studio moudel,Android Studio中的Module是指什么?
  20. 洛谷P4196 半平面交

热门文章

  1. crntos7启动php命令_CentOS7设置php-fpm开机自启动
  2. python连不上树莓派_树莓派respberry中cmake编译链接python2.7库不成功,求教
  3. HTML5新布局元素布局,HTML5新的布局元素
  4. mysql内部损坏_mysql表损坏故障案例
  5. ps一点等于多少厘米_企业展厅设计关于展台你了解多少?
  6. seata xid是什么_阿里开源的分布式事务框架 Seata
  7. convert.todatetime指定日期格式_SQL基础知识V2——常用日期函数
  8. matlab中degrees,Convert degrees-minutes-seconds to degrees
  9. 工业交换机常用术语及常见知识点汇总
  10. 网管型交换机比普通交换机有哪些明显优势