devfs(設備文件系統)是由Linux2.4內核引入的,它的出現主要使得設備驅動程式能夠自主管理自己的設備文件。具體來說,devfs具有如下優點: 可以通過程式在設備初始化時在/dev目錄下創建設備文件,卸載設備時將它刪除。 設備驅動程式可以指定設備名、所有者和許可權位,用戶空間程式仍可以修改所有者 ...
devfs(設備文件系統)是由Linux2.4內核引入的,它的出現主要使得設備驅動程式能夠自主管理自己的設備文件。具體來說,devfs具有如下優點:
可以通過程式在設備初始化時在/dev目錄下創建設備文件,卸載設備時將它刪除。
設備驅動程式可以指定設備名、所有者和許可權位,用戶空間程式仍可以修改所有者和許可權位。
不再需要為設備驅動程式分配主設備號以及處理次設備號,在程式中可以直接給register_chrdev()
傳遞0主設備號以動態獲得可用的主設備號,併在devfs_register()
中指定次設備號。
創建設備目錄、設備文件以及刪除函數如下:
devfs_handle_t devfs_mk_dir(devfs_handle_t dir, const char *name, void *info);
devfs_handle_t devfs_register(devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, umode_t mode
void devfs_unregister(devfs_handle_t de);
使用devfs的例子如下:
static devfs_handle_t devfs_handle;
static int __init xxx_init(void)
{
int ret;
int I;
/*在內核中註冊設備*/
ret = register_chrdev(XXX_major, DEVICE_NAME, &xxx_fops);
if( ret < 0)
{
printk(DEVICE_NAME “ can’t register major number\n”);
return ret;
}
/*創建設備文件*/
devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT, xxx_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &xxx_fops, NULL);
…
printk(DEVICE_NAME “ initialized\n”);
return 0;
}
static void __exit xxx_exit(void)
{
devfs_unregister(devfs_handle);/*撤消設備文件*/
unregister_chrdev(XXX_MAJOR, DEVICE_NAME);/*註銷設備*/
}
module_init(xxx_init);
module_exit(xxx_exit);
在最新的Linux 2.6的內核中, devfs已經被拋棄,udev取代了它。udev取代devfs的幾點原因如下:
- devfs所做的工作被確信可以在用戶態來完成
- 一些bug相當長的時間內未被修複
- devfs的維護者和作者停止了對代碼的維護工作。
- udev完全在用戶態工作,利用設備加入或移除內核所發送的熱插拔事件來工作。在熱插拔時,設備的詳細信息會由內核輸入到位於/sys的sysfs文件系統。udev的設備名策略、許可權控制和事件處理都是在用戶態下完成的,它利用sysfs中的信息來進行創建設備文件節點工作。
- 由於udev根據系統中硬體設備的狀態動態更新設備文件、進行設備文件的創建和刪除等,因此,在使用udev後,在/dev目錄下就只包含系統中真正存在的設備了。
- devfs與udev的另一個顯著區別在於:採用devfs,當一個並不存在的/dev節點被打開的時候,devfs能自動載入對應的驅動,而udev則不能。這是因為udev的設計者認為Linux應該在設備被髮現的時候載入驅動模塊,而不是當它被訪問的時候。udev的設計者認為devfs所提供的打開/dev節點時自動載入驅動的功能對於一個配置正確的電腦是多餘的。系統中所有的設備都應該產生熱插拔事件並載入恰當的驅動,而udev能註意到這點並且為它創建對應的設備節點。
使用udev的例子如下:
#include <linux/device.h>
…
static struct class * xxx_class;
static int __init xxx_init(void)
{
int ret;
int i;
/*在內核中註冊設備*/
ret = register_chrdev(XXX_major, DEVICE_NAME, &xxx_fops);
if( ret < 0)
{
printk(DEVICE_NAME “ can’t register major number\n”);
return ret;
}
//註冊一個類,使mdev可以在"/dev/"目錄下麵建立設備節點
xxx_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("Err: failed in EmbedSky-leds class. \n");
return -1;
}
//創建一個設備節點,節點名為DEVICE_NAME
class_device_create(xxx_class, NULL, MKDEV(xxx_major, 0), NULL, DEVICE_NAME);
…
printk(DEVICE_NAME “ initialized\n”);
return 0;
}
static void __exit xxx_exit(void)
{
unregister_chrdev(XXX_MAJOR, DEVICE_NAME);/*註銷設備*/
class_device_destroy(xxx_class, MKDEV(xx_major, 0));//刪掉設備點
class_destroy(xxx_class); //註銷類
}
module_init(xxx_init);
module_exit(xxx_exit);
mdev是busybox自帶的一個簡化版的udev,適合於嵌入式的應用埸合。其具有使用簡單的特點。它的作用,就是在系統啟動和熱插拔或動態載入驅動程式時,自動產生驅動程式所需的節點文件。在以busybox為基礎構建嵌入式linux的根文件系統時,使用它是最優的選擇。