Linux 裝置驅動模型中的class(類)

來源:互聯網
上載者:User

    首先,想說明一下,促使我研究class(類)的是因為它能夠自動建立/dev下的裝置節點。當然class還有其另外的作用,且自動建立裝置節點的還有udev系統,udev是處於使用者空間的,其自動建立裝置節點也是依賴於sysfs檔案系統中提供的class類,我有個問題,如果我的核心沒有移植好udev系統,只是利用class(類),能不能夠自動建立裝置節點呢???針對這樣一個問題,想寫這個文章理清理清一下思路。

    一個類是一個裝置的進階視圖, 它抽象出低級的實現細節. 驅動可以見到一個SCSI 磁碟或者一個 ATA 磁碟, 在類的層級, 它們都是磁碟. 類允許使用者空間基於它們做什麼來使用裝置, 而不是它們如何被串連或者它們如何工作.

    幾乎所有的類都在 sysfs 中在 /sys/class 下出現. 因此, 例如, 所有的網路介面可在 /sys/class/net 下發現, 不管介面類型. 輸入裝置可在 /sys/class/input 下, 以及串列裝置在 /sys/class/tty. 一個例外是塊裝置, 由於曆史的原因在 /sys/block. 

    早期的Linux核心(版本2.4之前)並沒有實現一個統一的裝置模型,裝置節點的建立一般是mknod命令手動建立或利用devfs檔案系統建立。早期的Linux發行版一般會採用手動建立的方式預先把通常用到的節點都建立出來,而嵌入式系統則會採用devfs的方式。起初Linux2.6 核心還支援devfs,但從2.6.18開始,核心完全移除了devfs系統而採用的udev的方式動態建立裝置節點。因此,新的Linux發行版都採用udev的方式管理裝置節點檔案。

     udev 依靠所有通過 sysfs 輸出給使用者空間的裝置資訊, 並且依靠被 /sbin/hotplug 通知有裝置添加或去除. 策略決策, 例如給一個裝置什麼名子, 可在使用者空間指定, 核心之外. 這保證了命名策略被從核心中去除並且允許大量每個裝置名稱子的靈活性.

     現在來驗證一下,class類是怎樣自動建立裝置節點的。代碼如下:

注意,首先申明一下,在看ldd3的時候,書上說的class的相關介面是class_simple,比如:class_simple_create()、class_simple_destory()、class_device_create()、class_device_destory()等,經我查看,我這是Linux2.6.31版本的核心,裡面沒有這些介面,這些介面都被修改成了class_create()、class_destroy()、device_create()、device_destory()等。相關介面可以自己去查看核心原始碼。

#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");

    上述代碼中標註紅色的為class類自動建立裝置節點的代碼。下載到開發板上運行,我們可以查看/dev目錄、/sys/class/目錄,看是否有/dev/hello、/sys/class/hello_class這樣的目錄。

    經過哥的驗證,在dev、sys/class目錄下都會有相應的節點。可以說明一下,我的檔案系統裡並沒有移植好udev系統。那就是說,class可以自動建立裝置節點,不需要udev,而udev自動建立節點需要用到class。

    為了證明我一開始的疑問,需要去深入class_create()、device_create()的源碼探索了。

可以肯定,sys/class中節點的建立是在struct class的註冊函數裡,/dev/節點的建立也應該在device的註冊函數裡

日後分析。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.