免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2754 | 回复: 3
打印 上一主题 下一主题

字符设备驱动不停打log 好像死循环了 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-03-05 15:18 |只看该作者 |倒序浏览
看了linux驱动开发详解书上的例子,网上找了代码,然后用这种方式一直是对的:
  1. #include <linux/module.h>  
  2. #include <linux/types.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/errno.h>  
  5. #include <linux/mm.h>  
  6. #include <linux/sched.h>  
  7. #include <linux/init.h>  
  8. #include <linux/cdev.h>  
  9. #include <asm/io.h>  
  10. #include <asm/system.h>  
  11. #include <asm/uaccess.h>  
  12.    
  13.    
  14. #define MEMDEV_MAJOR 251   /*预设的mem的主设备号*/  
  15. #define MEMDEV_NUM 2  /*设备数*/  
  16. #define MEMDEV_SIZE 1024  //分配的内存大小  
  17.    
  18. struct mem_dev  
  19. {  
  20.          unsignedint size;  
  21.          char*data;  
  22.          structsemaphore sem;  
  23. };  
  24.    
  25. static int mem_major = MEMDEV_MAJOR;  /*预设的mem的主设备号*/  
  26. struct cdev mem_cdev;  
  27. struct mem_dev *mem_devp; /*设备结构体指针*/  
  28. /*文件打开函数*/   
  29. static int mem_open(struct inode *inode,struct file *filp)  
  30. {  
  31.          struct mem_dev *dev;  
  32.          unsignedint num;  
  33.          
  34.          printk("mem_open.\n");  
  35.          
  36.          num= MINOR(inode->i_rdev);//获得次设备号  
  37.          if(num> (MEMDEV_NUM -1))          //检查次设备号有效性  
  38.                    return-ENODEV;  
  39.                     
  40.          dev= &mem_devp[num];  
  41.          filp->private_data= dev; //将设备结构保存为私有数据  
  42.          
  43.          return0;  
  44. }  
  45.    
  46. static int mem_release(struct inode *inode,struct file *filp)  
  47. {  
  48.          printk("mem_release.\n");  
  49.          return0;  
  50. }  
  51.    
  52. static ssize_t mem_read(struct file *filp,char __user *buf, size_t size, loff_t *ppos)  
  53. {  
  54.          intret = 0;  
  55.          structmem_dev *dev;  
  56.          unsignedlong p;  
  57.          unsignedlong count;  
  58.          
  59.          printk("mem_read.\n");  
  60.          
  61.          dev= filp->private_data;//获得设备结构  
  62.          count= size;  
  63.          p= *ppos;  
  64.          
  65.          //检查偏移量和数据大小的有效性  
  66.          if(p> MEMDEV_SIZE)  
  67.                    return0;  
  68.          if(count> (MEMDEV_SIZE-p))  
  69.                    count= MEMDEV_SIZE - p;  
  70.                     
  71.          if(down_interruptible(&dev->sem))//锁定互斥信号量  
  72.                   return -ERESTARTSYS;  
  73.                     
  74.          //读取数据到用户空间  
  75.          if(copy_to_user(buf,dev->data+p, count)){  
  76.                    ret= -EFAULT;  
  77.                    printk("copyfrom user failed\n");  
  78.          }  
  79.          else{  
  80.                    *ppos+= count;  
  81.                    ret= count;  
  82.                    printk("read%d bytes from dev\n", count);  
  83.          }  
  84.          
  85.          up(&dev->sem);//解锁互斥信号量  
  86.          
  87.          returnret;  
  88. }  
  89.    
  90. static ssize_t mem_write(struct file *filp,const char __user *buf, size_t size, loff_t *ppos)//注意:第二个参数和read方法不同  
  91. {  
  92.          intret = 0;  
  93.          structmem_dev *dev;  
  94.          unsignedlong p;  
  95.          unsignedlong count;  
  96.          
  97.          printk("mem_write.\n");  
  98.          
  99.          dev= filp->private_data;  
  100.          count= size;  
  101.          p= *ppos;  
  102.          printk("count : %d",count);
  103.          if(p> MEMDEV_SIZE)  
  104.                    return0;  
  105.          if(count> (MEMDEV_SIZE-p))  
  106.                    count= MEMDEV_SIZE - p;  
  107.                     
  108.          if(down_interruptible(&dev->sem))//锁定互斥信号量  
  109.                    return-ERESTARTSYS;  
  110.                     
  111.          if(copy_from_user(dev->data+p,buf, count)){  
  112.                    ret= -EFAULT;  
  113.                    printk("copyfrom user failed\n");  
  114.          }  
  115.          else{  
  116.                    *ppos+= count;  
  117.                    ret= count;  
  118.                    printk("write%d bytes to dev\n", count);  
  119.          }  
  120.          
  121.          up(&dev->sem);//解锁互斥信号量  
  122.          
  123.          returnret;  
  124. }  
  125.    
  126. static loff_t mem_llseek(struct file *filp,loff_t offset, int whence)  
  127. {  
  128.          intnewpos;  
  129.          
  130.          printk("mem_llseek.\n");  
  131.          
  132.          switch(whence)  
  133.          {  
  134.                    case0:  
  135.                             newpos= offset;  
  136.                             break;  
  137.                     
  138.                    case1:  
  139.                             newpos= filp->f_pos + offset;  
  140.                             break;  
  141.                              
  142.                    case2:  
  143.                             newpos= MEMDEV_SIZE - 1 + offset;  
  144.                             break;  
  145.                              
  146.                    default:  
  147.                             return-EINVAL;  
  148.          }  
  149.          
  150.          if((newpos<0)|| (newpos>(MEMDEV_SIZE - 1)))  
  151.                    return-EINVAL;  
  152.                     
  153.          filp->f_pos= newpos;  
  154.          returnnewpos;  
  155. }  
  156.   
  157. /*文件操作结构体*/  
  158. static const struct file_operations mem_fops = {  
  159.          .owner= THIS_MODULE,  
  160.          .open= mem_open,  
  161.          .write= mem_write,  
  162.          .read= mem_read,  
  163.          .release= mem_release,  
  164.          .llseek= mem_llseek,  
  165. };  
  166. /*设备驱动模块加载函数*/  
  167. static int __init memdev_init(void)  
  168. {  
  169.          int result;  
  170.          int err;  
  171.          int i;  
  172.          
  173.          //申请设备号  
  174.          dev_t devno = MKDEV(mem_major, 0);  
  175.          
  176.          if(mem_major)  
  177.                    result= register_chrdev_region(devno, MEMDEV_NUM, "memdev");//注意静态申请的dev_t参数和动态dev_t参数的区别  
  178.          else{        //静态直接传变量,动态传变量指针  
  179.                    result= alloc_chrdev_region(&devno, 0, MEMDEV_NUM, "memdev");  
  180.                    mem_major= MAJOR(devno);  
  181.          }  
  182.          
  183.          if(result< 0){  
  184.                    printk("can'tget major devno:%d\n", mem_major);  
  185.                    returnresult;  
  186.          }  
  187.          
  188.          //注册设备驱动  
  189.          cdev_init(&mem_cdev,&mem_fops);  /*初始化cdev结构*/  
  190.          mem_cdev.owner= THIS_MODULE;  
  191.          
  192.   /* 注册字符设备 */  
  193.   
  194.          err= cdev_add(&mem_cdev, MKDEV(mem_major, 0), MEMDEV_NUM);//如果有N个设备就要添加N个设备号  
  195.          if(err)  
  196.                    printk("addcdev faild,err is %d\n", err);  
  197.                     
  198.          //分配设备内存  
  199.          mem_devp= kmalloc(MEMDEV_NUM*(sizeof(struct mem_dev)), GFP_KERNEL);  
  200.          if(!mem_devp){  
  201.                     result = - ENOMEM;  
  202.                     goto fail_malloc;  
  203.          }  
  204.          memset(mem_devp,0, MEMDEV_NUM*(sizeof(struct mem_dev)));  
  205.          
  206.          
  207.          for(i=0;i<MEMDEV_NUM; i++){  
  208.                    mem_devp[i].size= MEMDEV_SIZE;  
  209.                    mem_devp[i].data= kmalloc(MEMDEV_SIZE, GFP_KERNEL);  
  210.                    memset(mem_devp[i].data,0, MEMDEV_SIZE);  
  211.                    sema_init(&mem_devp[i].sem,1);//初始化互斥锁  
  212.          }  
  213.          
  214.          returnresult;  
  215.          
  216. fail_malloc:  
  217.          unregister_chrdev_region(MKDEV(mem_major,0), MEMDEV_NUM);  
  218.          returnresult;  
  219. }  
  220.    
  221. static void memdev_exit(void)  
  222. {  
  223.          cdev_del(&mem_cdev);  
  224.          unregister_chrdev_region(MKDEV(mem_major,0), MEMDEV_NUM);//注意释放的设备号个数一定要和申请的设备号个数保存一致  
  225.          //否则会导致设备号资源流失  
  226.          printk("memdev_exit\n");  
  227. }  
  228.    
  229. module_init(memdev_init);  
  230. module_exit(memdev_exit);  
  231.    
  232. MODULE_AUTHOR("Y-Kee");  
  233. MODULE_LICENSE("GPL");  
