字元裝置驅動程式之自動建立裝置節點

來源:互聯網
上載者:User
原文:
http://liu1227787871.blog.163.com/blog/static/20536319720128901736417/

#include <linux/fs.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/device.h>static struct class *led_class;
int led_open(struct inode *inode, struct file *file){    printk("led_open\n");    return 0;}ssize_t led_write(struct file *file, const char __user *user, size_t size, loff_t *off){    printk("led_write\n");    return 0;}
static struct file_operations led_operation = {    .owner=THIS_MODULE,    .open=led_open,    .write=led_write,   };int major;int led_init(void){    major=register_chrdev(0,"led",&led_operation);
    led_class = class_create(THIS_MODULE, "led_class");
    device_create(led_class, NULL, MKDEV(major, 0), NULL,"led_device");    return 0;}
void led_exit(void){    unregister_chrdev(major,"led");    device_destroy(led_class,MKDEV(major, 0));    class_destroy(led_class);    }
module_init(led_init);module_exit(led_exit);MODULE_LICENSE("GPL");
主要思路:先建立一個類,在類下建立裝置!這樣我們就不需要在開發板上查看主裝置號,然後手動建立裝置節點了!在開發板上:ls /sys/class/會看到我們建立的類,ls /sys/class/led_class/會看到我們在類下建立的裝置!不過真正的裝置節點在/dev目錄下面,通過命令:ls /dev/led_device可以查看到!需要注意的是,我們在編寫應用程式的時候,open函數裡面的裝置名稱字要跟驅動裡面device_create指定的裝置名稱字相一致!
但是,系統做了什麼呢?在開發板的/etc/init.d/rcS檔案裡面有如下的資訊:

echo /sbin/mdev > /proc/sys/kernel/hotplugmdev -s這兩行資訊就是說,一旦發生了熱插拔事件(比如建立了類,在類下建立了裝置),就會調用/sbin/mdev命令,mdev命令會通過環境變數中的 ACTION 和 DEVPATH來判斷此次熱插拔事件影響了/sys目錄下的那個檔案,一旦發現了這個檔案,就會進入這個檔案裡面去尋找dev的屬性檔案,並根據屬性建立裝置節點!比如我們載入驅動的的時候,會在  /sys/class/目錄下建立類,在 /sys/class/led_class目錄下建立裝置,在

/sys/class/led_class目錄下有個dev檔案,dev檔案裡面就有裝置的主次裝置號,mdev就會根據主次裝置號在/dev/目錄下建立裝置節點!

============================分割線===========================================

問題: cannot create duplicate filename xxxxx

我遇到的問題是: 在模組卸載的時候我已經調用了
    unregister_chrdev_region(devno, 1); //release dev number    cdev_del(&firstcdev); //del char device    class_destroy(myclass); //del class    device_destroy(myclass, devno); //del device


可是在重新載入模組的時候還是會提示cannot create duplicate filename xxxxx
然後認真想了一下,發現有可能是釋放的順序不對,改成了下面的順序之後就可以了。

    unregister_chrdev_region(devno, 1); //release dev number    device_destroy(myclass, devno); //del device    class_destroy(myclass); //del class    cdev_del(&firstcdev); //del char device

並附上我自己寫的代碼:

#include <linux/miscdevice.h>#include <linux/delay.h>#include <asm/irq.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/string.h>#include <linux/list.h>#include <linux/pci.h>#include <linux/gpio.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <asm/unistd.h>#include <linux/device.h>//device name#define DEVNAME "ledctl"//cdevstruct cdev firstcdev;dev_t devno;//for auto creata device filestruct class *myclass;static int first_drv_open(struct inode *inode, struct file *file){printk("first_cdrv_open\n");s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT); //GPB5 out modes3c2410_gpio_setpin(S3C2410_GPB(5), 0);  //led1 onreturn 0;}static int first_drv_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos){printk("first_cdrv_write\n");int val;copy_from_user(&val, (int *)buf, sizeof(int));printk("val from user is %d\n", val);s3c2410_gpio_setpin(S3C2410_GPB(5), (val == 0 ? 1 : 0)); //val=1 led1 onreturn 0;}static struct file_operations first_drv_fops = {    .owner  =   THIS_MODULE,        .open   =   first_drv_open,     .write=   first_drv_write,   };static int first_drv_init(void){cdev_init(&firstcdev, &first_drv_fops);//init cdevalloc_chrdev_region(&devno, 0, 1, DEVNAME);//alloc char device numbercdev_add(&firstcdev, devno, 1); //register char devicemyclass = class_create(THIS_MODULE, "ctlled"); //create /sys/class/ctlleddevice_create(myclass, NULL, devno, NULL, DEVNAME); //auto create /dev/ledctlprintk("firstdrvcdev initialized.\n");return 0;}static void first_drv_exit(void){unregister_chrdev_region(devno, 1); //release dev numberdevice_destroy(myclass, devno); //del deviceclass_destroy(myclass); //del classcdev_del(&firstcdev); //del char device}module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");

其他參考資料: http://blog.csdn.net/garby2004/article/details/4603996
                             http://blog.csdn.net/jianchi88/article/details/6848035

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.