Linux內核驅動模塊編寫(Hello,World)

 

我覺得自己的目標很混亂,總是看這個又看那個.雖說這個習慣不好,可是也增加了許多見識.

今天嘗試編寫內核模塊,寫了一個hello,world,結果弄了1個小時。

主要參考了網上的人的說明,結果發現盡信書不如無書,很多人說的都不是很仔細,我覺得這對於初學者來說,很不好。

大家貼出來的東西,不僅僅給自己也是給別人,所以有時候一定要嚴謹,否則很可能誤導別人。

首先貼出代碼 


 1// 這兩個頭文件包含相應宏定義
 2#include <linux/init.h>
 3#include <linux/module.h>
 4// 告知內核,這是free模塊
 5MODULE_LICENSE("GPL");
 6
 7// 模塊進入函數
 8static int __init hello_init(void){
 9        printk(KERN_ALERT "Hello World/n");
10        return 0;
11}

12
13// 模塊退出函數
14static void __exit hello_exit(void){
15        printk(KERN_ALERT "Hello World exit/n");
16}

17
18// 初始化
19module_init(hello_init);
20// 退出 
21module_exit(hello_exit);
22// 作者聲明
23MODULE_AUTHOR("Di Zhuang");
24MODULE_DESCRIPTION("A simple Hello World Module");
25MODULE_ALIAS("a simplest module");

 那麼代碼是很簡單的,問題出現在編譯上,網上很多人說要在編譯的內核下編譯,這個我不太懂,可能是編譯後生成了我們所需要的文件?我是按照linux源代碼Documention目錄下面kbuild下的modules.txt和網上另一位仁兄的makefile寫的,之前我很多人說用gcc -D__KERNEL__ -DMODULE -DLINUX -I{"你的linux源程序目錄"} -c -o 這種編譯的,結果錯誤一大堆,上網搜索,結果也沒誰說出準確的解決方案,都是說自己解決,可我覺得這可能和不同的環境有關,很可能就是你的環境適合你的解決辦法,爲什麼沒人能夠說出一種通用的解決辦法。上面的辦法貌似聽說在2。4內核好用,我2.6還沒搞明白,估計這東西在2.6上不適合吧。

那麼還是採用2.6官方文檔和網上成功編譯人的方案,那就是寫個Makefile,寫好編譯路徑,以及模塊編譯後放置的路徑。insmod貌似總從/lib/modues/目錄下加載模塊的,至於make工具如何保證我們編譯的模塊一定能夠被正確加載,這個我暫時沒研究,以後研究一下。

下面把Makefile文件貼出來

ifneq ($(KERNELRELEASE),)
obj
-m := {你要編譯目標文件的名.o}
else
# modules所在目錄
KERNELDIR :
= /lib/modules/`uname -r`/build
default:
        $(MAKE) 
-C $(KERNELDIR) M=`pwd` modules
endif

 對於這段語句,說實話,我能明白,可不太知道爲什麼要if else 這麼寫,誰能解答一下? 

寫好之後,運行make,然後就會發現你當前目錄多了很多文件,其中一個就是.ko文件,這個就是我們需要的。

好,現在運行insmod ./你的ko文件

網上很多人會說打出什麼打印語句,結果我在控制檯什麼也沒看見,後來才知道,這個需要用dmesg | tail命令來看

好像insmod打印重定向了??????

之後你在運行rmmod ./你的ko文件

OK , 大功告成。

說來,一個Hello,World模塊書寫真老費時間。。。。。。。。 

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

(1) 模塊動態加載驅動方式

在內核源碼的“drivers/char/”目錄下新建一個名爲“hello .c”的文件,內容如下:

 

 

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

 

MODULE_LICENSE ("GPL");

 

static int __init hello_init (void)

{

   printk (KERN_INFO "Hello world/n");

   return 0;

}

 

static void __exit hello_exit (void)

{

   printk (KERN_INFO "Goodbye world/n");

}

 

module_init (hello_init);

module_exit (hello_exit);

 

   修改Makefile裏面的內核源碼包的路徑,這裏我們必須用到一個已經編譯好的內核的源碼

這裏我們用了

KERNELDIR ?= /mnt/mengyang/source/kernel/linux-2.6.33

根據自己的實際情況修改,一定確保你的內核可以編譯通過,內核可以正常運行!

在命令行裏運行make命令,順利的會生成*.ko文件。將*.ko文件複製到nfs目錄,或是其他的存儲設備。

在命令行裏運行插入模塊的命令

insmod *.ko

順利的可以看到init函數將會被調用。

同樣,運行

rmmod *.ko

順利的可以看到clean函數被執行了。

執行上面命令時,可能報錯誤rmmod: chdir(2.6.33.2-TE2440): No such file or directory

這是由於busybox 1.13.1導致的,,原來是現在的內核模塊在插入卸載時都會要轉到/lib/modules/內核版本號目錄裏。 所以只要建立這個目錄並且把要使用的模塊*.ko文件複製到這個目錄就行了。

2)靜態的加載驅動

在內核源碼中添加對hello 驅動的支持

修改drivers/char/目錄下的“Kconfig”文件,在行添加如下內容:(紅色部分所示)

#

# Character device configuration

#

menu "Character devices"

config CCTE_HELLO

tristate "CCTE2440 Hello Driver"

depends on ARCH_S3C2440

help

CCTE2440 Hello.

修改同目錄下的“Makefile”文件,在合適的行添加如下內容:

#

# Makefile for the kernel character device drivers.

 

#

#

# This file contains the font map for the default (hardware) font

#

obj-$(CONFIG_ CCTE_HELLO) += hello.o

 

配置內核

然後輸入:#make menuconfig,然後配置如下:

Device Drivers --->

Character devices --->

<*> CCTE2440 Hello Driver

將其選擇爲“M”(模塊),然後保存配置,編譯出內核鏡像燒寫到開發板中。或是下載到開發板上運行。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章