錯誤處理
把device item (通常會用指標指向一個struct表示)加入kernel的過程,也就是註冊(registeration),(此刻會在 /dev/ 目錄底下建立一個檔案),是可能失敗的,比如要求的記憶體目前不可用
所以必須時刻確認呼叫module的return value,確認行為都是正確執行的
goto
一般而言goto會破壞程式的可讀性與架構
但在錯誤處理時卻是比較簡明的寫法 (比如 try , catch , try expect …)
以下為註冊ini函式練習
int __init my_init_function(void)
{
int err;
/* registration takes a pointer and a name */
err = register_this(ptr1, "skull");
if (err) goto fail_this;
err = register_that(ptr2, "skull");
if (err) goto fail_that;
err = register_those(ptr3, "skull");
if (err) goto fail_those;
return 0; /* success */
fail_those: unregister_that(ptr2, "skull");
fail_that: unregister_this(ptr1, "skull");
fail_this: return err; /* propagate the error */
}
這邊要注意, return 值被稱為__error code__
被定義於 linux/errno.h 中
通常是負數, (也就是為甚麼main function會return 0)
這些負數值在顯示時,user programs一般都會轉換成有意義的錯誤訊息字串
當然,如果今天要註冊的item很多或很複雜,可以額外一個cleanup function
在error發生時,goto這個function
race condition
要注意就算是這個module註冊的設備,也很有可能被其他module拿去使用
所以最好是在註冊完立刻使用,也就是說,最好在要使用時才註冊
Module parameters
module可以透過insmod , modprobe在插入時接收參數,如
insmod hellop howmany=10 whom="Mom
可以泛化為
insmod <module> <arg1>=xxx <arg2>=xxx ...
module也可以在內部傳這些參數
要透過moduleparam.h 的module_param 巨集函數
會接收,variable name , type , permissions mask
比如 module_param(howmany, int, S_IRUGO);
parameter type
- bool
- invbool invert bool , 真值會為false , 假值會為true
- charp char pointer value,存user-provided strings
- int
- long
- short
- uint
- ulong
- ushort
比uint還短的整數
array
格式
module_param_array(name,type,num,perm);
分別收 陣列名、元素型態、元素個數、permissions value
permission value
可以參考 linux/stat.h
可以決定該變數的存取權
比如 perm == 0 L 沒有任何sysfs entry(文件系統)
perm == S_IRUGO 則大家都可以使用,但不能修改
perm == S_IRUGO|S_IWUSR 則root可以修改
通常都會不允許修改
參考資料
Ch2: Building and Running Modules
https://lwn.net/Kernel/LDD3/