Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1043805
  • 博文数量: 297
  • 博客积分: 11721
  • 博客等级: 上将
  • 技术积分: 3431
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-25 10:21
文章分类

全部博文(297)

文章存档

2016年(9)

2011年(71)

2010年(137)

2009年(80)

分类: C/C++

2009-07-14 18:01:31

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) |
给主人留下些什么吧!~~