//
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
int misc_register(struct miscdevice * misc);//注冊為雜項設備
int misc_deregister(struct miscdevice *misc);//注銷
miscdevice的數據結構如下圖所示:
int misc_register(struct miscdevice * misc)
{
struct miscdevice *c;
dev_t dev;
int err = 0;
INIT_LIST_HEAD(&misc->list);// // 初始化鏈表頭,將misc->list的next和pre都指向自己
mutex_lock(&misc_mtx);// 獲取互斥鎖, or睡眠
list_for_each_entry(c, &misc_list, list) { // 遍歷整個misc_list鏈表,所有的雜項驅動設備都有一個miscdevice數據結構,這些雜項驅動設備通過一個全局的misc_list鏈表連在一起, 相當一個記錄
if (c->minor == misc->minor) {// 如果misc_list中已經有了這個設備(minor相同),則解鎖返回,這里c是遍歷時的tmp miscdevice,指向當前遍歷節點
mutex_unlock(&misc_mtx);
return -EBUSY;
}
}
if (misc->minor == MISC_DYNAMIC_MINOR) { // 如果misc_list中沒有該設備,判斷minor是否準備動態分配,實驗中如此設置
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);// misc_minors是雜項設備位圖,總共有64個位DYNAMIC_MINORS=64,表示可以注冊64個雜項設備,這句代碼找到位圖中的空閑位置(表示還能加新設備)
if (i >= DYNAMIC_MINORS) {// 如果超過總設備數,則解鎖返回
mutex_unlock(&misc_mtx);
return -EBUSY;
}
misc->minor = DYNAMIC_MINORS - i - 1;// 計算子設備號,賦值到misc->minor
set_bit(i, misc_minors);// 對應的位圖也置位
}
dev = MKDEV(MISC_MAJOR, misc->minor); // 生成設備號
misc->this_device = device_create(misc_class, misc->parent, dev,
misc, '%s', misc->name);// 在sysfs中創建并注冊一個設備,可以在/dev下面看到misc->name
if (IS_ERR(misc->this_device)) {
int i = DYNAMIC_MINORS - misc->minor - 1;
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
err = PTR_ERR(misc->this_device);
goto out;
}
/*
* Add it to the front, so that later devices can 'override'
* earlier defaults
*/
list_add(&misc->list, &misc_list);// 以上操作都沒有問題后,將新設備加入misc_list鏈表,解鎖返回
out:
mutex_unlock(&misc_mtx);
return err;
}
/**
* misc_deregister - unregister a miscellaneous device
* @misc: device to unregister
*
* Unregister a miscellaneous device that was previously
* successfully registered with misc_register(). Success
* is indicated by a zero return, a negative errno code
* indicates an error.
*/
int misc_deregister(struct miscdevice *misc)
{
int i = DYNAMIC_MINORS - misc->minor - 1;
if (list_empty(&misc->list))
return -EINVAL;
mutex_lock(&misc_mtx);
list_del(&misc->list);
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
mutex_unlock(&misc_mtx);
return 0;
}
在Linux初始化期間會執行misc_init();
static int __init misc_init(void)
{
int err;
#ifdef CONFIG_PROC_FS //在proc文件系統下創建一個'misc'目錄。 misc_proc_fops是該文件系統下文件的操作函數集
proc_create('misc', 0, NULL, &misc_proc_fops);
#endif
misc_class = class_create(THIS_MODULE, 'misc'); // 前面device_create()中的misc_class就是在這里初始化的
err = PTR_ERR(misc_class);
if (IS_ERR(misc_class))
goto fail_remove;
err = -EIO;
if (register_chrdev(MISC_MAJOR,'misc',&misc_fops))//注冊一個主設備號為MISC_MAJOR(10)的字符設備,設備操作函數集為misc_fops
goto fail_printk;
misc_class->devnode = misc_devnode;
return 0;
fail_printk:
printk('unable to get major %d for misc devicesn', MISC_MAJOR);
class_destroy(misc_class);
fail_remove:
remove_proc_entry('misc', NULL);
return err;
}
上一篇:Linux下GPIO驅動(四) ----gpio_request();gpio_free();
下一篇:LED字符設備驅動實例及測試代碼
推薦閱讀最新更新時間:2025-04-23 20:42




設計資源 培訓 開發板 精華推薦
- 使用 Microchip Technology 的 SY58024U 的參考設計
- WS2812光魔方改進版
- LTC3633AIFE-3 1.8V/2.5V 4MHz 降壓穩壓器的典型應用電路
- 2020fpc轉接板 用于各種間距的液晶屏轉接測試板
- 使用 LTC2901-2 監視輸入、輸出、反饋電壓
- 使用 Analog Devices 的 LT3663EDCB-5 的參考設計
- 用于白光 LED 驅動器的 TB62755FPG 升壓型 DC/DC 轉換器的典型應用
- 基于SL2.1A的USB2.0HUB拓展塢
- 具有低噪聲、低失真差分放大器的 LTC6605-7 雙路匹配 7MHz 濾波器的典型應用
- 使用 Asahi Kasei Microdevices Corporation 的 AK4220VQP 的參考設計
- 高通攜手中國“汽車朋友圈”亮相2025上海車展: 加速駕駛輔助普惠,推動艙駕創新升級
- 工業市場正在快速回暖,德州儀器如何重塑電力電子市場?
- 特斯拉:美國交付的Model Y/3電池包已實現100%美國生產
- 地平線與博世深化合作,攜手為多家車企提供輔助駕駛產品
- 強化中國市場戰略布局,德州儀器正靈活應對全球關稅挑戰
- Molex莫仕通過本地合作和創新加強支持中國汽車行業
- 貿澤開售Texas Instruments適用于高分辨率AR HUD的 全新DLP4620S-Q1 0.46"汽車數字微鏡器件
- ROHM推出高功率密度的新型SiC模塊,將實現車載充電器小型化!
- 用上車規級UFS 4.0,讓出行變得高效且可靠
- 車載測試技術解析:聚焦高帶寬、多通道同步采集與協議分析