Kernel Module实战指南(一):Hello World!

原文地址:Kernel Module实战指南(一):Hello World!linux

Introduction

对于习惯了平时在Linux上进行C应用程序开发的你,是否想窥探一下底层的世界?
对于对Linux Kernel源码无从下手的你,是否但愿有一个简易的方法?
是的,这里有一个地方,可让你轻松的编写和调试Linux Kernel Code。
这个就是我将要介绍的Linux Kernel Module,即Linux内核模块。shell

Linux Kernel Module到底是什么?

Linux Kernel Module是一段能够在运行时被加载到Linux Kernel中的代码,能够使用Kernel Functions。Linux Kernel Module的用途很广,最多见的例子就是Device Driver,也就是设备驱动程序。
若是没有Linux Kernel Module,每一行修改Kernel代码,每个新增的Kernel功能特性,都须要从新编译Kernel,大大浪费了时间和效率。bash

如何查看已经加载的Linux Kernel Module

在bash下输入:函数

$ lsmod
Module      Size    Used by
nls_utf8   16384    1
isofs      30960    1
...

或者直接在bash下查看:ui

$ cat /proc/modules

Hello World!

闲话少说,开始编写咱们的第一个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!

一个像样的Kernel Module

咱们先简单包装一下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的警告了吧。

Summary

经过最简单的hello-world.c和Makefile(真的没有比这个更简单的代码了),介绍了如何编写咱们的第一个Kernel Module。动手作一作吧,你已经迈向了内核世界的第一步。

相关文章
相关标签/搜索