Chinaunix首页 | 论坛 | 博客
  • 博客访问: 54060
  • 博文数量: 18
  • 博客积分: 445
  • 博客等级: 下士
  • 技术积分: 185
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-26 16:57
文章分类
文章存档

2012年(18)

我的朋友

分类: LINUX

2012-10-23 22:28:30

   

       下面是一个简单的字符设备驱动程序,主要是一个模拟设备,使用了系统的内存,相信大家都能看懂,毕竟简单,而且注释清楚,编译测试的方法大家都知道吧,这里要说的就是习惯的测试方法是通过echo向设备文件写入内容,然后通过cat显示内容,但是希望大家看到,该设备只有4字节的内存,测试的时候建议大家可以试一试写入的内容小于4字节和大于4字节,大家自己看看出现什么事,呵呵:

  1. #include    
  2. #include    
  3. #include    
  4. #include    
  5. #include    
  6. #include    
  7. #include    
  8. #include    
  9. #include    
  10. #include    
  11. #include    
  12.   
  13. #define MEMSIZE     4   
  14.   
  15. #define MAJORNUM    2538   
  16.   
  17. static int major = MAJORNUM;  
  18.   
  19. /******定义自己的字符设备******/  
  20. struct char_mem_t {  
  21.     struct cdev memdev;  
  22.     int device[MEMSIZE];  
  23. }char_mem;  
  24.   
  25.   
  26. static ssize_t char_mem_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)  
  27. {  
  28.     /*******取得文件当前偏移量********/  
  29.     unsigned long p = *ppos;  
  30.     int ret = 0;  
  31.       
  32.     /*****分析当前要读取操作的读取位置和读取量是否满足要求*****/  
  33.     if(p > MEMSIZE)  
  34.         return 0;  
  35.     if(count > MEMSIZE - p)  
  36.         count = MEMSIZE - p;  
  37.       
  38.     /*******读取操作,调用copy_to_user()函数*********/  
  39.     if(copy_to_user(buf, (void*)(char_mem.device+p), count))  
  40.         ret = -EFAULT;  
  41.     else  //读取成功则需要调整文件指针位置   
  42.     {  
  43.         *ppos += count;  
  44.         ret = count;  
  45.           
  46.         printk(KERN_INFO "read %d bytes from %d", count, p);  
  47.     }  
  48.       
  49.     return ret;  
  50. }  
  51.   
  52. static ssize_t char_mem_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)  
  53. {  
  54.     /*******取得文件当前偏移量********/  
  55.     unsigned long p = *ppos;  
  56.     int ret = 0;  
  57.       
  58.     /*****分析当前要写入操作的写入位置和写入量是否满足要求*****/  
  59.     if(p >= MEMSIZE)  
  60.         return 0;  
  61.     if(count > MEMSIZE - p)  
  62.         count = MEMSIZE - p;  
  63.       
  64.     /*******写入操作,调用copy_from_user()函数*********/  
  65.     if(copy_from_user((void*)(char_mem.device+p), buf, count))  
  66.         ret = -EFAULT;  
  67.     else  //写入成功则需要调整文件指针位置   
  68.     {  
  69.         *ppos += count;  
  70.         ret = count;  
  71.           
  72.         printk(KERN_INFO "write %d bytes to %d", count, p);  
  73.     }  
  74.       
  75.     return ret;  
  76. }  
  77.   
  78. static loff_t char_mem_llseek(struct file *filp, loff_t offset, int orig)  
  79. {  
  80.     loff_t ret = 0;  
  81.       
  82.     switch(orig) {  
  83.     /*****从文件头开始偏移*****/  
  84.     case 0:  
  85.         if(offset < 0)  
  86.         {  
  87.             ret = -EINVAL;  
  88.             break;  
  89.         }  
  90.         if((unsigned int)offset > MEMSIZE)  
  91.         {  
  92.             ret = -EINVAL;  
  93.             break;  
  94.         }  
  95.         filp->f_pos = (unsigned int) offset;  
  96.         ret = filp->f_pos;  
  97.         break;  
  98.     /*******从当前位置偏移*************/  
  99.     case 1:  
  100.         if((filp->f_pos + offset) > MEMSIZE)  
  101.         {  
  102.             ret = -EINVAL;  
  103.             break;  
  104.         }  
  105.         if((filp->f_pos + offset) < 0)  
  106.         {  
  107.             ret = -EINVAL;  
  108.             break;  
  109.         }  
  110.         filp->f_pos += offset;  
  111.         ret = filp->f_pos;  
  112.         break;  
  113.     default:  
  114.         ret = -EINVAL;  
  115.     }  
  116.       
  117.     return ret;  
  118. }  
  119.   
  120.   
  121. static const struct file_operations char_mem_ops = {  
  122.     .owner = THIS_MODULE,  
  123.     .llseek = char_mem_llseek,  
  124.     .read = char_mem_read,  
  125.     .write = char_mem_write,  
  126. //  .ioctl = char_mem_ioctl,   
  127. };  
  128.   
  129.   
  130. static int charmem_init(void)  
  131. {  
  132.     int result = 0;  
  133.     int err = 0;  
  134.     dev_t dev = MKDEV(major, 0);  
  135.       
  136.     if(major)  
  137.     {  
  138.         result = register_chrdev_region(dev, 1, "charmem");  
  139.     }  
  140.     else  
  141.     {  
  142.         result = alloc_chrdev_region(&dev, 0, 1, "charmem");  
  143.         major = MAJOR(dev);  
  144.     }  
  145.       
  146.     /******申请设备号失败*******/  
  147.     if(result < 0)   
  148.         return result;  
  149.       
  150.     /********注册设备********/  
  151.     cdev_init(&char_mem.memdev, &char_mem_ops);  
  152.     char_mem.memdev.owner = THIS_MODULE;  
  153.     err = cdev_add(&char_mem.memdev, dev, 1);  
  154.       
  155.     /******注册失败********/  
  156.     if(err)  
  157.         printk(KERN_INFO "Error %d adding char_mem device", err);  
  158.       
  159. }  
  160.   
  161. static void charmem_exit(void)  
  162. {  
  163.     /****删除设备***/  
  164.     cdev_del(&char_mem.memdev);  
  165.     /*****释放设备编号******/  
  166.     unregister_chrdev_region(MKDEV(major, 0), 1);  
  167. }  
  168.   
  169.   
  170. MODULE_AUTHOR("chenlong12580");  
  171. MODULE_LICENSE("Dual BSD/GPL");  
  172.   
  173.   
  174. module_init(charmem_init);  
  175. module_exit(charmem_exit);
阅读(1659) | 评论(0) | 转发(0) |
0

上一篇:内核更新太快了

下一篇:misc设备驱动模型

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