免费注册 查看新帖 |

Chinaunix

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

ioctl函数总是抢先调用,求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-05-29 18:02 |只看该作者 |倒序浏览
大家好,我照LDD3写了一个驱动,然后写了一个用户空间应用去测试,然后就出现了一个很奇怪的问题,主要是针对ioctl的。
我的驱动是一个虚拟的,里面是一个链接表,写操作就向链表填加项,读就是读链表字符。ioctl的SCULL_IOCSET是向链表头加一个项,SCULL_IOCGET读链表每一个字符。SCULL_IOCCLEAR清空链表。

用户空间应用先是一个write函数,写26个英文字母,然后读出来,这都没出错,但是后来我读之后加入ioctl函数,然后问题就发生了。我发现ioctl函数总是先于write和read函数被执行,这是为什么呢?
shell执行结果如下:

[root@mini2440 /]# ./ioctl
Writting to scull0 :abcdefghijklmnopqrstuvwxyz...
cmd is 0x6b01,SCULL_IOCSET is 0x40046b02       //
cmd is 0x40016b02,SCULL_IOCSET is 0x40046b02//
cmd is 0x80016b03,SCULL_IOCSET is 0x40046b02//这三句是内核驱动模块中ioctl函数的打印结果。
Write OP Successful! 28 characters written.
Read from scull0 :abcdefghijklmnopqrstuvwxyz,OP successful!
Starting ioctl!......................................................
After clear ioctl:
set the first value 'm',then it reads:

What I get is :

求大侠帮解释一下,如果需要的话,下面是我的代码。先行谢了。
我的用户空间程序代码:
  1. #include <fcntl.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <linux/ioctl.h>
  5. #define SCULL_IOC_MAGIC  'k'  
  6. #define SCULL_IOCMAXCDMNR 3
  7. #define SCULL_IOCCLEAR  _IO(SCULL_IOC_MAGIC,1)
  8. #define SCULL_IOCSET  _IOW(SCULL_IOC_MAGIC,2,char)
  9. #define SCULL_IOCGET _IOR(SCULL_IOC_MAGIC,3,char)

  10. int  main()
  11. {
  12.   int ret;
  13.   int i;
  14.   int fd=open("/dev/scull0",O_RDWR);
  15.   char buf[28]="abcdefghijklmnopqrstuvwxyz";
  16.   char buff[28];
  17.   
  18.   printf("Writting to scull0 :%s...\n",buf);
  19.   
  20.   if(sizeof(buf)==write(fd,buf,sizeof(buf)))
  21.     printf("Write OP Successful! %d characters written.\n",sizeof(buf));
  22.   else
  23.     printf("Write error!\n");

  24.   if(sizeof(buf)==read(fd,buff,sizeof(buf)))
  25.     printf("Read from scull0 :%s,OP successful!\n",buff);
  26.   else
  27.     printf("Read error!\n");




  28.   
  29.   printf("Starting ioctl!......................................................\n");
  30.   ioctl(fd,SCULL_IOCCLEAR);
  31.   strcpy(buff,"");
  32.   read(fd,buff,sizeof(buf));
  33.   printf("After clear ioctl:%s\n",buff);
  34.   
  35.   buf[0]='m';
  36.   ioctl(fd,SCULL_IOCSET,&buf[0]);
  37.   read(fd,buff,sizeof(buf));
  38.   printf("set the first value 'm',then it reads:\n");
  39.   printf("%s\n",buff);
  40.   
  41.   
  42.   buff[0]=0;
  43.   ioctl(fd,SCULL_IOCGET,buff[0]);
  44.   printf("What I get is :%c\n",buff[0]);
  45.   
  46.   

  47.   
  48.   return 0;
  49. }
