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.kolicense: 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