Linux 设备驱动模型中的class(类)
首先,想說明一下,促使我研究class(類)的是因?yàn)樗軌蜃詣?dòng)創(chuàng)建/dev下的設(shè)備節(jié)點(diǎn)。當(dāng)然class還有其另外的作用,且自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)的還有udev系統(tǒng),udev是處于用戶空間的,其自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)也是依賴于sysfs文件系統(tǒng)中提供的class類,我有個(gè)問題,如果我的內(nèi)核沒有移植好udev系統(tǒng),只是利用class(類),能不能夠自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)呢???針對(duì)這樣一個(gè)問題,想寫這個(gè)文章理清理清一下思路。
??? 一個(gè)類是一個(gè)設(shè)備的高級(jí)視圖, 它抽象出低級(jí)的實(shí)現(xiàn)細(xì)節(jié). 驅(qū)動(dòng)可以見到一個(gè)SCSI 磁盤或者一個(gè) ATA 磁盤, 在類的級(jí)別, 它們都是磁盤. 類允許用戶空間基于它們做什么來使用設(shè)備, 而不是它們?nèi)绾伪贿B接或者它們?nèi)绾喂ぷ?
??? 幾乎所有的類都在 sysfs 中在 /sys/class 下出現(xiàn). 因此, 例如, 所有的網(wǎng)絡(luò)接口可在 /sys/class/net 下發(fā)現(xiàn), 不管接口類型. 輸入設(shè)備可在 /sys/class/input 下, 以及串行設(shè)備在 /sys/class/tty. 一個(gè)例外是塊設(shè)備, 由于歷史的原因在 /sys/block.?
??? 早期的Linux內(nèi)核(版本2.4之前)并沒有實(shí)現(xiàn)一個(gè)統(tǒng)一的設(shè)備模型,設(shè)備節(jié)點(diǎn)的創(chuàng)建一般是mknod命令手動(dòng)創(chuàng)建或利用devfs文件系統(tǒng)創(chuàng)建。早期的Linux發(fā)行版一般會(huì)采用手動(dòng)創(chuàng)建的方式預(yù)先把通常用到的節(jié)點(diǎn)都創(chuàng)建出來,而嵌入式系統(tǒng)則會(huì)采用devfs的方式。起初Linux2.6 內(nèi)核還支持devfs,但從2.6.18開始,內(nèi)核完全移除了devfs系統(tǒng)而采用的udev的方式動(dòng)態(tài)的創(chuàng)建設(shè)備節(jié)點(diǎn)。因此,新的Linux發(fā)行版都采用udev的方式管理設(shè)備節(jié)點(diǎn)文件。
???? udev 依靠所有通過 sysfs 輸出給用戶空間的設(shè)備信息, 并且依靠被 /sbin/hotplug 通知有設(shè)備添加或去除. 策略決策, 例如給一個(gè)設(shè)備什么名子, 可在用戶空間指定, 內(nèi)核之外. 這保證了命名策略被從內(nèi)核中去除并且允許大量每個(gè)設(shè)備名子的靈活性.???? 現(xiàn)在來驗(yàn)證一下,class類是怎樣自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)的。代碼如下:
注意,首先申明一下,在看ldd3的時(shí)候,書上說的class的相關(guān)接口是class_simple,比如:class_simple_create()、class_simple_destory()、class_device_create()、class_device_destory()等,經(jīng)我查看,我這是Linux2.6.31版本的內(nèi)核,里面沒有這些接口,這些接口都被修改成了class_create()、class_destroy()、device_create()、device_destory()等。相關(guān)接口可以自己去查看內(nèi)核源代碼。
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/fs.h> #define DEVNAME "hello" static dev_t dev; static struct class *hello_class; static struct cdev *hello_cdev; static int hello_open(struct inode *inode,struct file *flp) { return 0; } static int hello_close(struct inode *inode,struct file *flp) { return 0; } static struct file_operations hello_fops={ .owner=THIS_MODULE, .open =hello_open, .release=hello_close, }; static int __init hello_init(void) { int error; error = alloc_chrdev_region(&dev, 0, 2, "hello"); if (error) { printk("hello: alloc_chardev_region failed! "); goto out; } hello_cdev = cdev_alloc(); if (hello_cdev == NULL) { printk("hello: alloc cdev failed! "); error = -ENOMEM; goto out_chrdev; } hello_cdev->ops = &hello_fops; hello_cdev->owner = THIS_MODULE; error = cdev_add(hello_cdev, dev, 1); if (error) { printk("hello: cdev_add failed! "); goto out_cdev; } hello_class = class_create(THIS_MODULE, DEVNAME);if (IS_ERR(hello_class)) { error = PTR_ERR(hello_class); goto out_chrdev; } device_create(hello_class, NULL, dev, NULL, DEVNAME); //memset (hello_buf, 0, sizeof(hello_buf)); //memcpy(hello_buf, DEFAULT_MSG, sizeof(DEFAULT_MSG)); printk("hello: Hello World! "); return 0; out_cdev: cdev_del(hello_cdev); out_chrdev: unregister_chrdev_region(hello_cdev->dev, 2); out: return error; } static void __exit hello_exit(void) { device_destroy(hello_class, dev); class_destroy(hello_class); unregister_chrdev_region(hello_cdev->dev, 2); cdev_del(hello_cdev); printk("hello: Goodbye World "); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("YWW"); MODULE_DESCRIPTION("HELLO_CLASS_AUTO_DEV");
??? 上述代碼中標(biāo)注紅色的為class類自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)的代碼。下載到開發(fā)板上運(yùn)行,我們可以查看/dev目錄、/sys/class/目錄,看是否有/dev/hello、/sys/class/hello_class這樣的目錄。
??? 經(jīng)過哥的驗(yàn)證,在dev、sys/class目錄下都會(huì)有相應(yīng)的節(jié)點(diǎn)??梢哉f明一下,我的文件系統(tǒng)里并沒有移植好udev系統(tǒng)。那就是說,class可以自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn),不需要udev,而udev自動(dòng)創(chuàng)建節(jié)點(diǎn)需要用到class。
??? 為了證明我一開始的疑問,需要去深入class_create()、device_create()的源碼探索了。
可以肯定,sys/class中節(jié)點(diǎn)的創(chuàng)建是在struct class的注冊(cè)函數(shù)里,/dev/節(jié)點(diǎn)的創(chuàng)建也應(yīng)該在device的注冊(cè)函數(shù)里
日后分析。
總結(jié)
以上是生活随笔為你收集整理的Linux 设备驱动模型中的class(类)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wbe笔记
- 下一篇: linux下shell编程课程设计,Li