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。動手作一作吧,你已經邁向了內核世界的第一步。

相關文章
相關標籤/搜索