复制代码
echo 'dddd'>/dev/memdev
cat /dev/memdev
但是用了自己写的测试程序就不行了:
  1. #include <stdio.h>

  2. int main()
  3. {
  4. FILE *fp0 = NULL;
  5. char Buf[4096];

  6. /*初始化Buf*/
  7. strcpy(Buf,"Mem is char dev!");
  8. printf("BUF: %s\n",Buf);

  9. /*打开设备文件*/
  10. fp0 = fopen("/dev/memdev0","r+");
  11. if (fp0 == NULL)
  12. {
  13.   printf("Open Memdev0 Error!\n");
  14.   return -1;
  15. }

  16. /*写入设备*/
  17. fwrite(Buf, sizeof(Buf), 1, fp0);

  18. /*重新定位文件位置(思考没有该指令,会有何后果)*/
  19. fseek(fp0,0,SEEK_SET);

  20. /*清除Buf*/
  21. strcpy(Buf,"Buf is NULL!");
  22. printf("BUF: %s\n",Buf);


  23. /*读出设备*/
  24. fread(Buf, sizeof(Buf), 1, fp0);

  25. /*检测结果*/
  26. printf("BUF: %s\n",Buf);

  27. return 0;

  28. }
复制代码
不停打映出log :
[ 3721.809411] write 0 bytes to dev
[ 3721.809413] mem_write.
[ 3721.809615] count= 3072
[ 3721.809816] write 0 bytes to dev
[ 3721.809817] mem_write.
[ 3721.810018] count= 3072
[ 3721.810219] write 0 bytes to dev
[ 3721.810221] mem_write.
[ 3721.810422] count= 3072

