Chinaunix首页 | 论坛 | 博客
  • 博客访问: 133906
  • 博文数量: 49
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 182
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-14 13:22
个人简介

Linux的热爱者

文章存档

2014年(7)

2013年(42)

我的朋友

分类: LINUX

2013-09-25 14:23:50

创建字符设备的三种方法:
1. 使用早期的register_chardev()方法

点击(此处)折叠或打开

  1. #include<linux/kernel.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<asm/uaccess.h>
  5. int init_module(void);
  6. void cleanup_module(void);
  7. static int device_open(struct inode*, struct file*);
  8. static int device_release(struct inode*, struct file*);
  9. static ssize_t device_read(struct file*, char *, size_t, loff_t*);
  10. static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
  11. #define SUCCESS 0
  12. #define DEVICE_NAME "chardev"
  13. #define BUF_LEN 80
  14. static int major;
  15. static int Device_open = 0;
  16. static char msg[BUF_LEN];
  17. static char *msg_ptr;
  18. static struct file_operations fops =
  19. {
  20.         .read = device_read,
  21.         .write = device_write,
  22.         .open = device_open,
  23.         .release = device_release,
  24. };
  25. int init_module(void)
  26. {
  27.         major = register_chrdev(0, DEVICE_NAME, &fops);
  28.         if (major < 0)
  29.         {
  30.                 printk(KERN_ALERT "Registering char device failed with %d\n", major);
  31.                 return major;
  32.         }
  33.         printk(KERN_INFO "I was assigned major number %d.\n", major);
  34.         return SUCCESS;
  35. }
  36. void cleanup_module(void)
  37. {
  38.         int ret = unregister_chrdev(major, DEVICE_NAME);
  39.         if (ret < 0)
  40.         {
  41.                 printk(KERN_ALERT "Error in unregister chrdev %d\n", major);
  42.         }
  43. }
  44. static int device_open(struct inode* inode, struct file* file)
  45. {
  46.         static int counter = 0;
  47.         if (Device_open)
  48.         {
  49.                 return -EBUSY;
  50.         }
  51.         Device_open++;
  52.         sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n" , counter++, Device_open);
  53.         msg_ptr = msg;
  54.         try_module_get(THIS_MODULE);
  55.         return SUCCESS;
  56. }
  57. static int device_release(struct inode* inode, struct file* file)
  58. {
  59.         Device_open--;
  60.         module_put(THIS_MODULE);
  61.         return 0;
  62. }
  63. static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
  64. {
  65.         int bytes_read = 0;
  66.         if (*msg_ptr == '\0')
  67.                 return 0;
  68.         printk(KERN_ALERT "length=%d\n", length);
  69.         while (length && *msg_ptr)
  70.         {
  71.                 put_user(*(msg_ptr++), buffer++);
  72.                 length--;
  73.                 bytes_read++;
  74.         }
  75.         return bytes_read;
  76. }
  77. static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
  78. {
  79.         printk(KERN_ALERT "Sorry, this operation isn't supported\n");
  80.         return -EINVAL;
  81. }

2. 使用cdev的方法

点击(此处)折叠或打开

  1. #include<linux/kernel.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/types.h>
  5. #include<linux/fs.h>
  6. #include<linux/cdev.h>
  7. #include<asm/uaccess.h>
  8. int init_module(void);
  9. void cleanup_module(void);
  10. static int device_open(struct inode*, struct file*);
  11. static int device_release(struct inode*, struct file*);
  12. static ssize_t device_read(struct file*, char *, size_t, loff_t*);
  13. static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
  14. #define SUCCESS 0
  15. #define DEVICE_NAME "chardev"
  16. #define BUF_LEN 80

  17. static int major;
  18. static int Device_open = 0;
  19. static char msg[BUF_LEN];
  20. static char *msg_ptr;
  21. static struct cdev *my_cdev;
  22. static struct file_operations fops =
  23. {
  24.         .read = device_read,
  25.         .write = device_write,
  26.         .open = device_open,
  27.         .release = device_release,
  28. };
  29. int init_module(void)
  30. {
  31.         int err;
  32.         dev_t devid ;
  33.         alloc_chrdev_region(&devid, 0, 1, "chardev");
  34.         major = MAJOR(devid);
  35.         my_cdev = cdev_alloc();
  36.         cdev_init(my_cdev, &fops);
  37.         err = cdev_add(my_cdev, devid, 1);
  38.         if (err)
  39.         {
  40.                 printk(KERN_INFO "I was assigned major number %d.\n", major);
  41.                 return -1;
  42.         }
  43.         printk("major number is %d\n", MAJOR(devid));
  44.         return SUCCESS;
  45. }
  46. void cleanup_module(void)
  47. {
  48.         cdev_del(my_cdev);
  49.         printk("cleanup done\n");
  50. }
  51. static int device_open(struct inode* inode, struct file* file)
  52. {
  53.         static int counter = 0;
  54.         if (Device_open)
  55.         {
  56.                 return -EBUSY;
  57.         }
  58.         Device_open++;
  59.         sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n", counter++, Device_open);
  60.         msg_ptr = msg;
  61.         try_module_get(THIS_MODULE);
  62.         return SUCCESS;
  63. }
  64. static int device_release(struct inode* inode, struct file* file)
  65. {
  66.         Device_open--;
  67.         module_put(THIS_MODULE);
  68.         return 0;
  69. }
  70. static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
  71. {
  72.         int bytes_read = 0;
  73.         if (*msg_ptr == '\0')
  74.                 return 0;
  75.         printk(KERN_ALERT "length=%d\n", length);
  76.         while (length && *msg_ptr)
  77.         {
  78.                 put_user(*(msg_ptr++), buffer++);
  79.                 length--;
  80.                 bytes_read++;
  81.         }
  82.         return bytes_read;
  83. }
  84. static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
  85. {
  86.         printk(KERN_ALERT "Sorry, this operation isn't supported\n");
  87.         return -EINVAL;
  88. }

