有关驱动开发里面队列的问题

linyilong3 2011-03-21 11:30:25


static ssize_t globalfifo_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos)
{
int ret;
DECLARE_WAITQUEUE(wait,current);
down(&globalfifo_devp->sem);
add_wait_queue(&globalfifo_devp->w_wait,&wait);
if(globalfifo_devp->current_len==GLOBALFIFO_SIZE)
{
if(filp->f_flags & O_NONBLOCK)
{
ret=-EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&globalfifo_devp->sem);

schedule();
if(signal_pending(current))
{
ret=-ERESTARTSYS;
goto out2;
}
down(&globalfifo_devp->sem);
}
if(count>GLOBALFIFO_SIZE-globalfifo_devp->current_len)
count=GLOBALFIFO_SIZE-globalfifo_devp->current_len;

if(copy_from_user(globalfifo_devp->mem+globalfifo_devp->current_len,buf,count))
{
ret=-EFAULT;
goto out;
}
else
{
globalfifo_devp->current_len +=count;
printk(KERN_INFO"written %d bytes ,curren_len:%d\n",count,globalfifo_devp->current_len);
wake_up_interruptible(&globalfifo_devp->r_wait);
ret=count;
}

out:up(&globalfifo_devp->sem);
out2:remove_wait_queue(&globalfifo_devp->w_wait,&wait);
set_current_state(TASK_RUNNING);
return ret;
}


static ssize_t globalfifo_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)
{
int ret;
DECLARE_WAITQUEUE(wait,current);
down(&globalfifo_devp->sem);
add_wait_queue(&globalfifo_devp->r_wait,&wait);
if(globalfifo_devp->current_len==0)
{
if(filp->f_flags & O_NONBLOCK)
{
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&globalfifo_devp->sem);
schedule();
if(signal_pending(current))
{
ret =-ERESTARTSYS;
goto out2;
}
down(&globalfifo_devp->sem);
}

if(count>globalfifo_devp->current_len)
count=globalfifo_devp->current_len;
if(copy_to_user(buf,globalfifo_devp->mem,count))
{
ret=-EFAULT;
goto out;
}
else
{
memcpy(globalfifo_devp->mem,globalfifo_devp->mem+count,globalfifo_devp->current_len-count);
globalfifo_devp->current_len-=count;
printk(KERN_INFO"read %d bytes,current_len:%d\n",count,globalfifo_devp->current_len);
wake_up_interruptible(&globalfifo_devp->w_wait);
ret=count;
}
out:up(&globalfifo_devp->sem);
out2:remove_wait_queue(&globalfifo_devp->w_wait,&wait);
return ret;
}


上面这段代码是读和写的,有几个问题
1.我执行cat /dev/globalfifo &后,然后echo "hello" > /dev/globalfifo,这个时候输出hello没错,但是不是程序应该直接结束吗?怎么好像可以再重复,好像没有while循环之类的把程序又跳到globalfifo_read的开头

2.DECLARE_WAITQUEUE(wait,current)的wait和current是在内核中就定义的吗?如果是那么read和write是否是在同一个等待队列里面?

3.当我执行cat /dev/globalfifo后,程序阻塞在哪条语句里面?
...全文
52 点赞 收藏 3
写回复
3 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
linyilong3 2011-03-23
谢谢LS的了
回复
lvyinghong 2011-03-22
DECLARE_WAITQUEUE(wait,current)
这个应该是定义了一个名字叫做wait的 waitqueue 结构, current是内核的预定义的宏,表示当前进程task结构。

关键是 add_wait_queue(&globalfifo_devp->r_wait,&wait);
这个把wait加到 一个全局的等待队列里面去了,所以你read和write函数都是等待的同一个&globalfifo_devp->r_wait 。


wake_up_interruptible(&globalfifo_devp->w_wait);
的时候就唤醒对方了。

当你执行 cat /dev/globalfifo的时候,因为这时globalfifo_devp->current_len==0)
所以你执行到 schedule();的时候会把自己调度出去,也就是说停到这里了,一直等待对方的唤醒。


当有写入的时候就执行的到wake_up在唤醒这个读进程了。


你看到的cat /dev/globalfifo 不会退出的原因是因为是,cat 会尝试读一直度到文件末尾。所以你第一个 globalfifo_read 返回hello时,cat认为你文件里面还有内容,会进行第二次globalfifo_read 的。你要设置 globalfifo_read 的返回值让cat知道已经读到文件末尾才行的。 不然第二次进来的时候有会断在那里。 你可以传个参数给cat让他只读指定的长度看看。
回复
相关推荐
发帖
Linux_Kernel
创建于2007-08-27

4113

社区成员

Linux/Unix社区 内核源代码研究区
申请成为版主
帖子事件
创建了帖子
2011-03-21 11:30
社区公告
暂无公告