- 论坛徽章:
- 0
|
6可用积分
/*globalfifo读函数*/
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count,
loff_t *ppos)
{
int ret;
struct globalfifo_dev *dev = filp->private_data; //获得设备结构体指针
DECLARE_WAITQUEUE(wait, current); //定义等待队列
down(&dev->sem); //此函数包含了进入睡眠的动作吗?
add_wait_queue(&dev->r_wait, &wait); //为何要在获得信号量后进入读等待队列头?
/* 等待FIFO非空 */
while (dev->current_len == 0)
{
if (filp->f_flags &O_NONBLOCK) //?
{
ret = - EAGAIN; //?
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE); //改变进程状态为睡眠
up(&dev->sem);
schedule(); //调度其他进程执行
if (signal_pending(current)) //?
//如果是因为信号唤醒
{
ret = - ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
/* 拷贝到用户空间 */
if (count > dev->current_len)
count = dev->current_len;
if (copy_to_user(buf, dev->mem, count))
{
ret = - EFAULT;
goto out;
}
else
{
memcpy(dev->mem, dev->mem + count, dev->current_len - count); //fifo数据前移
dev->current_len -= count; //有效数据长度减少
printk(KERN_INFO "read %d bytes(s),current_len:%d\n", count, dev->current_len);
wake_up_interruptible(&dev->w_wait); //唤醒写等待队列
ret = count;
}
out: up(&dev->sem); //释放信号量
out2:remove_wait_queue(&dev->w_wait, &wait); //从附属的等待队列头移除
set_current_state(TASK_RUNNING);
return ret;
}
本人对阻塞操作还是不能结合这个实际例子加以理解。
我只能理解:从进入睡眠wait_event()到睡眠唤醒wake_up()
可这里没有wait_event()相关函数,为什么?
另外,这里的睡眠、等待队列,和信号量又有什么关系??看书都看晕了!!
[ 本帖最后由 todayrw 于 2009-4-20 17:41 编辑 ] |
最佳答案
查看完整内容
首先应从总体上把握程序的思想,信号量在这儿涉及到两个函数:此处你给出的读函数,还有一个你没有给出的写函数(globalfifo_write)。globalfifo_dev 结构表示底层被驱动的硬件(此处可能只是表示软件模拟的一个环形FIFO),这个结构显然定义了两个进程睡眠队列:r_wait,w_wait,即一个读数据的进程睡眠队列和一个写数据进程的睡眠队列。由于读写进程操作的是同一块区域,所以这块区域就成为我们通常所说的“临界区”,读写进程不 ...
|