原文地址:Kernel Module实战指南(一):Hello World!linux
对于习惯了平时在Linux上进行C应用程序开发的你,是否想窥探一下底层的世界?
对于对Linux Kernel源码无从下手的你,是否但愿有一个简易的方法?
是的,这里有一个地方,可让你轻松的编写和调试Linux Kernel Code。
这个就是我将要介绍的Linux Kernel Module,即Linux内核模块。shell
Linux Kernel Module是一段能够在运行时被加载到Linux Kernel中的代码,能够使用Kernel Functions。Linux Kernel Module的用途很广,最多见的例子就是Device Driver,也就是设备驱动程序。
若是没有Linux Kernel Module,每一行修改Kernel代码,每个新增的Kernel功能特性,都须要从新编译Kernel,大大浪费了时间和效率。bash
在bash下输入:函数
$ lsmod Module Size Used by nls_utf8 16384 1 isofs 30960 1 ...
或者直接在bash下查看:ui
$ cat /proc/modules
闲话少说,开始编写咱们的第一个Kernel Module,直接上代码,hello-world.c:命令行
#include <linux/kernel.h> #include <linux/module.h> int init_module(void) { printk(KERN_INFO "Hello World!\n"); return 0; } void cleanup_module(void) { printk(KERN_INFO "Bye World!\n"); }
内核中打印函数和应用打印函数略微不一样,printf()是glibc的函数,内核中使用printk()。实际上printk()的设计并非为了打印,而是为了记录,根据配置不一样,内容可能由syslogd或者klogd打印到/var/log/messages中,或者打印到你的console中。
编译的话,和应用层代码使用的gcc或者g++不一样,Kernel Module使用Makefile,或者kbuild。下面是Makefile文件:设计
obj-m += hello-world.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
在命令行输入:调试
$ Make
若是成功,你将在当前目录看到hello-world.ko,以及其余的临时文件。
经过modinfo来查看module信息,在命令行输入:code
$ modinfo hello-world.ko filename: hello-world.ko ...
如今没有什么信息,别着急,后面会介绍如何将信息(author, license等)写到Kernel Module中。
运行咱们的Kernel Module,在命令行输入:开发
$ insmod hello-world.ko
若是提示权限不够,输入:
$ sudo insmod hello-world.ko
执行完毕后,可能在console上不会显示任何结果。还记得前面提到的吗?咱们须要查看/var/log/messages,最简单的方法是在命令行输入:
$ dmesg ... [26484.975093] Hello World!
好了,咱们卸载模块,一样在命令行输入:
$ rmmod hello-world.ko
若是提示权限不够,输入:
$ sudo rmmod hello-world.ko
执行完毕后,可能在console上不会显示任何结果。一样查看/var/log/messages:
$ dmesg ... [26484.975093] Hello World! [26739.017345] Bye World!
咱们先简单包装一下Hello World的Code,让他看上去稍微丰富一点:
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> static int __init init_my_module(void) { printk(KERN_INFO "Hello, my module!\n"); return 0; } static void __exit exit_my_module(void) { printk(KERN_INFO "Bye, my module!\n"); } module_init(init_my_module); module_exit(exit_my_module); MODULE_LICENSE("GPL"); MODULE_AUTHOR("csprojectedu");
这里咱们使用了linux/init.h中提供的宏__init和__exit,解放咱们的函数名,再也不沿用蹩脚的init_module()和cleanup_module()了。
Makefile仍是沿用以前的:
obj-m += my_module.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
在命令行输入:
$ Make
经过modinfo来查看module信息,在命令行输入:
$ modinfo my_module.ko filename: my_module.ko author: csprojectedu license: GPL ...
是否是多了author和license?insmod的时候也再也不报缺乏license的警告了吧。
经过最简单的hello-world.c和Makefile(真的没有比这个更简单的代码了),介绍了如何编写咱们的第一个Kernel Module。动手作一作吧,你已经迈向了内核世界的第一步。