嵌入式驱动day04

复习day03
1.内核定时器
struct timer_list{
    expires
    function
    data
}
jiffies
init_timer
add_timer
del_timer
mod_timer
2.系统调用
如何实现?
    从用户态能够切换到内核的方法
         系统调用
         中断
3.字符设备驱动框架
    struct cdev{
         ...
         dev_t dev;//设备号
         file_operations fops*;
         ...
    }
    设备号=主设备好+次设备号
    主设备号:代表一类设备
    次设备号:用于区分同类设备中不同的个体

    静态分配      register_chrdev_region()
    动态分配     alloc_chrdev_region()

    cdev的操作
         cdev_init(*cdev,*file_operations)
         cdev_add(...)
         cdev_del(..)
    struct file_operations{
         .owner =THIS_MODULE,
    }
    insmod cdd.ko
    mknod /dev/cdd c 248 0
    ./test
---------------------------------------------------------------------------------------

   
   
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/cdev.h>
  5. MODULE_LICENSE("GPL");
  6. #define CDD_MAJOR 200
  7. #define CDD_MINOR 0
  8. #define CDD_COUNT 1
  9. dev_t dev=0;
  10. u32 cdd_major=0;
  11. u32 cdd_minor=0;
  12. /*定义cdev类型的变量*/
  13. struct cdev cdd_cdev;
  14. int cdd_open(struct inode *inode,struct file *filp){
  15. printk("enter cdd_open\n");
  16. return 0;
  17. }
  18. int cdd_read(struct file* filp,char __user *buf,size_t count,
  19. loff_t *offset){
  20. printk("enter cdd_read\n");
  21. return 0;
  22. }
  23. int cdd_write(struct file *filp,const char __user *buf,
  24. size_t count,loff_t *offset){
  25. printk("enter cdd_write!\n");
  26. return 0;
  27. }
  28. int cdd_ioctl(struct inode *inode,struct file *filp,
  29. unsigned int cmd ,unsigned data){
  30. printk("enter cdd_ioctl!\n");
  31. return 0;
  32. }
  33. int cdd_release(struct inode *inode,struct file *filp){
  34. printk("enter cdd_release!\n");
  35. return 0;
  36. }
  37. struct file_operations cdd_fops={
  38. .owner = THIS_MODULE,
  39. .open=cdd_open,
  40. .read=cdd_read,
  41. .write=cdd_write,
  42. .ioctl=cdd_ioctl,
  43. .release=cdd_release,
  44. };
  45. int __init cdd_init(void){
  46. int ret =0;
  47. if(cdd_major){
  48. //静态方式分配设备号
  49. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  50. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  51. }else{
  52. /*动态分配设备号*/
  53. ret =all_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  54. }
  55. if(ret<0){
  56. prink("register_chrdev_region failed!\n");
  57. goto failure_register_chrdev;
  58. }
  59. /*获取主设备号*/
  60. cdd_major=MAJOR(dev);
  61. /*初始化cdev
  62. *cdev_int(struct cdev* dev,const struct file_operations* fops)
  63. */
  64. cdev_int(&dev,&cdd_fops) ;
  65. /*添加cdev到内核中
  66. *cdev_add(struct cdev*p,dev_t dev ,unsigned count)
  67. */
  68. ret=cdev_add(&cdev,dev,CDD_COUNT);
  69. if(ret<0){
  70. printk("cdev_add failed!\n");
  71. goto failure_cdev_add;
  72. }
  73. return 0;
  74. failure_cdv_add:
  75. unregister_chrdev_region(dev,CDD_COUNT);
  76. failure_register_chrdev:
  77. return ret;
  78. }
  79. void __exit cdd_exit(void){
  80. /*从内核中删除cdev*/
  81. cdev_del(&cdd_cdev);
  82. /*注销设备号*/
  83. unregister_chrdev_region(dev,CDD_COUNT);
  84. }
  85. module_init(cdd_init);
  86. moudle_exit(cdd_exit);

