在Linux 2.6内核中,devfs被认为是过时的方法,并最终被抛弃,udev取代了它。Devfs的一个很重要的特点就是可以动态创建设备结点。那我们现在如何通过udev和sys文件系统动态创建设备结点呢?
下面通过一个实例,说明udev、sys动态创建设备结点的方法。注意代码中红色的部分是为了实现动态创建设备结点添加的。
CODE:
#include #include #include #include #include #include #include MODULE_LICENSE ("GPL");
int hello_major = 252; int hello_minor = 0; int number_of_devices = 1; char data[50]="foobar not equal to barfoo";
struct cdev cdev; dev_t dev = 0; static int hello_open (struct inode *inode, struct file *file) { printk (KERN_INFO "Hey! device opened\n"); return 0; }
static int hello_release (struct inode *inode, struct file *file) { printk (KERN_INFO "Hmmm... device closed\n"); return 0; } ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp) { ssize_t result = 0; if (copy_to_user (buff, data, sizeof(data)-1)) result = -EFAULT; else printk (KERN_INFO "wrote %d bytes\n", count); return result; }
ssize_t hello_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) { ssize_t ret = 0; printk (KERN_INFO "Writing %d bytes\n", count); if (count>127) return -ENOMEM; if (count<0) return -EINVAL; if (copy_from_user (data, buf, count)) { ret = -EFAULT; } else { data[127]='\0'; printk (KERN_INFO"Received: %s\n", data); ret = count; } return ret; } struct file_operations hello_fops = { .owner = THIS_MODULE, .open = hello_open, .release = hello_release, .read = hello_read, .write = hello_write }; struct class *my_class; static void char_reg_setup_cdev (void) { int error, devno = MKDEV (hello_major, hello_minor); cdev_init (&cdev, &hello_fops); cdev.owner = THIS_MODULE; cdev.ops = &hello_fops; error = cdev_add (&cdev, devno , 1); if (error) printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error); /* creating your own class */ my_class =class_create(THIS_MODULE, "farsight_class");//add by lht if(IS_ERR(my_class)) { printk("Err: failed in creating class.\n"); return ; } /* register your own device in sysfs, and this will cause udevd to create corresponding device node */ class_device_create(my_class,NULL, devno, NULL,"farsight_dev"); // device_create(my_class,NULL, devno,"farsight_dev"); }
static int __init hello_2_init (void) { int result; dev = MKDEV (hello_major, hello_minor); result = register_chrdev_region (dev, number_of_devices, "test"); if (result<0) { printk (KERN_WARNING "hello: can't get major number %d\n", hello_major); return result; } char_reg_setup_cdev (); printk (KERN_INFO "char device registered\n"); return 0; } static void __exit hello_2_exit (void) { dev_t devno = MKDEV (hello_major, hello_minor); cdev_del (&cdev); unregister_chrdev_region (devno, number_of_devices); class_device_destroy(my_class, devno); class_destroy(my_class); } module_init (hello_2_init); module_exit (hello_2_exit);v | 在编译了驱动后,可以查看/dev/farsight_dev设备结点,和 /sys/class/farsight_class/farsight_dev/
本代码的测试环境是Ubantu7.04,内核版本是2.6.20-15-generi。在不同版本的内核中,有些系统函数的参数可能不太一样。 | |