三、字符設備驅動(基于北京迅為電子)
一、概述
字符設備的驅動包括設備號、字符設備結構體、自動創建設備節點、fops結構體
二、知識點
- 設備號:一個32bit的數據,高12bit表示主設備號,低20bit表示次設備號
- 宏定義:
MAJOR(dev),MINOR(dev),MKDEV(ma,mi) - 分配設備號:
register_chrdev_region、alloc_chrdev_region前者靜態分配設備號,后者動態分配設備號 cat /proc/devices查看已經分配的設備號- 分配設備號
register_chrdev_region(dev_t, unsigned, const char*); // 起始設備號、數量、名稱
alloc_chrdev_region(dev_t*, unsigned, unsigned, const char*); // 保存申請到的設備號、起始次設備號、數量、名稱
unregister_chrdev_region(dev_t, unsigned); // 要釋放的設備號、要釋放的設備號的數量
- 注冊一個字符設備
struct cdev {
struct kobject kobj; // 父對象
struct module *owner; // 所有者
const struct file_operations *ops; // fops
struct list_head list; // 鏈表頭
dev_t dev; // 設備號
unsigned int count; // 數量
} __randomize_layout;
void cdev_init(struct cdev *, const struct file_operations *); // 初始化cdev結構體并關聯fops
int cdev_add(struct cdev *, dev_t, unsigned); // 關聯設備號和數量,并注冊cdev
void cdev_del(struct cdev *); // 注銷cdev
- 文件操作函數結構體
struct file_operations ;
應用層的open、read、write、close、ioctl函數均有驅動層的相應函數對應,這些函數指針都放在file_operation結構體中
- 創建設備節點
手動創建設備節點 mknod /dev/xxx c 250 0
struct class *cls = class_create(owner, name);
void class_destroy(struct class *cls);
device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
void device_destroy(struct class *cls, dev_t devt);
- 用戶空間和內核空間
通過系統調用、軟中斷、硬件中斷,進程由用戶空間陷入內核空間。兩個空間拷貝數據的API:copy_from_user和copy_to_user - file結構體的私有數據,一般驅動空間中會由一個自定義的結構體,這樣在open時設置file的private_data為該結構體實例對象的指針,在后續的read/write函數中通過訪問file的private_data就可以得到有用數據
container_of(type, struct, name);通過結構體成員的地址得到結構體的地址- 錯誤處理:使用goto完成不同階段的錯誤處理退出,使用IS_ERR判斷指針是否有效,通過PTR_TO_ERR將錯誤指針返回錯誤
三、雜項設備
- 雜項設備是無法歸類的一系列設備,主設備號都是10,用來避免主設備號的浪費
- 雜項設備不需要手動設置設備節點,實現相應的miscdevice結構體,填充name、minor和fops即可(minor使用MISC_DYNAMIC_MINOR表示動態申請次設備號)
- 實現miscdevice結構體之后,調用
misc_register就可以注冊一個雜項設備并自動生成設備節點 - 調用
misc_unregister注銷雜項設備
四、字符設備的驅動框架
- 定義cdev結構體
- 動態分配一個設備號
alloc_chrdev_region - 初始化cdev結構體并添加到系統中
cdev_init cdev_add - 設置自動創建設備節點
class_create device_create cdev_init時需要傳入fops,因此需要實現fops的幾個函數,open、read、write等等- 出口函數中需要反過來一步一步地注銷

浙公網安備 33010602011771號