Chinaunix首页 | 论坛 | 博客
  • 博客访问: 216008
  • 博文数量: 76
  • 博客积分: 106
  • 博客等级: 民兵
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 16:55
文章分类

全部博文(76)

文章存档

2014年(47)

2013年(2)

2012年(20)

2011年(7)

分类:

2012-09-22 20:53:25

原文地址:ioctl 传输大数据量 作者:gududesiling

之前在csdn上发了个帖子,讨论这个问题:帖子地方:

后来还是自己最终解决了:我发当时的意思给粘贴在这:

  1. 我的问题是我试过4k的,能传输下去了
  2. 但是4k以上的就传不下去,app和drv层涉及主要的结构体和函数列出如下:

  3. app:
  4. typedef struct {
  5.       unsigned int type;
  6.       unsigned int addr;
  7.       unsigned int len;
  8.       unsigned int cmd;
  9.       unsigned int *prv;
  10. }fpga_opt_t;
  11. unsigned char ramdata[4096*4];
  12. memset(ramdata,0x07, 4096*4* sizeof(unsigned char));
  13. wt.addr = addr;
  14. wt.len = len;
  15. wt.prv =(unsigned int *) ramdata;
  16. retval =ioctl(scfd,3094,&wt);


  17. drv:
  18. static int wmsc_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
  19. {
  20.       fpga_opt_t tmp;
  21.       fpga_opt_t *ptmp = &tmp;
  22.       
  23.       switch(cmd)
  24.       {
  25.             case 3094:
  26.             printk("\nwmsc_write is write ram is:\n");
  27.             copy_from_user((unsigned char *)ptmp,(unsigned char *)arg,sizeof(fpga_opt_t));
  28.             
  29.             start =4093;
  30.             for( i=start; i<(start +16); i++){    
  31.             if( i%8 ==0)
  32.             printk("\n");    
  33.             printk("0x%04x ",*( (unsigned char *)( ( (fpga_opt_t *)ptmp)->prv +i)) );    
  34.       }
  35.       break;    
  36. }

  37. 上面的start参数为4093,所以打印出了如下的数据:
  38. 0x0007 0x0007 0x0007
  39. 0x0000 0x0000 0x0031 0x0031 0x000f 0x0000 0x0000 0x0000
  40. 0x0000 0x0000 0x0000 0x0000 0x0000
  41. 说明前三个是正确的,后面的都是随机的

  42. 同时,我修改start参数,当在0-4096之间的话,就可以输出0x0007,而一旦大于4096,输出基本为0.

  43. 这个证明了,ioctl只能传递4k大小的数据么?还是我程序中有问题。


  44. 问题解决了:
  45. 说一个我的方法,并且我相信大家以后也会碰到这个问题的,在ddrIII中也讲述了关于ioctl来传递数据的问题,但是没有讲述操作大量数据的方法。

  46. 实际上我上面也提到了方法,就是回复1楼得一个帖子中,再次使用copy_from_user,把用户空间的那个指针指向的区域也传下来:
  47. 具体程序中执行的方法,我列出来(我把我提的问题中的drv下的ioctl修改一下如下:):
  48. static int wmsc_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
  49. {
  50.       fpga_opt_t tmp;
  51.       fpga_opt_t *ptmp = &tmp;
  52.       char *pbuff_ram1; //预先定义一个指针
  53.       
  54.       
  55.       switch(cmd)
  56.       {
  57.             case 3094:
  58.                   printk("\nwmsc_write is write ram is:\n");
  59.                   copy_from_user((unsigned char *)ptmp,(unsigned char *)arg,sizeof(fpga_opt_t));
  60.                   pbuff_ram1=(char *)kmalloc(4096 *4*sizeof(char),GFP_KERNEL);
  61.                   
  62.                   copy_from_user((unsigned char *)pbuff_ram1,(unsigned char *)(( (fpga_opt_t *)ptmp)->prv),4096 *4);start =4093;
  63.                   
  64.                   start =16370;
  65.                   for( i=start; i<(start +16); i++){
  66.                   if( i%8 ==0)
  67.                         printk("\n");    
  68.                         printk("0x%04x ",*( (unsigned char *)( pbuff_ram1 +i)) );    
  69.                   }    
  70.                   break;
  71.                   kfree(pbuff_ram1);
  72. }


  73. 可以看到我把start改为16370,已经快接近16K的大小了,新的打印信息如下:
  74. 0x0007 0x0007 0x0007 0x0007 0x0007 0x0007
  75. 0x0007 0x0007 0x0007 0x0007 0x0007 0x0007 0x0007 0x0007

  76. 说明新的修改方法正确了。。。
  77. 希望我的这个方法可以帮到其他的人。。。


记录下来,以后学习。。。
阅读(1061) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~