地球人都知道LDD這書經典,但一直沒時間看(貌似是借口)現在開始啃,希望自己能堅持下去。God bless me!
要看到核心的列印資訊,可以先執行下面的語句:echo 8 > /proc/sys/kernel/printk
這裡,有blog不錯,可以學習下http://blog.chinaunix.net/u1/34474/showart_404278.html
由於驅動程式可能同時被不同的程式並發訪問,解決並發的一些方法:1.可以在裝置上實現獨立於硬體功能的記憶體映射。
2. 為使用者提供獨立的函數庫,運用同步原語。
3.裝置檔案和普通檔案之間的唯一區別在於:對普通檔案的訪問可以前後移動訪問訪問位置,但對大多數字元裝置檔案的訪問只能順序訪問。
4.許多網路連接是面向流的,但網路裝置卻圍繞資料包的傳輸和接受而設計。網路驅動程式不需要知道各個串連的相關資訊,他只要處理資料包即可。由於不是面向流的裝置,因此將網路介面映射到檔案系統中的節點比較困難,linux訪問網路介面的方法仍然是給他們一個唯一的名字(eth0),但這個名字在檔案系統中不存在對應的節點。核心和網路裝置的通訊,不同於字元和塊裝置,核心調用一套和資料包傳輸相關的函數,而不是read,write.
5.關於hello模組Makefile的寫法:
obj-m += hello.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
如果是多個原檔案編譯出一個模組,則不能出現.c 檔案。
obj-m += test.o
test.o := file1.o file2.o file3.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) m=$(PWD) clean
其中KDIR為核心存放的路徑,PWD當前路徑,uname -r為取得當前使用的核心配置。
6.現代的unix系統基本提供兩種保護方式:一種是特權級劃分,0到6個層級,ROOT的特權級最高。另一種是分頁保護機制,系統除了在啟動完成裝置初始化時運行在實模式下外,啟動起來會開啟MMU然後運行在保護模式下。
7.執行系統調用的核心代碼運行在進程上下文中,它代表調用進行執行操作,因此可以訪問進程地址空間裡的所有資料,而處理硬體中斷的核心代碼和進程是非同步,與任何一個特定進程無關。
8.modprobe和insmod的區別,它會考慮要裝載的模組是否引用了一些當前核心不存在的符號。如果有這類引用modprobe會在當前模組的收索路徑中尋找定義了這些符號的其他模組,如果找到這些相依模組會同時將這些模組載入到核心中。如果這種情況下用insmod,則會失敗。
9.大多數模組都必須包括的標頭檔:
#include <linux/moduel.h>
#include <linux/init.h>
#include <moduleparam.h>
10.如果在發生某個特定類型的錯誤以後無法繼續裝載模組,則要將出錯之前的任何註冊工作撤銷掉。
模組註冊程式碼範例:
#include <linux/module.h>
#include <linux/init.h>
#include <moduleparam.h>
struct something *item1;
struct somethingelse *item2;
int stuff_ok;
void my_cleanup()
{
if(item1)
release_thing(item1);
if(item2){
release_thing(item2);
if(stuff_ok)
unregister_stuff;
}
static int __init my_init(void)
{
int err;
item1 = allocate_thing(arguments);
item2 = allocate_thing(arguments2);
if(!item1 || !item2)
goto fail;
err = register_stuff(item1,item2);
if(!err){
stuff_ok = 1;
}else{
goto fail;
}
return 0;
fail:
my_cleanup();
return err;
}
11.include <linux/sched.h>
該檔案包含驅動驅動程式中使用的大部分核心API的定義,包括睡眠函數以及各種變數的聲明。
struct task_struct *current;
current->pid
current->comm
獲得當前進程的id和命令名
MAJOR(dev_t dev);
MINOR(dev_t dev);
MKDEV(int major,int minor);