test.c
   
   
  1. #include<stdio.h>
  2. #include<fcntl.h>
  3. #include<stdlib.h>
  4. int fd =0;
  5. int main(void){
  6. char ch;
  7. char buf[10];
  8. fd=open("/dev/cdd",O_RDWR);
  9. if(fd<0){
  10. printf("open failed!\n");
  11. return -1;
  12. }
  13. printf("open successed fd =%d",fd);
  14. while(1){
  15. printf("string to test /dev/cdd...\n");
  16. ch=getchar();
  17. getchar();
  18. if(ch=='q'){
  19. break;
  20. }
  21. switch(ch){
  22. case 'r': read(fd,buf,0);break;
  23. case 'w': write(fd,buf,0);break;
  24. case 'o': ioctl(fd,0,0);break;
  25. default:
  26. break;
  27. }
  28. sleep(1);
  29. }
  30. close(fd);
  31. return 0;
  32. }
insmod cdd.ko
mknod /dev/cdd c 248 0

用户空间open调用到内核中的cdd_open
open
----------------
    sys_open
         ->do_sys_open
              ->do_filp_open
                   ->do_last
                        ->nameidat_to_filp
                             ->__dentry_open
                                  ->chrdev_open
                                       ->filp->f_op->open(cdd_open)
思考:/dev/cdd 起到的作用? 通道?

手工创建节点
    mknod 
自动创建设备结点
   
   
  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. //动态申请的头文件
  7. #include<linux/slab.h>
  8. MODULE_LICENSE("GPL");
  9. #define CDD_MAJOR 200
  10. #define CDD_MINOR 0
  11. #define CDD_COUNT 10
  12. dev_t dev=0;
  13. u32 cdd_major=0;
  14. u32 cdd_minor=0;
  15. /*定义cdev类型的变量*/
  16. struct cdev cdd_cdev;
  17. struct class *dev_class=NULL;
  18. //struct device *dev_device=NULL;
  19. struct cdd_cdev{
  20. struct cdev cdev;
  21. struct device *dev_device;
  22. u8 led;
  23. };
  24. struct cdd_cdev *cdd_cdevp=NULL;
  25. int cdd_open(struct inode *inode,struct file *filp){
  26. printk("enter cdd_open\n");
  27. return 0;
  28. }
  29. int cdd_read(struct file* filp,char __user *buf,size_t count,
  30. loff_t *offset){
  31. printk("enter cdd_read\n");
  32. return 0;
  33. }
  34. int cdd_write(struct file *filp,const char __user *buf,
  35. size_t count,loff_t *offset){
  36. printk("enter cdd_write!\n");
  37. return 0;
  38. }
  39. int cdd_ioctl(struct inode *inode,struct file *filp,
  40. unsigned int cmd ,unsigned data){
  41. printk("enter cdd_ioctl!\n");
  42. return 0;
  43. }
  44. int cdd_release(struct inode *inode,struct file *filp){
  45. printk("enter cdd_release!\n");
  46. return 0;
  47. }
  48. struct file_operations cdd_fops={
  49. .owner = THIS_MODULE,
  50. .open=cdd_open,
  51. .read=cdd_read,
  52. .write=cdd_write,
  53. .ioctl=cdd_ioctl,
  54. .release=cdd_release,
  55. };
  56. int __init cdd_init(void){
  57. int ret =0;
  58. int i;
  59. if(cdd_major){
  60. //静态方式分配设备号
  61. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  62. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  63. }else{
  64. /*动态分配设备号*/
  65. ret =alloc_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  66. }
  67. if(ret<0){
  68. prink("register_chrdev_region failed!\n");
  69. goto failure_register_chrdev;
  70. }
  71. /*获取主设备号*/
  72. cdd_major=MAJOR(dev);
  73. cdd_cdevp=kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT,GFP_KERNEL);
  74. if(IS_ERR(cdd_cdevp)){
  75. printk("kzalloc fail");
  76. goto failure_kzalloc;
  77. }
  78. /*创建设备类*/
  79. dev_class = class_create(THIS_MODULE,"cdd_class");
  80. if(IS_ERR(dev_class)){
  81. printk("class_create failed!\n");
  82. ret=PTR_ERR(dev_class);
  83. goto failure_dev_class;
  84. }
  85. for(i=0;i<CDD_COUNT;i++){
  86. /*初始化cdev*/
  87. cdev_init(&(cdd_cdevp[i].cdev),&cdd_fops);
  88. /*添加cdev到内核*/
  89. cdev_add(&(cdd_cdevp[i].cdev),dev+i,1);
  90. /*"/dev/xxx"*/
  91. device_create(dev_class,NULL,dev+i,NULL,"cdd%d",i);
  92. }
  93. return 0;
  94. failure_dev_class:
  95. kfree(cdd_cdevp);
  96. failure_kzalloc:
  97. unregister_chrdev_region(dev,CDD_COUNT);
  98. failure_register_chrdev:
  99. return ret;
  100. }
  101. void __exit cdd_exit(void){
  102. int i=0;
  103. for(i=0;i<CDD_COUNT;i++){
  104. device_destroy(dev_class,dev+i);
  105. cdev_del(*(cdd_cdevp[i].cdev));
  106. }
  107. /*从内核中删除设备类*/
  108. class_destroy(dev_class);
  109. kfree(cdd_cdevp);
  110. /*注销设备号*/
  111. unregister_chrdev_region(dev,CDD_COUNT);
  112. }
  113. module_init(cdd_init);
  114. moudle_exit(cdd_exit);自动创建设备节点文件的方式
    用户态的程序创建的设备节点文件
    udev(mdev嵌入式使用),根据/sys/的变化,动态在目录下
    创建设备节点文件。
    (pc环境下)
    udev ,后台守护进程接收uevent事件,
            device_create会发出该事件
            udev会根据事件信息创建/dev/cdd0
    (嵌入式环境下)
    mdev,device_create函数会直接调用/sbin/mdev程序下
            来创建设备节点文件。
            
    /proc ->procfs 导出内核运行状态信息
    /sys  ->sysfs 重点在于导出内核中所有硬件设备的结构层次图
    这两个目录都是虚拟目录