为什么用fwrite的方式,count会这么大?3072 ?但是为什么会反复打印出log 、write()函数按道理只会执行一次的。

论坛徽章:
0
2 [报告]
发表于 2012-03-06 11:23 |只看该作者
你程序中:
  1. /*写入设备*/
  2. fwrite(Buf, sizeof(Buf), 1, fp0);
复制代码
应改为
  1. /*写入设备*/
  2. fwrite(Buf, strlen(Buf), 1, fp0);
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-03-06 14:54 |只看该作者
ice2000feng 发表于 2012-03-06 11:23
你程序中:应改为

是的 我也发觉了 但是我研究不出来 为什么sizeof(buf),也就是4096,可以导致驱动write函数不停的像死循环一样?
我直接把copy_from_user()的count数设置为4096也不会有这种效果的,为什么会不停打印出log ?谢谢

论坛徽章:
0
4 [报告]
发表于 2012-03-19 00:47 |只看该作者
回复 3# win1naruto


    第一次写了1024个字节,后面每次count先初始化为剩余的3072,但是又被改成mem_size-offset=0了,每次写0个字节,就写不完了。

   因为没写完,又没出错,所以write一直被调用。代码只能保存1024个字节的内容,多了应该返回错误。

   read读的字节可以比要求的少,write不一样。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP