Linux /dev 自动创建设备节点

udev的支持主要作用是:在驱动初始化的代码里调用class_create(...)为该设备创建一个class,再为每个设备调用device_create(...);

内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

下面写一个字符设备测试程序:

  1. #include <linux/module.h>  
  2. #include <linux/module.h>  
  3. #include <linux/kernel.h>  
  4. #include <linux/init.h>  
  5. #include <linux/fs.h>  
  6. #include <linux/cdev.h>  
  7. #include <linux/device.h>  
  8. #include <asm/uaccess.h>   
  9.   
  10. #define HELLO_MAJOR 250  
  11. #define HELLO_MINOR 0  
  12. #define NUMBER_OF_DEVICES 2  
  13.   
  14. struct class *hello_class;  
  15. static struct cdev cdev;  
  16. dev_t devno;  
  17.   
  18. static ssize_t hello_read(struct file *file, char __user *buf, size_t count,  
  19.                 loff_t *ppos)  
  20. {  
  21.     char *str = "hello world";  
  22.   
  23.     copy_to_user(buf,str,strlen(str));  
  24.     *(buf + strlen(str)) = '\n';  
  25.     return count;  
  26. }  
  27.   
  28. static ssize_t hello_open(struct inode *inode,struct file *file)  
  29. {  
  30.     return 0;   
  31. }  
  32.   
  33. static const struct file_operations hello_fops = {  
  34.         .open = hello_open,  
  35.         .read = hello_read,  
  36.         .owner = THIS_MODULE,  
  37. };  
  38.   
  39. static int __init hello_init(void)  
  40. {  
  41.     int ret;  
  42.     devno = MKDEV(HELLO_MAJOR,HELLO_MINOR);  
  43.   
  44.     if(HELLO_MAJOR){  
  45.         ret = register_chrdev_region(devno,NUMBER_OF_DEVICES,"chrdev");  
  46.     }else{  
  47.         ret = alloc_chrdev_region(&devno, 0, NUMBER_OF_DEVICES, "chrdev");  
  48.     }  
  49.     if(ret < 0){  
  50.         printk("%s register chrdev error\n",__func__);  
  51.         return ret;  
  52.     }  
  53.   
  54.     hello_class = class_create(THIS_MODULE,"hello_char_calss");  
  55.     if(IS_ERR(hello_class)){  
  56.         printk("%s create class error\n",__func__);  
  57.         return -1;  
  58.     }  
  59.   
  60.     device_create(hello_class, NULL, devno, NULL, "chrdev");  
  61.       
  62.       
  63.     cdev_init(&cdev, &hello_fops);  
  64.     cdev.owner = THIS_MODULE;  
  65.     cdev_add(&cdev, devno, NUMBER_OF_DEVICES);  
  66.   
  67.     return 0;  
  68. }  
  69.   
  70.   
  71. static void __exit hello_exit(void)  
  72. {  
  73.     printk("%s",__func__);  
  74.     cdev_del(&cdev);  
  75.     device_destroy(hello_class,devno);  
  76.     class_destroy(hello_class);  
  77.     unregister_chrdev_region(devno,NUMBER_OF_DEVICES);  
  78.   
  79. }  
  80.   
  81. module_init(hello_init);  
  82. module_exit(hello_exit);  
  83. MODULE_LICENSE("GPL");  
  84. MODULE_AUTHOR("weed<weed_hz@126.com>");  

Makefile:

ifeq ($(KERNELRELEASE),)
#KERNEL_DIR:=/lib/modules/$(shell uname -r)/build/
KERNEL_DIR:=/usr/src/linux-headers-3.2.0-29-generic-pae
PWD:=$(shell pwd)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
rm -rf  .*.cmd *.ko  *.o modules.order  Module.symvers *mod.c
.PHONY: modules modules_install clean 
else
modules-objs := dev.o
obj-m := dev.o
endif

编译模块安装之后会在/sys/class/看到hello_char_class 以及目录内的chrdev,同时也会在/dev下看到udev为我们建立的节点chrdev.

测试程序:

  1. #include <stdio.h>  
  2. #include <fcntl.h>  
  3.   
  4. int main(void)  
  5. {  
  6.     int fd;  
  7.     int i;    
  8.     char buf[50];  
  9.   
  10.     fd = open("/dev/chrdev",O_RDWR);  
  11.     if(fd < 0){  
  12.         printf("can't open dev\n");  
  13.         return -1;  
  14.     }  
  15.   
  16.     read(fd,buf,11);  
  17.       
  18.     printf("%s",buf);  
  19.   
  20.     return 0;  
  21. }  

测试程序执行后会输出hello world.,
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值