Linux驅動編程必備基礎知識
時間:2023-10-12 來源:華清遠見
一、內核空間和用戶空間
用戶空間和內核空間參數對應關系

用戶空間->內核空間(write)
int copy_from_user(void *to, const void __user volatile *from, unsigned long n)
函數功能:將數據從用戶空間拷貝數據到內核空間
參數: to:內核空間的首地址
from:用戶空間首地址 (__user:給編譯器使用,告訴編譯器這是一個用戶空間的地址)
n:拷貝字節的大小(單位字節)
返回值:成功返回0,
失敗返回未拷貝的字節個數 錯誤碼:EIO,找到內核中的錯誤碼
內核空間->用戶空間(read)
int copy_to_user(void __user volatile *to, const void *from, unsigned long n)
函數功能:將內核空間數據拷貝到用戶空間
參數: to:用戶的地址
from:內核地址 (__user:給編譯器使用,告訴編譯器這是一個用戶空間的地址)
n:拷貝字節的大小
返回值:成功返回0,失敗返回未拷貝的字節個數
二、模塊
Linux內核模塊分為:入口、出口、許可證
入口:資源的申請工作,在驅動安裝insmod的時候執行
出口:資源釋放工作,在驅動卸載rmmod的時候執行
許可證:驅動需要遵循GPL協議(開源)
三、設備模塊分類:字符設備和塊設備
設備管理
i) 字符設備:按照字節流來訪問,并且順序訪問的設備
ii) 塊設備:按照block(512字節)來訪問設備,可以順序訪問,也可以無序訪問
iii) 網卡設備:網卡沒有設備節點,接收網絡協議棧發來的數據,將這些數據向網線上收發即可,網絡驅動沒有設備文件 網卡設備早于Linux內核設備
四、驅動程序框架

五、錯誤和消息打印
應用層是使用printf來打印信息 內核中使用printk來打印信息
如何查看打印級別 以下為printk打印級別:

2、在Linux內核中將打印的信息分為8個級別,分別是0~7,數字越小級別越高,內核中這個打印級別是用于過濾信息的
3、打印格式: printk(打印級別 "打印信息\n"); 或者 printk("打印信息\n");---->使用默認的消息級別 總結:內核中的printk用法和printf用法除了打印級別之外都是一樣的,這個打印級別是用來過濾打印信息
4、printk打印的內容屬于消息,消息的級別在內核中一共有8種,數值越小優先級越高 消息有消息的級別,終端也有終端的級別,只有消息級別大于終端級別的時候,消息才會在終端顯示
5、默認的消息打印級別: 命令查看:cat /proc/sys/kernel/printk 打印信息:4 4 1 7 終端級別 默認消息級別 終端最大級別 終端最小級別
6、如何進行修改默認消息級別 su root echo 4 3 1 7 > /proc/sys/kernel/printk 備注:sudo passwd root (更改ubuntu密碼)
7、如何進入虛擬終端 如何進入虛擬終端 進入虛擬終端:ctrl+Fn+alt[F2-F7] 推出終端:ctrl+Fn+alt+F1
8、主動查看打印信息:dmesg sudo dmesg -C:直接清除打印信息 sudo dmesg -c:先回顯所有的打印信息后,在清除打印信息 內核從啟動到現在的時間,時間為s 。
六、模塊參數
內核模塊為什么需要傳參?
1.編譯通過傳參不需要每次都給變量的值
2.有些驅動廠商不提供源代碼,直接提供.ko驅動模塊,驅動中具體的數據通過傳參的形式更改
接收命令行參數
函數原型:module_param(name, type, perm)
功能:用于接收安裝驅動時命令行傳遞過來參數
參數:
name:變量名
type:變量的類型
perm:修飾的是
sys目錄下文件的權限(0664/0444)
對變量進行描述
MODULE_PARM_DESC(_parm, desc)
功能:對變量進行描述(modinfo命令查看)
參數:
param:被描述的變量
desc:描述字段,也就是需要描述的內容
接收向內核模塊傳遞的數組
函數原型:module_param_array(name, type, nump, perm)
功能:接受向內核模塊傳遞的數組
參數:
name:數組名
type:數組成員的類型
nump:變量的地址(用戶獲取用戶傳遞的參數個數)
perm:權限