3. 使用udev在/dev/下动态生成设备文件的方式

点击(此处)折叠或打开

  1. #include<linux/kernel.h>
  2. #include<linux/module.h>
  3. #include<linux/types.h>
  4. #include<linux/fs.h>
  5. #include<linux/cdev.h>
  6. #include<linux/pci.h>
  7. #include<linux/moduleparam.h>
  8. #include<linux/init.h>
  9. #include<linux/string.h>
  10. #include<asm/uaccess.h>
  11. #include<asm/unistd.h>
  12. #include<asm/uaccess.h>
  13. MODULE_LICENSE("GPL"); /*此处如果不加的话加载的时候会出错*/
  14. int init_module(void);
  15. void cleanup_module(void);
  16. static int device_open(struct inode*, struct file*);
  17. static int device_release(struct inode*, struct file*);
  18. static ssize_t device_read(struct file*, char *, size_t, loff_t*);
  19. static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
  20. #define SUCCESS 0
  21. #define DEVICE_NAME "chardev"
  22. #define BUF_LEN 80

  23. static int major;
  24. static int Device_open = 0;
  25. static char msg[BUF_LEN];
  26. static char *msg_ptr;
  27. static struct cdev *my_cdev;
  28. static struct class *my_class;
  29. dev_t devid ;
  30. static struct file_operations fops =
  31. {
  32.         .read = device_read,
  33.         .write = device_write,
  34.         .open = device_open,
  35.         .release = device_release,
  36. };
  37. int init_module(void)
  38. {
  39.         int err;
  40.         alloc_chrdev_region(&devid, 0, 1, "chardev");
  41.         major = MAJOR(devid);
  42.         my_cdev = cdev_alloc();
  43.         cdev_init(my_cdev, &fops);
  44.         my_cdev->owner = THIS_MODULE;
  45.         err = cdev_add(my_cdev, devid, 1);
  46.         if (err)
  47.         {
  48.                 printk(KERN_INFO "I was assigned major number %d.\n", major);
  49.                 return -1;
  50.         }
  51.         my_class = class_create(THIS_MODULE, "chardev_class1");
  52.         if (IS_ERR(my_class))
  53.         {
  54.                 printk(KERN_INFO "create class error\n");
  55.                 return -1;
  56.         }
  57.         class_device_create(my_class, NULL, devid, NULL, "chardev" "%d", MINOR(devid));
  58.         printk("major number is %d\n", MAJOR(devid));
  59.         return SUCCESS;
  60. }
  61. void cleanup_module(void)
  62. {
  63.         cdev_del(my_cdev);
  64.         class_device_destroy(my_class, devid);
  65.         class_destroy(my_class);
  66.         printk("cleanup done\n");
  67. }
  68. static int device_open(struct inode* inode, struct file* file)
  69. {
  70.         static int counter = 0;
  71.         if (Device_open)
  72.         {
  73.                 return -EBUSY;
  74.         }
  75.         Device_open++;
  76.         sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n", counter++, Device_open);
  77.         msg_ptr = msg;
  78.         try_module_get(THIS_MODULE);
  79.         return SUCCESS;
  80. }
  81. static int device_release(struct inode* inode, struct file* file)
  82. {
  83.         Device_open--;
  84.         module_put(THIS_MODULE);
  85.         return 0;
  86. }
  87. static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
  88. {
  89.         int bytes_read = 0;
  90.         if (*msg_ptr == '\0')
  91.                 return 0;
  92.         printk(KERN_ALERT "length=%d\n", length);
  93.         while (length && *msg_ptr)
  94.         {
  95.                 put_user(*(msg_ptr++), buffer++);
  96.                 length--;
  97.                 bytes_read++;
  98.         }
  99.         return bytes_read;
  100. }
  101. static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
  102. {
  103.         printk(KERN_ALERT "Sorry, this operation isn't supported\n");
  104.         return -EINVAL;
  105. }




阅读(1290) | 评论(0) | 转发(0) |
0

上一篇:字符设备驱动-1

下一篇:字符设备驱动—3

给主人留下些什么吧!~~