免费注册 查看新帖 |

Chinaunix

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

read时出现问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-31 18:07 |只看该作者 |倒序浏览
为什么下面的代码生成的字符驱动,在读的时候,内容一直在刷,是什么问题导致的呢?
测试方法:
date > /dev/对应的设备文件
cat /dev/对应的设备文件。
cat 后,屏幕上就一直打印出东西,内容还是乱码。
(代码就是linux设备驱动开发详解中的第6章的例子)

另外看到一个人的博客里这样写到:
2.加载和创建设备节点都是成功的.但就是用cat命令查看时,虽然读出了正确的字符,却总是在最后还要加上一句提示"找不到设备或地址".不知为何会多出这句来.

# echo 'hello world!' > /dev/globalmem
written 13 bytes(s) from 0
# cat /dev/
/dev/console    /dev/globalmem  /dev/null
# cat /dev/globalmem
read 4096 bytes(s) from 0
hello world!
cat: read error: No such device or address
#
ANSWER:其实没问题,
<1>你把globalmem_read函数中的if (p >= GLOBALMEM_SIZE)改为if (p > GLOBALMEM_SIZE)就好了。具体原因是一次调用cat会读两次,每次读取4096个字节,此时文件读指针ppos就是4096了,在第二次读的时候,到if (p >= GLOBALMEM_SIZE)这里条件为真,globalmem_read就返回ENXIO错误了,所以才会出现No such device or address"错误。不知道在宋老师的机子上为什么就是正确的?
<2> 宋宝华 :返回错误值才是正确的,因为读的位置已经越界,所以要返回错误。该返回错误的时候返回正确,那就是错误。改成if (p > GLOBALMEM_SIZE)是错误的。

<3> 根据上面两点可以小结书上是没有错误的。输出的错误信息是正常的debug信息,千不该万不该就是cat调用了read两次。
0