--------------------------------------------------------------------------------
支持多设备去驱动
   
   
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/cdev.h>
  5. #inlcude<linux/device.h>
  6. //动态申请的头文件
  7. #include<linux/slab.h>
  8. MODULE_LICENSE("GPL");
  9. #define CDD_MAJOR 200
  10. #define CDD_MINOR 0
  11. #define CDD_COUNT 10
  12. dev_t dev=0;
  13. u32 cdd_major=0;
  14. u32 cdd_minor=0;
  15. /*定义cdev类型的变量*/
  16. struct cdev cdd_cdev;
  17. struct class *dev_class=NULL;
  18. //struct device *dev_device=NULL;
  19. struct cdd_cdev{
  20. struct cdev cdev;
  21. struct device *dev_device;
  22. u8 led;
  23. }
  24. struct cdd_cdev *cdd_cdevp=NULL;
  25. int cdd_open(struct inode *inode,struct file *filp){
  26. printk("enter cdd_open\n");
  27. return 0;
  28. }
  29. int cdd_read(struct file* filp,char __user *buf,size_t count,
  30. loff_t *offset){
  31. printk("enter cdd_read\n");
  32. return 0;
  33. }
  34. int cdd_write(struct file *filp,const char __user *buf,
  35. size_t count,loff_t *offset){
  36. printk("enter cdd_write!\n");
  37. return 0;
  38. }
  39. int cdd_ioctl(struct inode *inode,struct file *filp,
  40. unsigned int cmd ,unsigned data){
  41. printk("enter cdd_ioctl!\n");
  42. return 0;
  43. }
  44. int cdd_release(struct inode *inode,struct file *filp){
  45. printk("enter cdd_release!\n");
  46. return 0;
  47. }
  48. struct file_operations cdd_fops={
  49. .owner = THIS_MODULE,
  50. .open=cdd_open,
  51. .read=cdd_read,
  52. .write=cdd_write,
  53. .ioctl=cdd_ioctl,
  54. .release=cdd_release,
  55. };
  56. int __init cdd_init(void){
  57. int ret =0;
  58. int i;
  59. if(cdd_major){
  60. //静态方式分配设备号
  61. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  62. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  63. }else{
  64. /*动态分配设备号*/
  65. ret =all_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  66. }
  67. if(ret<0){
  68. prink("register_chrdev_region failed!\n");
  69. goto failure_register_chrdev;
  70. }
  71. /*获取主设备号*/
  72. cdd_major=MAJOR(dev);
  73. cdd_cdevp=kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT,GFP_KERNEL);
  74. if(IS_ERR(cdd_cdevp)){
  75. printk("kzalloc fail");
  76. goto failure_kzalloc;
  77. }
  78. /*创建设备类*/
  79. dev_class = class_create(THIS_MODULE,"cdd_class");
  80. if(IS_ERR(dev_class)){
  81. printk("class_create failed!\n");
  82. ret=PTR_ERR(dev_class);
  83. goto failure_dev_class;
  84. }
  85. for(i=0;i<CDD_COUNT;i++){
  86. /*初始化cdev*/
  87. cdev_init(&(cdd_cdevp[i].cdev),&cdd_fops);
  88. /*添加cdev到内核*/
  89. cdev_add(&(cdd_cdevp[i].cdev),dev+i,1);
  90. /*"/dev/xxx"*/
  91. device_create(dev_class,NULL,dev+i,NULL,"cdd%d",i);
  92. }
  93. return 0;
  94. failure_dev_class:
  95. kfree(cdd_cdevp);
  96. failure_kzalloc:
  97. unregister_chrdev_region(dev,CDD_COUNT);
  98. failure_register_chrdev:
  99. return ret;
  100. }
  101. void __exit cdd_exit(void){
  102. int i=0;
  103. for(i=0;i<CDD_COUNT;i++){
  104. device_destroy(dev_class,dev+i);
  105. cdev_del(*(cdd_cdevp[i].cdev));
  106. }
  107. /*从内核中删除设备类*/
  108. class_destroy(dev_class);
  109. kfree(cdd_cdevp);
  110. /*注销设备号*/
  111. unregister_chrdev_region(dev,CDD_COUNT);
  112. }
  113. module_init(cdd_init);
  114. moudle_exit(cdd_exit);

