Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1253984
  • 博文数量: 479
  • 博客积分: 12240
  • 博客等级: 上将
  • 技术积分: 4999
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-24 17:12
文章分类

全部博文(479)

文章存档

2014年(1)

2013年(1)

2012年(1)

2011年(95)

2010年(177)

2009年(167)

2008年(16)

2007年(21)

分类: LINUX

2011-01-16 20:59:24

支持udev的字符驱动。

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/cdev.h>
  5. #include <linux/device.h>

  6. static int major = 232;     //静态设备节点方式的默认值
  7. static int minor = 0;         //静态设备节点方式的默认值
  8. module_param(major, int, S_IRUGO);
  9. module_param(minor, int, S_IRUGO);

  10. struct cdev *char_cdev;     //cdev数据结构
  11. static dev_t devno;        //设备编号
  12. static struct class *char_cdev_class;

  13. #define DEVICE_NAME     "charcdev"

  14. static int char_cdev_open(struct inode *inode, struct file *file )
  15. {
  16.     try_module_get(THIS_MODULE);
  17.     printk(KERN_INFO DEVICE_NAME "opened!\n");

  18.     return 0;
  19. }

  20. static int char_cdev_release(struct inode *inode, struct file *file )
  21. {
  22.     printk(KERN_INFO DEVICE_NAME "closed!\n");

  23.     module_put(THIS_MODULE);
  24.     return 0;
  25. }


  26. static ssize_t char_cdev_read(struct file *file, char *buf,size_t count, loff_t *f_pos)
  27. {
  28.     printk(KERN_INFO DEVICE_NAME "read method!\n");

  29.     return count;
  30. }

  31. static ssize_t char_cdev_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
  32. {
  33.     printk(KERN_INFO DEVICE_NAME "write method!\n");

  34.     return count;
  35. }

  36. static int char_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  37. {
  38.     printk(KERN_INFO DEVICE_NAME "ioctl method!\n");

  39.     return 0;
  40. }

  41. struct file_operations char_cdev_fops = {
  42.     .owner        = THIS_MODULE,
  43.     .read        = char_cdev_read,
  44.     .write        = char_cdev_write,
  45.     .open        = char_cdev_open,
  46.     .release    = char_cdev_release,
  47.     .ioctl        = char_cdev_ioctl
  48. };


  49. static int __init char_cdev_init(void)
  50. {
  51.     int ret;

  52.     if (major > 0) { //静态设备节点
  53.         devno = MKDEV(major, minor);
  54.         ret = register_chrdev_region(devno, 1, "char_cdev");
  55.     } else { //动态设备节点
  56.         ret = alloc_chrdev_region(&devno, minor, 1, "char_cdev"); //从系统获取主设备号
  57.         major = MAJOR(devno);

  58.     }
  59.     if (ret < 0) {
  60.         printk(KERN_ERR "cannot get major %d \n", major);
  61.         return -1;
  62.     }

  63.     char_cdev = cdev_alloc();        //分配char_cdev结构
  64.     if (char_cdev != NULL) {
  65.         cdev_init(char_cdev, &char_cdev_fops);        //初始化char_cdev结构
  66.          //char_cdev->ops = &char_cdev_fops;     //可以不要
  67.         char_cdev->owner = THIS_MODULE;
  68.         if (cdev_add(char_cdev, devno, 1) != 0) {    //增加char_cdev到系统中
  69.             printk(KERN_ERR "add cdev error!\n");
  70.             goto error1;
  71.         }
  72.             
  73.     } else {
  74.         printk(KERN_ERR "cdev_alloc error!\n");
  75.         goto error2;
  76.     }

  77.     char_cdev_class = class_create(THIS_MODULE, "char_cdev_class"); //在/sys/class/下创建char_cdev_class目录
  78.     if (IS_ERR(char_cdev_class)) {
  79.         printk(KERN_INFO "create class error\n");
  80.         return -1;
  81.     }
  82.     //device_create(char_cdev_class, NULL, devno, NULL, "char_cdev" "%d", MINOR(devno)); //将创建/dev/char_cdev0文件
  83.     device_create(char_cdev_class, NULL, devno, NULL, "char_cdev", NULL); //将创建/dev/char_cdev文件

  84.     return 0;

  85. error1:
  86.     unregister_chrdev_region(devno, 1);     //释放已经获得的设备号
  87. error2:
  88.     return ret;
  89. }

  90. static void __exit char_cdev_exit(void)
  91. {
  92.     device_destroy(char_cdev_class, devno); 
  93.     class_destroy(char_cdev_class);
  94.     cdev_del(char_cdev);            //移除字符设备
  95.     unregister_chrdev_region(devno, 1);    //释放设备号  
  96. }

  97. module_init(char_cdev_init);
  98. module_exit(char_cdev_exit);

  99. MODULE_LICENSE("GPL");
  100. MODULE_AUTHOR("Chenxibing,hibrian.chen@gmail.com");

使用方法:
支持静态/动态设备节点,自动创建设备节点。

#insmod char_cdev.ko
# cat /proc/devices
  232 char_cdev

#ls /dev/char_cdev -l
crw------- 1 root root 232, 0 2011-01-16 20:43 /dev/char_cdev

#ls /sys/class/char_cdev_class/char_cdev -la
lrwxrwxrwx 1 root root 0 2011-01-16 20:58 /sys/class/char_cdev_class/char_cdev -> ../../devices/virtual/char_cdev_class/char_cdev


测试程序:
  1. 1 #include <stdio.h>
  2.      2 #include <stdlib.h>
  3.      3 #include <unistd.h>
  4.      4 #include <sys/ioctl.h>
  5.      5 #include <errno.h>
  6.      6 #include <fcntl.h>
  7.      7
  8.      8 #define DEV_NAME "/dev/char_cdev"
  9.      9
  10.     10 int main(int argc, char *argv[])
  11.     11 {
  12.     12 int i;
  13.     13 int fd = 0;
  14.     14 int dat = 0;
  15.     15
  16.     16 fd = open (DEV_NAME, O_RDWR);
  17.     17 if (fd < 0) {
  18.     18 perror("Open "DEV_NAME" Failed!\n");
  19.     19 exit(1);
  20.     20 }
  21.     21
  22.     22 i = read(fd, &dat, 1);
  23.     23 if (!i) {
  24.     24 perror("read "DEV_NAME" Failed!\n");
  25.     25 exit(1);
  26.     26 }
  27.     27
  28.     28 dat = 0;
  29.     29 i = write(fd, &dat, 1);
  30.     30 if (!i) {
  31.     31 perror("write "DEV_NAME" Failed!\n");
  32.     32 exit(1);
  33.     33 }
  34.     34
  35.     35 i = ioctl(fd, NULL, NULL);
  36.     36 if (!!i) {
  37.     37 perror("ioctl "DEV_NAME" Failed!\n");
  38.     38 exit(1);
  39.     39 }
  40.     40
  41.     41 close(fd);
  42.     42 return 0;
  43.     43 }








阅读(2202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~