复制代码
我的驱动程序代码:
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/moduleparam.h>
  4. #include <linux/kdev_t.h>
  5. #include <linux/fs.h>
  6. #include <linux/cdev.h>
  7. #include <asm/uaccess.h>
  8. #include <linux/proc_fs.h>
  9. //#include <asm/semaphore.h>

  10. MODULE_LICENSE("Dual BSD/GPL");
  11. #define SCULL_USE_PROC
  12. #define MAX_PROC_IN 30
  13. #define SCULL_IOC_MAGIC  'k'  
  14. #define SCULL_IOCMAXCDMNR 3
  15. #define SCULL_IOCCLEAR  _IO(SCULL_IOC_MAGIC,1)
  16. #define SCULL_IOCSET  _IOW(SCULL_IOC_MAGIC,2,int)
  17. #define SCULL_IOCGET _IOR(SCULL_IOC_MAGIC,3,int)

  18. static int major=0;
  19. static int minor=0;
  20. static int  devCount=4;
  21. static char proc_in[MAX_PROC_IN]="";

  22. struct scull_buf{
  23.   char value;
  24.   struct scull_buf * next;
  25. };
  26. struct scull_dev{
  27.   struct cdev cdev;
  28.   struct  scull_buf  *bufHead;
  29.   struct semaphore sem;
  30. };

  31. struct scull_dev * scull;

  32. int scull_open(struct inode * inode ,struct file *filp)
  33. {
  34.   struct scull_dev *dev;
  35.   dev=container_of(inode->i_cdev,struct scull_dev,cdev);
  36.   filp->private_data=dev;//for later use in other methods.
  37.   return 0;
  38. }

  39. int scull_release(struct inode *inode,struct file *filp)
  40. {
  41.   return 0;
  42. }

  43. ssize_t scull_write(struct file *filp,const char __user *buff,size_t count,loff_t *offp)
  44. {
  45.   int i;
  46.   struct scull_dev * dev=filp->private_data;
  47.   struct scull_buf *bptr=NULL;

  48.   if (down_interruptible (&dev->sem))
  49.                 return -ERESTARTSYS;
  50.   
  51.   for(i=0;i<count;i++)
  52.   {
  53.     struct scull_buf *tmp=kmalloc(sizeof(struct scull_buf),GFP_KERNEL);
  54.    
  55.     if(!copy_from_user(&tmp->value,buff++,1))
  56.     {
  57.       tmp->next=NULL;
  58.       if(i==0)
  59.       {
  60.         dev->bufHead=tmp;
  61.         bptr=tmp;
  62.       }
  63.       else
  64.       {
  65.         bptr->next=tmp;
  66.         bptr=tmp;
  67.       }
  68.     }
  69.     else
  70.     {
  71.       printk(KERN_ALERT"Copy from user failed!\n");
  72.       return -EFAULT;
  73.     }
  74.   }

  75. up (&dev->sem);
  76. return count;
  77.   
  78. }

  79. ssize_t scull_read(struct file *filp,char __user *buff,size_t count,loff_t * offp)
  80. {
  81.   int i;
  82.   struct scull_dev * dev=filp->private_data;
  83.   struct scull_buf *bptr=dev->bufHead;
  84.   
  85.   if(down_interruptible(&dev->sem))
  86.     return -ERESTARTSYS;

  87.   for(i=0;i<count&&bptr!=NULL;i++)
  88.   {
  89.     if(!copy_to_user(buff++,&(bptr->value),1)==1)
  90.       bptr=bptr->next;
  91.     else
  92.     {
  93.       printk(KERN_INFO"Copy to user failed!");
  94.     }
  95.   }
  96.   up(&dev->sem);
  97.   return count;
  98. }

  99. int scull_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
  100. {
  101.   int err=0,ret=0;
  102.   struct scull_dev * dev=filp->private_data;
  103.   struct scull_buf * buf=dev->bufHead;

  104.   if(_IOC_TYPE(cmd)!=SCULL_IOC_MAGIC) return -ENOTTY;
  105.   if(_IOC_NR(cmd)>SCULL_IOCMAXCDMNR) return -ENOTTY;

  106. /*
  107.   if(_IOC_DIR(cmd)&_IOC_READ)
  108.     err=!access_ok(VERIFY_WRITE,(void __user *)arg ,_IOC_SIZE(cmd));
  109.   else if(_IOC_DIR(cmd)&_IOC_WRITE)
  110.     err=!access_ok(VERIFY_READ,(void __user *)arg, _IOC_SIZE(cmd));
  111.   if(err) return -ENOTTY;*/
  112. printk("cmd is 0x%x,SCULL_IOCSET is 0x%x\n",cmd,SCULL_IOCSET);
  113.   

  114.   switch (cmd)
  115.   {
  116.     case SCULL_IOCCLEAR:
  117.       while(buf!=NULL)
  118.       {
  119.         struct scull_buf * b;
  120.         b=buf->next;
  121.         kfree(buf);
  122.         buf=b;
  123.       }
  124.       break;
  125.       
  126.     case SCULL_IOCSET:
  127.     {
  128.       struct scull_buf *b;
  129.      // while(buf!=NULL&&buf->value!=0)
  130.         //buf=buf->next;
  131.      // b=buf->next;
  132.       b=kmalloc(sizeof(struct scull_buf),GFP_KERNEL);
  133.       ret=__get_user(b->value,(char __user *)arg);
  134.       b->next=buf->next;
  135.       kfree(buf);
  136.       buf=b;
  137.       printk("%c........",b->value);
  138.     }
  139.     break;
  140.     case SCULL_IOCGET:
  141.     {
  142.       ret=__put_user(buf->value,(char __user *)arg);
  143.     }
  144.     break;
  145.     default:
  146.       return -ENOTTY;
  147.   }
  148.   dev->bufHead=buf;
  149.   return ret;
  150. }
  151.       
  152.       
  153.       
  154. #ifdef SCULL_USE_PROC
  155. static int proc_scull_read(char * buf,char **start,off_t offset,int len,int *eof,void *data)
  156. {
  157.   int i,count=0;
  158.   struct scull_buf * buff;
  159.   for(i=0;i<devCount;i++)
  160.   {
  161.     if((scull+i)->bufHead==NULL)
  162.       count+=sprintf(buf+count,"scull%d is empty.\n",i);
  163.     else
  164.     {
  165.       buff=(scull+i)->bufHead;
  166.       count+=sprintf(buf+count,"scull%d is :\n",i);
  167.       while(buff!=NULL)
  168.       {
  169.         count+=sprintf(buf+count,"%c",buff->value);
  170.         buff=buff->next;
  171.       }
  172.       count+=sprintf(buf+count,"\n");
  173.     }
  174.   }
  175.   
  176.   count+=sprintf(buf+count,"proc_in:%s",proc_in);
  177.   return count;
  178. }

  179. static ssize_t proc_scull_write(struct file *filp,const char __user * buf,unsigned long len,void *data)
  180. {
  181.   if(len<=MAX_PROC_IN)       
  182.     if(!copy_from_user(proc_in,buf,len))
  183.       printk(KERN_INFO"Write done!\n");
  184.   return len;
  185. }


  186. static struct proc_dir_entry * proc_scull_entry;   
  187. #endif

  188. struct file_operations scull_ops={
  189.   .owner=THIS_MODULE,
  190.   .open=scull_open,
  191.   .release=scull_release,
  192.   .write= scull_write,
  193.   .read=scull_read,
  194.   .ioctl=scull_ioctl,
  195. };

  196. static void scull_setup_cdev(struct scull_dev *dev,int index)
  197. {
  198.   int err;
  199.   dev_t devno=MKDEV(major,minor+index);
  200.   cdev_init(&dev->cdev,&scull_ops);
  201.   dev->cdev.owner=THIS_MODULE;
  202.   dev->bufHead=NULL;
  203.   //dev->cdev.ops=&scull_fops;//don't know about what it is like in other version of kernel,but in 2.6.30,this is not at all neccessary.
  204.   //it's already done by cdev_init.
  205.   err=cdev_add(&dev->cdev,devno,1);
  206.   /*fail gracefully if need be */
  207.   if(err)
  208.     printk(KERN_NOTICE"Error %d adding scull%d",err,index);
  209. }
  210. static int scull_init(void)
  211. {
  212.   int ret,i;
  213.   static dev_t devno;
  214.     if(major==0)
  215.   {
  216.     ret=alloc_chrdev_region(&devno ,minor,devCount,"scull");
  217.     major=MAJOR(devno);
  218.     minor=MINOR(devno);
  219.   }
  220.   else
  221.   {
  222.     devno=MKDEV(major,minor);
  223.     ret=register_chrdev_region(devno,devCount,"scull");
  224.   }
  225.   if(ret<0)
  226.   {
  227.     printk(KERN_WARNING "scull:can't get major %d\n",major);
  228.     return ret;
  229.   }
  230.   else
  231.      printk(KERN_ALERT"Dev_t registered:%d ,%d\n",major,minor);
  232.   scull=kmalloc(devCount*sizeof(struct scull_dev),GFP_KERNEL);
  233.   if(!scull)
  234.   {
  235.     ret=-ENOMEM;
  236.     printk(KERN_INFO"fail malloc for scull_dev\n");
  237.     goto fail_malloc;
  238.   }
  239.   memset(scull,0,devCount*sizeof(struct scull_dev));
  240.   
  241.   for(i=0;i<devCount;i++)
  242.   {
  243.     scull_setup_cdev(scull+i,i);
  244.     sema_init(&(scull+i)->sem,1);
  245.   }
  246.   
  247. #ifdef SCULL_USE_PROC
  248.   proc_scull_entry=create_proc_entry("scull",0,NULL);
  249.   if(proc_scull_entry)
  250.   {
  251.     proc_scull_entry->read_proc=proc_scull_read;
  252.     proc_scull_entry->write_proc=proc_scull_write;
  253.   }
  254.   else
  255.     printk(KERN_ERR"Proc file scull registration failed!\n");
  256. #endif
  257.   
  258.   fail_malloc:
  259.   unregister_chrdev_region(devno,devCount);
  260.   return 0;
  261. }
  262. static void scull_exit(void)
  263. {
  264.   static dev_t devno;
  265.   int i;
  266. #ifdef SCULL_USE_PROC
  267.   remove_proc_entry("scull",NULL);
  268. #endif
  269.   
  270.   for(i=0;i<devCount;i++)
  271.   {
  272.     cdev_del(&scull[i].cdev);
  273.   }
  274.   kfree(scull);
  275.   unregister_chrdev_region(devno,devCount);
  276. }

  277. module_param(major,int,S_IRUGO);
  278. module_init(scull_init);
  279. module_exit(scull_exit);
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP