1. 程式人生 > >Linux裝置驅動程式(第三版)讀書筆記1,hello world

Linux裝置驅動程式(第三版)讀書筆記1,hello world

1.構建一個核心樹

說是要2.6核心的原始碼書,所以就去kernel.org下載一個2.6的核心linux-2.6.32.63.tar.xz

xz -d linux-2.6.32.63.tar.xz
tar -xvf  linux-2.6.32.63.tar
cd linux-2.6.32.63
make oldconfig #配置原版
make -j4  @編譯核心(此過程耗時長,編譯完後在linux-2.6.32.63多出一個vmlinux,jN代表用幾個執行緒來編譯)

//make
  -j4  modules #編譯模組,2.6核心並不需要再單獨編譯了,make已經做過了
make modules_install  安裝模組(操作結束後多出目錄/lib/modules/2.6.32.63)

,, 

make install #安裝2.6核心的系統中,會自動安裝核心並更新grub

2.重啟

進入grub啟動項,沒有倒計時的話開機一直按shift鍵或者是esc鍵,啟動2.6核心。

這裡我編譯的核心啟動後貌似卡死在紫色螢幕,所以我暫時先放棄了啟動2.6核心,嘗試ubuntu12.4自帶的3.5核心吧。(ps,後續重新編譯了一次,能進入2.6核心了)

3. uname -r 可以看到啟動後核心

 3.5.0-23-generic

4.測試hello,world
①、hellomod.c

#include<linux/init.h>  //初始換函式
#include<linux/kernel.h>  //核心標頭檔案
#include<linux/module.h>  //模組的標頭檔案
MODULE_LICENSE("Dual BSD/GPL");
 
static int hello_init(void)
{
 printk(KERN_ALERT "Hello,world\n");
 return 0;
}

static void hello_exit(void)
{
 printk(KERN_ALERT "Goodbye,Cruel world \n");
}

module_init(hello_init);
module_exit(hello_exit);
</pre><pre name="code" class="cpp"><pre name="code" class="html">②、Makefile
obj-m := hello.o
KVERSION = $(shell uname -r) #這裡編譯<span style="white-space: pre;">核心版本可以ls /lib/modules看一下</span>
all:
	make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

會在目錄下生成hello.ko檔案
無錯誤的輸出:
make -C /lib/modules/3.5.0-23-generic/build M=/home/u/桌面 modules
make[1]: 正在進入目錄 `/usr/src/linux-headers-3.5.0-23-generic'
  Building modules, stage 2.
  MODPOST 1 modules
make[1]:正在離開目錄 `/usr/src/linux-headers-3.5.0-23-generic'


$ modinfo hello.ko

filename:       hello.ko
license:        Dual BSD/GPL
srcversion:     800BA9CD509F78BD1257A18
depends:        
vermagic:       3.5.0-23-generic SMP mod_unload modversions -

$ uname -r

3.5.0-23-generic

④、插入核心並檢視insmod hello.ko

#發現沒有hello world  

#原因書上介紹了由於是虛擬終端,資訊不會顯示出來,而是存到系統日誌中檢視日誌:

tail -f /var/log/kern.log  

Jul 22 17:08:25 u-VirtualBox kernel: [ 5634.200312] Hello,world!

#切換到黑視窗很清楚的看到這個現象

或者cat  /var/log/messages   #發現沒有這個檔案,文件說不同的 linux可能路徑不同,ubuntu解決辦法是在最下面。

直接用下面這個命令看已經載入的模組

$ lsmod

ModuleSize  Used by   hello                  12497  0 [permanent] #這個永久的意思包含的資訊量太大了

                                       vesafb                 13846  1 

⑤移除模組sudo rmmod hellomod

ERROR: Module hellomod does not exist in /proc/modules

#錯誤應該是來自於[permanent] 這裡 應該是無法被解除安裝!#經測試重啟後會消失掉!

原因:系統預設的核心使用gcc版本與當前編譯模組的gcc不同導致。   

忽然想起來了編譯安卓的時候把預設的GCC改成4.4了。。然後我們還是繼續看一下。

$ cd  /lib/modules/`uname -r`/build/include/generated/

$ cat compile.h 

/* This file is auto generated, version 35~precise1-Ubuntu */

/*SMP */#define UTS_MACHINE "x86_64"#define UTS_VERSION "#35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013"

#define LINUX_COMPILE_BY "buildd"

#define LINUX_COMPILE_HOST "komainu"

#define LINUX_COMPILER "gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) "

可以看到官方編譯的gcc版本為 4.6.3$gcc -vgcc version 4.4.7 (Ubuntu/Linaro 4.4.7-1ubuntu2) //發現了吧,然後解決辦法。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

解決辦法(測試成功)

ls -al /usr/bin/gcc*

   lrwxrwxrwx 1 root root     7  7月 16 10:57 

  /usr/bin/gcc -> gcc-4.4-rwxr-xr-x 1 root root 259232  4月 16  2012

  /usr/bin/gcc-4.4-rwxr-xr-x 1 root root 353216  4月 16  2012 

  /usr/bin/gcc-4.6lrwxrwxrwx 1 root root      7  7月 15 16:10

 /usr/bin/gcc.bak -> gcc-4.6  

那麼很簡單了把gcc這個軟連線指向gcc-4.6就ok了,

之前我有備份直接改一下名字就可以了

建立軟連線的方法:ln -s /usr/bin/gcc-4.6 /usr/bin/gcc

重新編譯lsmod一下:

Module                  Size  Used byhello                   12497  0

 rmmod hello

沒有出現提示錯誤檢視一下日誌吧,

tail-f /var/log/kernel.0

Jul 22 18:04:47 u-VirtualBox kernel: [   69.715499] Hello,worldJul 22 18:06:00 u-VirtualBox kernel: [  142.161470] Goodbye 

————————————————————————————————————————————————————————————

版本2:

//關於載入模組時指定模組引數的值

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

MODULE_LICENSE("Dual BSD/GPL");
static char *whom = "world";
static int howmany = 1;
//module_param巨集在moduleparam.h定義,charp字元指標,
//最後一個引數是許可權掩碼作為輔助的sysfs入口
//insmod hello howmany=10 whom="hello" 這樣改變模組引數
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO); 
//bool invbool charp int long short uint ulong ushort
//陣列 module_param_array(name,type,num,perm)
//1.陣列名 2.陣列元素型別 3.長度  4.許可權值

static int hello_init(void)
{
	int i;
	for (i = 0; i < howmany; i++)
		printk(KERN_ALERT "(%d) Hello, %s\n", i, whom);
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ps::
ubuntu12.04沒有/var/log/messages解決
 
因為出錯了找不到這個檔案,很奇怪,因為網上介紹說檢視這個檔案的
 
然後百度,發現有些版本是沒有,不過ubuntu的可以有
 
編輯/etc/rsyslog.d/50-default.conf
 
其中有這麼一段
 
*.=info;*.=notice;*.=warn;\
    auth,authpriv.none;\
    cron,daemon.none;\
    mail,news.none        -/var/log/messages
 
這是本來就有,卻被註釋了。現在解註釋就行
 
儲存後重啟服務:sudo restart rsyslog