1.主設備號和次設備號
對字符設備的訪問是通過文件系統內的設備名稱進行的。通常位於/dev/目錄下。
對於設備文件,ls -l命令可以看到兩個數,就是相應設備的主設備號和次設備號。
主設備號標識設備對應的驅動程序(driver)。次設備號由內核使用,用於正確確定設備文件所指的設備。
dev_t類型用來保存設備編號
MAJOR(dev_t dev) MINOR(dev_t dev) MKDEV(int major, int minor)
分配主設備號:
事先已知所需要的設備編號:register_chrdev_gegion
事先不知道設備使用的設備編號,動態分配:alloc_chrdev_region
釋放設備編號:unregister_chrdev_region
cat /proc/devices
mknod /dev/scull0 c $major 3
設備節點的訪問策略
*分配主設備號的最佳方式是:默認採用動態分配,同時保留在加載甚至是編譯時指定主設備號的餘地。
三個重要的內核數據結構
file_operations file inode
file_operations:用來將驅動程序操作連接到設備編號。
面向對象編程的例證:每個打開的文件(用struct file表示)和一組函數關聯(通常包含指向一個file_operations結構的f_op字段)。文件是一個“對象”,而操作它的函數是“方法”,對象聲明的動作將作用於其本身。
_ _user字符串:參數帶有_ _user字符串,表明指針是一個用戶空間地址,不能被直接引用
llseek read write ioctl mmap open release
file_operation結構初始化的形式:
struct file_operation scull_fops =
{
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scill_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file:file結構表示一個打開的文件。
inode:文件索引信息
字符設備的註冊
struct cdev結構表示字符設備
cdev_alloc() ——> cdev_init ——> cdev_add()
open和release方法
open應完成如下工作:
1.檢查設備特定的錯誤(如設備未就緒或類似的硬件問題)
2.如果設備是首次打開,則對其進行初始化
3.如有必要,更新f_op指針。
4.分配並填寫置於filp->private_data裏的數據結構
container_of
filp->private_data = dev
release方法
當關閉一個設備文件的次數比打開它的次數多時,系統中會發生什麼情況?例如大多數程序從來不打開它們的stdin文件(或設備),但它們都會在終止時被關閉。驅動程序如何才能知道一個打開的設備文件要被真正關閉?
答案很簡單:並不是每一個close系統調用都會引起release方法的調用。只有那些真正釋放設備數據結構的close調用纔會調用release。內核對每個file結構維護其被使用多少次的計數器,只有在file結構的計數歸0時,close系統調用纔會指向release方法。
scull的內存使用
對於驅動程序中任何不確定的或與策略相關的數組,用戶可以採用以下方法來修改:
編譯時,可以修改宏
模塊加載時,可以設置模塊參數
運行時,可以使用ioctl修改
read和write方法
read write方法的buff參數是用戶空間的指針。因此內核代碼不能直接引用其中的內容。
爲了確保安全,應該使用內核提供的專用函數:
copy_to_user
copy_from_user
scull的實現例程
readv和writev
這些“向量型”的函數具有一個結構數組,每個結構包含一個指向緩衝區的指針和一個長度值。
strace監視應用程序調用的系統調用以及它們的返回值。