- 论坛徽章:
- 0
|
大家好,我照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 :
求大侠帮解释一下,如果需要的话,下面是我的代码。先行谢了。
我的用户空间程序代码:- #include <fcntl.h>
- #include <string.h>
- #include <stdio.h>
- #include <linux/ioctl.h>
- #define SCULL_IOC_MAGIC 'k'
- #define SCULL_IOCMAXCDMNR 3
- #define SCULL_IOCCLEAR _IO(SCULL_IOC_MAGIC,1)
- #define SCULL_IOCSET _IOW(SCULL_IOC_MAGIC,2,char)
- #define SCULL_IOCGET _IOR(SCULL_IOC_MAGIC,3,char)
- int main()
- {
- int ret;
- int i;
- int fd=open("/dev/scull0",O_RDWR);
- char buf[28]="abcdefghijklmnopqrstuvwxyz";
- char buff[28];
-
- printf("Writting to scull0 :%s...\n",buf);
-
- if(sizeof(buf)==write(fd,buf,sizeof(buf)))
- printf("Write OP Successful! %d characters written.\n",sizeof(buf));
- else
- printf("Write error!\n");
- if(sizeof(buf)==read(fd,buff,sizeof(buf)))
- printf("Read from scull0 :%s,OP successful!\n",buff);
- else
- printf("Read error!\n");
-
-
- printf("Starting ioctl!......................................................\n");
- ioctl(fd,SCULL_IOCCLEAR);
- strcpy(buff,"");
- read(fd,buff,sizeof(buf));
- printf("After clear ioctl:%s\n",buff);
-
- buf[0]='m';
- ioctl(fd,SCULL_IOCSET,&buf[0]);
- read(fd,buff,sizeof(buf));
- printf("set the first value 'm',then it reads:\n");
- printf("%s\n",buff);
-
-
- buff[0]=0;
- ioctl(fd,SCULL_IOCGET,buff[0]);
- printf("What I get is :%c\n",buff[0]);
-
-
-
- return 0;
- }
复制代码 我的驱动程序代码:- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kdev_t.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <asm/uaccess.h>
- #include <linux/proc_fs.h>
- //#include <asm/semaphore.h>
- MODULE_LICENSE("Dual BSD/GPL");
- #define SCULL_USE_PROC
- #define MAX_PROC_IN 30
- #define SCULL_IOC_MAGIC 'k'
- #define SCULL_IOCMAXCDMNR 3
- #define SCULL_IOCCLEAR _IO(SCULL_IOC_MAGIC,1)
- #define SCULL_IOCSET _IOW(SCULL_IOC_MAGIC,2,int)
- #define SCULL_IOCGET _IOR(SCULL_IOC_MAGIC,3,int)
- static int major=0;
- static int minor=0;
- static int devCount=4;
- static char proc_in[MAX_PROC_IN]="";
- struct scull_buf{
- char value;
- struct scull_buf * next;
- };
- struct scull_dev{
- struct cdev cdev;
- struct scull_buf *bufHead;
- struct semaphore sem;
- };
- struct scull_dev * scull;
- int scull_open(struct inode * inode ,struct file *filp)
- {
- struct scull_dev *dev;
- dev=container_of(inode->i_cdev,struct scull_dev,cdev);
- filp->private_data=dev;//for later use in other methods.
- return 0;
- }
- int scull_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- ssize_t scull_write(struct file *filp,const char __user *buff,size_t count,loff_t *offp)
- {
- int i;
- struct scull_dev * dev=filp->private_data;
- struct scull_buf *bptr=NULL;
- if (down_interruptible (&dev->sem))
- return -ERESTARTSYS;
-
- for(i=0;i<count;i++)
- {
- struct scull_buf *tmp=kmalloc(sizeof(struct scull_buf),GFP_KERNEL);
-
- if(!copy_from_user(&tmp->value,buff++,1))
- {
- tmp->next=NULL;
- if(i==0)
- {
- dev->bufHead=tmp;
- bptr=tmp;
- }
- else
- {
- bptr->next=tmp;
- bptr=tmp;
- }
- }
- else
- {
- printk(KERN_ALERT"Copy from user failed!\n");
- return -EFAULT;
- }
- }
-
- up (&dev->sem);
- return count;
-
- }
- ssize_t scull_read(struct file *filp,char __user *buff,size_t count,loff_t * offp)
- {
- int i;
- struct scull_dev * dev=filp->private_data;
- struct scull_buf *bptr=dev->bufHead;
-
- if(down_interruptible(&dev->sem))
- return -ERESTARTSYS;
- for(i=0;i<count&&bptr!=NULL;i++)
- {
- if(!copy_to_user(buff++,&(bptr->value),1)==1)
- bptr=bptr->next;
- else
- {
- printk(KERN_INFO"Copy to user failed!");
- }
- }
- up(&dev->sem);
- return count;
- }
- int scull_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
- {
- int err=0,ret=0;
- struct scull_dev * dev=filp->private_data;
- struct scull_buf * buf=dev->bufHead;
- if(_IOC_TYPE(cmd)!=SCULL_IOC_MAGIC) return -ENOTTY;
- if(_IOC_NR(cmd)>SCULL_IOCMAXCDMNR) return -ENOTTY;
- /*
- if(_IOC_DIR(cmd)&_IOC_READ)
- err=!access_ok(VERIFY_WRITE,(void __user *)arg ,_IOC_SIZE(cmd));
- else if(_IOC_DIR(cmd)&_IOC_WRITE)
- err=!access_ok(VERIFY_READ,(void __user *)arg, _IOC_SIZE(cmd));
- if(err) return -ENOTTY;*/
- printk("cmd is 0x%x,SCULL_IOCSET is 0x%x\n",cmd,SCULL_IOCSET);
-
- switch (cmd)
- {
- case SCULL_IOCCLEAR:
- while(buf!=NULL)
- {
- struct scull_buf * b;
- b=buf->next;
- kfree(buf);
- buf=b;
- }
- break;
-
- case SCULL_IOCSET:
- {
- struct scull_buf *b;
- // while(buf!=NULL&&buf->value!=0)
- //buf=buf->next;
- // b=buf->next;
- b=kmalloc(sizeof(struct scull_buf),GFP_KERNEL);
- ret=__get_user(b->value,(char __user *)arg);
- b->next=buf->next;
- kfree(buf);
- buf=b;
- printk("%c........",b->value);
- }
- break;
- case SCULL_IOCGET:
- {
- ret=__put_user(buf->value,(char __user *)arg);
- }
- break;
- default:
- return -ENOTTY;
- }
- dev->bufHead=buf;
- return ret;
- }
-
-
-
- #ifdef SCULL_USE_PROC
- static int proc_scull_read(char * buf,char **start,off_t offset,int len,int *eof,void *data)
- {
- int i,count=0;
- struct scull_buf * buff;
- for(i=0;i<devCount;i++)
- {
- if((scull+i)->bufHead==NULL)
- count+=sprintf(buf+count,"scull%d is empty.\n",i);
- else
- {
- buff=(scull+i)->bufHead;
- count+=sprintf(buf+count,"scull%d is :\n",i);
- while(buff!=NULL)
- {
- count+=sprintf(buf+count,"%c",buff->value);
- buff=buff->next;
- }
- count+=sprintf(buf+count,"\n");
- }
- }
-
- count+=sprintf(buf+count,"proc_in:%s",proc_in);
- return count;
- }
- static ssize_t proc_scull_write(struct file *filp,const char __user * buf,unsigned long len,void *data)
- {
- if(len<=MAX_PROC_IN)
- if(!copy_from_user(proc_in,buf,len))
- printk(KERN_INFO"Write done!\n");
- return len;
- }
- static struct proc_dir_entry * proc_scull_entry;
- #endif
- struct file_operations scull_ops={
- .owner=THIS_MODULE,
- .open=scull_open,
- .release=scull_release,
- .write= scull_write,
- .read=scull_read,
- .ioctl=scull_ioctl,
- };
- static void scull_setup_cdev(struct scull_dev *dev,int index)
- {
- int err;
- dev_t devno=MKDEV(major,minor+index);
- cdev_init(&dev->cdev,&scull_ops);
- dev->cdev.owner=THIS_MODULE;
- dev->bufHead=NULL;
- //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.
- //it's already done by cdev_init.
- err=cdev_add(&dev->cdev,devno,1);
- /*fail gracefully if need be */
- if(err)
- printk(KERN_NOTICE"Error %d adding scull%d",err,index);
- }
- static int scull_init(void)
- {
- int ret,i;
- static dev_t devno;
- if(major==0)
- {
- ret=alloc_chrdev_region(&devno ,minor,devCount,"scull");
- major=MAJOR(devno);
- minor=MINOR(devno);
- }
- else
- {
- devno=MKDEV(major,minor);
- ret=register_chrdev_region(devno,devCount,"scull");
- }
- if(ret<0)
- {
- printk(KERN_WARNING "scull:can't get major %d\n",major);
- return ret;
- }
- else
- printk(KERN_ALERT"Dev_t registered:%d ,%d\n",major,minor);
- scull=kmalloc(devCount*sizeof(struct scull_dev),GFP_KERNEL);
- if(!scull)
- {
- ret=-ENOMEM;
- printk(KERN_INFO"fail malloc for scull_dev\n");
- goto fail_malloc;
- }
- memset(scull,0,devCount*sizeof(struct scull_dev));
-
- for(i=0;i<devCount;i++)
- {
- scull_setup_cdev(scull+i,i);
- sema_init(&(scull+i)->sem,1);
- }
-
- #ifdef SCULL_USE_PROC
- proc_scull_entry=create_proc_entry("scull",0,NULL);
- if(proc_scull_entry)
- {
- proc_scull_entry->read_proc=proc_scull_read;
- proc_scull_entry->write_proc=proc_scull_write;
- }
- else
- printk(KERN_ERR"Proc file scull registration failed!\n");
- #endif
-
- fail_malloc:
- unregister_chrdev_region(devno,devCount);
- return 0;
- }
- static void scull_exit(void)
- {
- static dev_t devno;
- int i;
- #ifdef SCULL_USE_PROC
- remove_proc_entry("scull",NULL);
- #endif
-
- for(i=0;i<devCount;i++)
- {
- cdev_del(&scull[i].cdev);
- }
- kfree(scull);
- unregister_chrdev_region(devno,devCount);
- }
- module_param(major,int,S_IRUGO);
- module_init(scull_init);
- module_exit(scull_exit);
复制代码 |
|