添加修改
   设备节点文件                     内核中
    /dev/cdd0                           cdev0        led=0
   /dev/cdd1                            cdev1        led=1
  ...                                             ...                     ...    
   /dev/cdd9                            cdev9        led=9

open("/dev/cdd0")
cdd_open(struct inode *inode,struct file *filp )
uc中打开一个文件
推荐一本书<unix高级环境编程>

   
   
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/cdev.h>
  5. #inlcude<linux/device.h>
  6. //动态申请的头文件
  7. #include<linux/slab.h>
  8. MODULE_LICENSE("GPL");
  9. #define CDD_MAJOR 200
  10. #define CDD_MINOR 0
  11. #define CDD_COUNT 10
  12. dev_t dev=0;
  13. u32 cdd_major=0;
  14. u32 cdd_minor=0;
  15. /*定义cdev类型的变量*/
  16. struct cdev cdd_cdev;
  17. struct class *dev_class=NULL;
  18. //struct device *dev_device=NULL;
  19. struct cdd_cdev{
  20. struct cdev cdev;
  21. struct device *dev_device;
  22. u8 led;
  23. }
  24. struct cdd_cdev *cdd_cdevp=NULL;
  25. int cdd_open(struct inode *inode,struct file *filp){
  26. printk("enter cdd_open\n");
  27. return 0;
  28. }
  29. int cdd_read(struct file* filp,char __user *buf,size_t count,
  30. loff_t *offset){
  31. printk("enter cdd_read\n");
  32. return 0;
  33. }
  34. int cdd_write(struct file *filp,const char __user *buf,
  35. size_t count,loff_t *offset){
  36. printk("enter cdd_write!\n");
  37. return 0;
  38. }
  39. int cdd_ioctl(struct inode *inode,struct file *filp,
  40. unsigned int cmd ,unsigned data){
  41. printk("enter cdd_ioctl!\n");
  42. return 0;
  43. }
  44. int cdd_release(struct inode *inode,struct file *filp){
  45. printk("enter cdd_release!\n");
  46. return 0;
  47. }
  48. struct file_operations cdd_fops={
  49. .owner = THIS_MODULE,
  50. .open=cdd_open,
  51. .read=cdd_read,
  52. .write=cdd_write,
  53. .ioctl=cdd_ioctl,
  54. .release=cdd_release,
  55. };
  56. int __init cdd_init(void){
  57. int ret =0;
  58. int i;
  59. if(cdd_major){
  60. //静态方式分配设备号
  61. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  62. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  63. }else{
  64. /*动态分配设备号*/
  65. ret =all_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  66. }
  67. if(ret<0){
  68. prink("register_chrdev_region failed!\n");
  69. goto failure_register_chrdev;
  70. }
  71. /*获取主设备号*/
  72. cdd_major=MAJOR(dev);
  73. cdd_cdevp=kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT,GFP_KERNEL);
  74. if(IS_ERR(cdd_cdevp)){
  75. printk("kzalloc fail");
  76. goto failure_kzalloc;
  77. }
  78. /*创建设备类*/
  79. dev_class = class_create(THIS_MODULE,"cdd_class");
  80. if(IS_ERR(dev_class)){
  81. printk("class_create failed!\n");
  82. ret=PTR_ERR(dev_class);
  83. goto failure_dev_class;
  84. }
  85. for(i=0;i<CDD_COUNT;i++){
  86. /*初始化cdev*/
  87. cdev_init(&(cdd_cdevp[i].cdev),&cdd_fops);
  88. /*添加cdev到内核*/
  89. cdev_add(&(cdd_cdevp[i].cdev),dev+i,1);
  90. /*"/dev/xxx"*/
  91. device_create(dev_class,NULL,dev+i,NULL,"cdd%d",i);
  92. cdd_cdevp[i].led=i;
  93. }
  94. return 0;
  95. failure_dev_class:
  96. kfree(cdd_cdevp);
  97. failure_kzalloc:
  98. unregister_chrdev_region(dev,CDD_COUNT);
  99. failure_register_chrdev:
  100. return ret;
  101. }
  102. void __exit cdd_exit(void){
  103. int i=0;
  104. for(i=0;i<CDD_COUNT;i++){
  105. device_destroy(dev_class,dev+i);
  106. cdev_del(*(cdd_cdevp[i].cdev));
  107. }
  108. /*从内核中删除设备类*/
  109. class_destroy(dev_class);
  110. kfree(cdd_cdevp);
  111. /*注销设备号*/
  112. unregister_chrdev_region(dev,CDD_COUNT);
  113. }
  114. module_init(cdd_init);
  115. moudle_exit(cdd_exit);
文件表
 struct inode
{
     dev_t    i_rdev;//记录设备号
     union{
        struct pipe_inode_info *i_pipe;
        struct cdev  *i_cdev;//指向了cdev_add时添加的cdev
     }
}

   
   
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/cdev.h>
  5. #inlcude<linux/device.h>
  6. //动态申请的头文件
  7. #include<linux/slab.h>
  8. MODULE_LICENSE("GPL");
  9. #define CDD_MAJOR 200
  10. #define CDD_MINOR 0
  11. #define CDD_COUNT 10
  12. dev_t dev=0;
  13. u32 cdd_major=0;
  14. u32 cdd_minor=0;
  15. /*定义cdev类型的变量*/
  16. struct cdev cdd_cdev;
  17. struct class *dev_class=NULL;
  18. //struct device *dev_device=NULL;
  19. struct cdd_cdev{
  20. struct cdev cdev;
  21. struct device *dev_device;
  22. u8 led;
  23. }
  24. struct cdd_cdev *cdd_cdevp=NULL;
  25. int cdd_open(struct inode *inode,struct file *filp){
  26. printk("enter cdd_open\n");
  27. struct cdd_cdev* pcdevp=NULL;
  28. printk("enter cdd_open\n");
  29. pcdevp = container_of(inode->i_cdev,struct cdd_cdev,cdev);
  30. printk("led=%d\n",pcdevp->led);
  31. return 0;
  32. }
  33. int cdd_read(struct file* filp,char __user *buf,size_t count,
  34. loff_t *offset){
  35. printk("enter cdd_read\n");
  36. return 0;
  37. }
  38. int cdd_write(struct file *filp,const char __user *buf,
  39. size_t count,loff_t *offset){
  40. printk("enter cdd_write!\n");
  41. return 0;
  42. }
  43. int cdd_ioctl(struct inode *inode,struct file *filp,
  44. unsigned int cmd ,unsigned data){
  45. printk("enter cdd_ioctl!\n");
  46. return 0;
  47. }
  48. int cdd_release(struct inode *inode,struct file *filp){
  49. printk("enter cdd_release!\n");
  50. return 0;
  51. }
  52. struct file_operations cdd_fops={
  53. .owner = THIS_MODULE,
  54. .open=cdd_open,
  55. .read=cdd_read,
  56. .write=cdd_write,
  57. .ioctl=cdd_ioctl,
  58. .release=cdd_release,
  59. };
  60. int __init cdd_init(void){
  61. int ret =0;
  62. int i;
  63. if(cdd_major){
  64. //静态方式分配设备号
  65. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  66. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  67. }else{
  68. /*动态分配设备号*/
  69. ret =all_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  70. }
  71. if(ret<0){
  72. prink("register_chrdev_region failed!\n");
  73. goto failure_register_chrdev;
  74. }
  75. /*获取主设备号*/
  76. cdd_major=MAJOR(dev);
  77. cdd_cdevp=kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT,GFP_KERNEL);
  78. if(IS_ERR(cdd_cdevp)){
  79. printk("kzalloc fail");
  80. goto failure_kzalloc;
  81. }
  82. /*创建设备类*/
  83. dev_class = class_create(THIS_MODULE,"cdd_class");
  84. if(IS_ERR(dev_class)){
  85. printk("class_create failed!\n");
  86. ret=PTR_ERR(dev_class);
  87. goto failure_dev_class;
  88. }
  89. for(i=0;i<CDD_COUNT;i++){
  90. /*初始化cdev*/
  91. cdev_init(&(cdd_cdevp[i].cdev),&cdd_fops);
  92. /*添加cdev到内核*/
  93. cdev_add(&(cdd_cdevp[i].cdev),dev+i,1);
  94. /*"/dev/xxx"*/
  95. device_create(dev_class,NULL,dev+i,NULL,"cdd%d",i);
  96. cdd_cdevp[i].led=i;
  97. }
  98. return 0;
  99. failure_dev_class:
  100. kfree(cdd_cdevp);
  101. failure_kzalloc:
  102. unregister_chrdev_region(dev,CDD_COUNT);
  103. failure_register_chrdev:
  104. return ret;
  105. }
  106. void __exit cdd_exit(void){
  107. int i=0;
  108. for(i=0;i<CDD_COUNT;i++){
  109. device_destroy(dev_class,dev+i);
  110. cdev_del(*(cdd_cdevp[i].cdev));
  111. }
  112. /*从内核中删除设备类*/
  113. class_destroy(dev_class);
  114. kfree(cdd_cdevp);
  115. /*注销设备号*/
  116. unregister_chrdev_region(dev,CDD_COUNT);
  117. }
  118. module_init(cdd_init);
  119. moudle_exit(cdd_exit);
上面代码在open中确定用户中打开哪个设备
--------------------------------------------------------------------
用户空间操作的设备在read函数中实现知道那个设备
struct filp{
    loff_t    f_ops;
}
fd5=open("/dev/cdd5")    struct file    filp5
read(fd5,....)
    cdd_read()

cdd_open中添加
   filp->private_data = pcdevp ;
cdd_read
    -----------------------------------------------------------------------
4.内核空间和用户空间数据交互问题
   内核态数据向用户态拷贝 copy_to_user(.....)
    用户态数据向内核态拷贝    copy_from_user(....)
    定义在arch/arm/include/asm/uaccess.h

  
  
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/fs.h>
  4. #include<linux/cdev.h>
  5. #inlcude<linux/device.h>
  6. #include<asm/uaccess.h>//用户空间拷贝头文件
  7. //动态申请的头文件
  8. #include<linux/slab.h>
  9. MODULE_LICENSE("GPL");
  10. #define CDD_MAJOR 200
  11. #define CDD_MINOR 0
  12. #define CDD_COUNT 10
  13. dev_t dev=0;
  14. u32 cdd_major=0;
  15. u32 cdd_minor=0;
  16. /*定义cdev类型的变量*/
  17. struct cdev cdd_cdev;
  18. struct class *dev_class=NULL;
  19. //struct device *dev_device=NULL;
  20. #define BUF_SIZE 100
  21. struct cdd_cdev{
  22. struct cdev cdev;
  23. struct device *dev_device;
  24. u8 led;
  25. char kbuf[BUF_SIZE];
  26. }
  27. struct cdd_cdev *cdd_cdevp=NULL;
  28. int cdd_open(struct inode *inode,struct file *filp){
  29. printk("enter cdd_open\n");
  30. struct cdd_cdev* pcdevp=NULL;
  31. printk("enter cdd_open\n");
  32. pcdevp = container_of(inode->i_cdev,struct cdd_cdev,cdev);
  33. printk("led=%d\n",pcdevp->led);
  34. filp->private_data = pcdevp;
  35. return 0;
  36. }
  37. int cdd_read(struct file* filp,char __user *buf,size_t count,
  38. loff_t *offset){
  39. int ret=0
  40. struct cdd_cdev* pcdevp = filp->private_data;
  41. printk("LED%d\n",pcdevp->led);
  42. //copy_to_user(to,from,n);
  43. ret=copy_to_user(buf,pcdevp->kbuf,count);
  44. return ret;
  45. }
  46. int cdd_write(struct file *filp,const char __user *buf,
  47. size_t count,loff_t *offset){
  48. printk("enter cdd_write!\n");
  49. int ret=0;
  50. copy_from_user(pcdevp->kbuf,buf,count);
  51. return ret;
  52. }
  53. int cdd_ioctl(struct inode *inode,struct file *filp,
  54. unsigned int cmd ,unsigned data){
  55. printk("enter cdd_ioctl!\n");
  56. return 0;
  57. }
  58. int cdd_release(struct inode *inode,struct file *filp){
  59. printk("enter cdd_release!\n");
  60. return 0;
  61. }
  62. struct file_operations cdd_fops={
  63. .owner = THIS_MODULE,
  64. .open=cdd_open,
  65. .read=cdd_read,
  66. .write=cdd_write,
  67. .ioctl=cdd_ioctl,
  68. .release=cdd_release,
  69. };
  70. int __init cdd_init(void){
  71. int ret =0;
  72. int i;
  73. if(cdd_major){
  74. //静态方式分配设备号
  75. dev=MKDEV(CDD_MAJOR,CDD_MINOR);
  76. ret =register_chrdev_region(dev,CDD_COUNT,cdd_demo);
  77. }else{
  78. /*动态分配设备号*/
  79. ret =all_chrdev_region(&dev,cdd_minor,CDD_COUNT,cdd_demo);
  80. }
  81. if(ret<0){
  82. prink("register_chrdev_region failed!\n");
  83. goto failure_register_chrdev;
  84. }
  85. /*获取主设备号*/
  86. cdd_major=MAJOR(dev);
  87. cdd_cdevp=kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT,GFP_KERNEL);
  88. if(IS_ERR(cdd_cdevp)){
  89. printk("kzalloc fail");
  90. goto failure_kzalloc;
  91. }
  92. /*创建设备类*/
  93. dev_class = class_create(THIS_MODULE,"cdd_class");
  94. if(IS_ERR(dev_class)){
  95. printk("class_create failed!\n");
  96. ret=PTR_ERR(dev_class);
  97. goto failure_dev_class;
  98. }
  99. for(i=0;i<CDD_COUNT;i++){
  100. /*初始化cdev*/
  101. cdev_init(&(cdd_cdevp[i].cdev),&cdd_fops);
  102. /*添加cdev到内核*/
  103. cdev_add(&(cdd_cdevp[i].cdev),dev+i,1);
  104. /*"/dev/xxx"*/
  105. device_create(dev_class,NULL,dev+i,NULL,"cdd%d",i);
  106. cdd_cdevp[i].led=i;
  107. }
  108. return 0;
  109. failure_dev_class:
  110. kfree(cdd_cdevp);
  111. failure_kzalloc:
  112. unregister_chrdev_region(dev,CDD_COUNT);
  113. failure_register_chrdev:
  114. return ret;
  115. }
  116. void __exit cdd_exit(void){
  117. int i=0;
  118. for(i=0;i<CDD_COUNT;i++){
  119. device_destroy(dev_class,dev+i);
  120. cdev_del(*(cdd_cdevp[i].cdev));
  121. }
  122. /*从内核中删除设备类*/
  123. class_destroy(dev_class);
  124. kfree(cdd_cdevp);
  125. /*注销设备号*/
  126. unregister_chrdev_region(dev,CDD_COUNT);
  127. }
  128. module_init(cdd_init);
  129. moudle_exit(cdd_exit);
编写测试程序
   
   
  1. #include<stdio.h>
  2. #inlcude<fcntl.h>
  3. #inlcude<stdlib.h>
  4. int fd =0;
  5. char rbuf[100];
  6. char wbuf[100]="nihao!\n"
  7. int main(void){
  8. char ch;
  9. fd=open("/dev/cdd5",O_RDWR);
  10. if(fd<0){
  11. printf("open failed");
  12. return -1;
  13. }
  14. printf("open successed fd=%d\n",fd);
  15. while(1){
  16. ch=getchar()
  17. getchar();
  18. switch(ch){
  19. case 'r':
  20. read(fd,rbuf,100);
  21. printf("%s",rbuf);
  22. break;
  23. case 'w':
  24. write(fd,wbuf,100);
  25. break;
  26. case 'o':
  27. ioctl(fd,0,0);
  28. break;
  29. default:
  30. break;
  31. }
  32. }
  33. }

























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值