struct scull_pipe
{
wait_queue_head_t inq, outq; //读写对列
char *buffer, *end; //缓冲区头指针/未指针
int buffersize; //缓冲区大小
char *rp, *wp; //读指针位置,写指针位置
int nreaders, nwriters; /* number of openings for r/w */
struct fasync_struct *async_queue; /* asynchronous readers */
struct semaphore sem; //旗标
struct cdev cdev; //字符设备结构
};
static ssize_t scull_p_read (struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct scull_pipe *dev = filp->private_data; //用户私有数据
if (down_interruptible(&dev->sem)) //获得设备旗标
return -ERESTARTSYS;
while (dev->rp == dev->wp) //等待数据:如果不存在数据,循环等待
{ /* nothing to read */
up(&dev->sem); /* release the lock */
if (filp->f_flags & O_NONBLOCK) //判断是否为非阻塞IO
return -EAGAIN;
PDEBUG("\"%s\" reading: going to sleep\n", current->comm);
if (wait_event_interruptible(dev->inq, (dev->rp != dev->wp))) //有数据产生,唤醒读进程队列
return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ /* otherwise loop, but first reacquire the lock */
if (down_interruptible(&dev->sem)) //获得设备旗标
return -ERESTARTSYS;
}
/* ok, data is there, return something */
//开始处理数据
if (dev->wp > dev->rp)
count = min(count, (size_t)(dev->wp - dev->rp));
else /* the write pointer has wrapped, return data up to dev->end */
//写指针小于读指针位置,说明数据已经写满队列,并且写指针在写操作中被重置.此时count=尾指针-读指针
count = min(count, (size_t)(dev->end - dev->rp));
if (copy_to_user(buf, dev->rp, count)) //向用户空间拷贝数据
{
up (&dev->sem); //释放设备旗标
return -EFAULT;
}
dev->rp += count; //更新读指针位置
if (dev->rp == dev->end)
dev->rp = dev->buffer; //读到队尾,重新置头指针 /* wrapped */
up (&dev->sem); //释放设备旗标
/* finally, awake any writers and return */
//唤醒写进程队列
wake_up_interruptible(&dev->outq);
PDEBUG("\"%s\" did read %li bytes\n",current->comm, (long)count);
return count;
}
阅读(777) | 评论(0) | 转发(0) |