cat 会调用read两次?
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/types.h>
  5. #include <linux/errno.h>
  6. #include <linux/init.h>
  7. #include <linux/cdev.h>

  8. #include <asm/system.h>
  9. #include <asm/uaccess.h>

  10. #define GLOBALMEM_SIZE 0X1000 /* global memory size: 4kB */

  11. #define MEM_CLEAR 0X1        /* fill 0 to the global memory */

  12. #define GLOBALMEM_MAJOR 250        /* set globalmem device major number */

  13. MODULE_LICENSE("Dual BSD/GPL");


  14. static int globalmem_major = GLOBALMEM_MAJOR;
  15. static int globalmem_minor = 0;

  16. module_param(globalmem_major, int, S_IRUGO);

  17. /* define self dev struct */
  18. struct globalmem_dev
  19. {
  20.         struct cdev cdev;
  21.         unsigned char mem[GLOBALMEM_SIZE];
  22. };

  23. struct globalmem_dev *dev;        /* the object of the device struct */


  24. int globalmem_open(struct inode *inode, struct file *filp)
  25. {
  26.         struct globalmem_dev *dev;
  27.         dev = container_of(inode, struct globalmem_dev, cdev);
  28.         filp->private_data = dev;
  29.         return 0;
  30. }

  31. int globalmem_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  32. {
  33.         unsigned long p = *f_pos;
  34.         struct globalmem_dev *dev = filp->private_data;
  35.                
  36.         if (p >= GLOBALMEM_SIZE)
  37.         {
  38.                 return count ? ENXIO:0;
  39.         }        
  40.         
  41.         if (count > GLOBALMEM_SIZE - p)
  42.         {
  43.                 count = GLOBALMEM_SIZE - p;
  44.         }

  45.         if (copy_to_user(buf, (void *)(dev->mem + p), count))
  46.         {
  47.                 return -EFAULT;
  48.         }
  49.         printk(KERN_WARNING "The buf content is %s\n", buf);
  50.         *f_pos += count;

  51.         printk(KERN_NOTICE "read %d bytes from globalmem, and the content is %s\n", count, buf);

  52.         return count;
  53. }

  54. int globalmem_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  55. {
  56.         struct globalmem_dev *dev = filp->private_data;
  57.         unsigned long p = *f_pos;
  58.         
  59.         if (p > GLOBALMEM_SIZE)
  60.         {
  61.                 return count ? -ENXIO:0;
  62.         }        
  63.         
  64.         if (count > GLOBALMEM_SIZE - p)
  65.         {
  66.                 count = GLOBALMEM_SIZE - p;
  67.         }

  68.         if (copy_from_user(dev->mem + p, buf, count))
  69.         {
  70.                 printk(KERN_NOTICE "Writing data to device Fail\n");
  71.                 return -EFAULT;
  72.         }

  73.         printk(KERN_NOTICE "Writed %d bytes data to device\n", count);
  74.         *f_pos += count;

  75.         return count;
  76. }

  77. int globalmem_release(struct inode *inode, struct file *filp)
  78. {
  79.         return 0;
  80. }

  81. loff_t globalmem_llseek(struct file *filp, loff_t off_set, int orig)
  82. {
  83.         loff_t ret;
  84.         
  85.         switch(orig)
  86.         {
  87.         case 0: /* from the header of the file to move */
  88.                 if (off_set < 0)
  89.                 {
  90.                         ret = -EINVAL;
  91.                 }               
  92.                 else if ((unsigned int)off_set > GLOBALMEM_SIZE)
  93.                 {
  94.                         ret = -EINVAL;
  95.                 }
  96.                 else
  97.                 {
  98.                         filp->f_pos = (unsigned int)off_set;
  99.                         ret = filp->f_pos;
  100.                 }
  101.                 break;
  102.         case 1: /* from the current position of the file to move */
  103.                 if (off_set + filp->f_pos < 0 || off_set + filp->f_pos > GLOBALMEM_SIZE)
  104.                 {
  105.                         ret = -EINVAL;
  106.                 }
  107.                 else
  108.                 {
  109.                         filp->f_pos += off_set;
  110.                         ret = filp->f_pos;
  111.                 }
  112.                 break;
  113.         case 2:
  114.                 if (off_set > 0 || off_set + filp->f_pos < 0)
  115.                 {
  116.                         ret = -EINVAL;
  117.                 }
  118.                 else
  119.                 {
  120.                         filp->f_pos += off_set;
  121.                         ret = filp->f_pos;
  122.                 }
  123.                 break;
  124.         default:
  125.                 ret = -EINVAL;               
  126.         }

  127.         return ret;

  128. }


  129. int globalmem_ioctrl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  130. {
  131.         int ret;
  132.         struct globalmem_dev *dev = filp->private_data;
  133.         
  134.         switch(cmd)
  135.         {
  136.         case MEM_CLEAR:
  137.                 memset(dev->mem, 0, GLOBALMEM_SIZE);
  138.                 printk(KERN_NOTICE "globalmem memory content reset is zero\n");
  139.                 ret = 0;
  140.                 break;
  141.         default:
  142.                 ret = -EINVAL;
  143.         }

  144.         return ret;        
  145. }

  146. struct file_operations globalmem_fops =
  147. {
  148.         .owner = THIS_MODULE,
  149.         .open = globalmem_open,
  150.         .release = globalmem_release,
  151.         .read = globalmem_read,
  152.         .write = globalmem_write,
  153.         .ioctl = globalmem_ioctrl,
  154.         .llseek = globalmem_llseek,
  155. };

  156. void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
  157. {
  158.         int err;
  159.         dev_t devno = MKDEV(globalmem_major, globalmem_minor + index);
  160.         cdev_init(&(dev->cdev), &globalmem_fops);

  161.         dev->cdev.owner = THIS_MODULE;
  162.         err = cdev_add(&(dev->cdev), devno, 1);
  163.         if (err)
  164.         {
  165.                 printk(KERN_NOTICE "add cdev fail\n");
  166.         }        
  167. }

  168. static int globalmem_init(void)
  169. {
  170.         int result;
  171.         dev_t devno = MKDEV(globalmem_major, 0);
  172.         
  173.         if (globalmem_major)
  174.         {
  175.                 result = register_chrdev_region(devno, 1, "globalmem");
  176.         }
  177.         else
  178.         {
  179.                 result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
  180.                 globalmem_major = MAJOR(devno);
  181.         }

  182.         if (result < 0)
  183.         {
  184.                 printk(KERN_NOTICE "call globalmem_init fail!\n");
  185.                 return result;
  186.         }

  187.         dev = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
  188.         if (dev == NULL)
  189.         {
  190.                 printk(KERN_WARNING "Alloc gobalmem_dev Fail\n");
  191.                 unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);
  192.                 return 0;
  193.         }

  194.         memset(dev, 0, sizeof(struct globalmem_dev));

  195.         globalmem_setup_cdev(dev, 0);
  196.         
  197.         
  198.         return 0;
  199. }

  200. void globalmem_exit(void)
  201. {
  202.         cdev_del(&(dev->cdev));
  203.         unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);
  204. }

  205. module_init(globalmem_init);
  206. module_exit(globalmem_exit);
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP