首页 > 学院 > 开发设计 > 正文

高级字符驱动之堵塞与非堵塞IO

2019-11-06 08:54:40
字体:
来源:转载
供稿:网友
/** *此实例涉及到线程的挂起与竞态,字符IO的堵塞与非堵塞 */struct scull_pipe { wait_queue_head_t inp, outp; char *buffer, *end; char *rp, wp; //int buffersize; int nreaders, nwriters; struct fasync_struct *async_queue; struct semaphore sem; struct cdev cdev;};/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * /inlcude/linux/kernel.h * *//*#define container_of(ptr, type, member) ({ / const typeof( ((type *)0)->member ) *__mptr = (ptr); / (type *)( (char *)__mptr - offsetof(type,member) );})*/static ssize_t scull_p_read (struct file *filp, char __user *buffer, size_t count, loff_t *f_pos){ /*得到指向结构体scull_pipe的指针*/ /* (void *PRivate_data)private_data指针是file结构体中的成员之一, 它是跨系统挑用是保存状态信息的非常有用的资源,这里我们 在open阶段使用container_of函数得到指向结构体scull_pipe的指针并将private_data指向它 记住要在release方法中释放其内存 */ struct scull_pipe *dev = filp->private_data; /*使用信号量限制在同一时刻只有一个线程执行*/ /*若被中断则返回非零值,若无法撤销任何用户可见的修改return - EINTR*/ if (down_interruptible(&dev->sem)) return -ERESTARTSYS; while (dev->rp == dev->wp) { up_interruptible(&dev->sem); /*判断用户是否设置了非堵塞IO*/ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; /*将线程挂起*/ if (wait_event_interruptible(&dev->inp, dev->rp != dev->wp)) return -ERESTARTSYS; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; } /*min函数在Linux内核/include/linux/kernel.h中*/ if (dev->wp > dev->rp) count = min(count, (size_t) (dev->wp - dev->rp)); else count = min(count, (size_t) (dev->end - dev->rp)); if (copy_to_user(buffer, dev->rp, count)) { up_interruptible(&dev->sem); return -EFAULT; } dev->rp += count; if (dev->rp == dev->end) dev->rp = dev->buffer up_interruptible(&dev->sem); wake_up_interruptible(&dev->outp); return count;}/*个人仿照上方写的管道写操作代码*/static ssize_t scull_p_write (struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos){ struct scull_pipe *dev = filp->private_data; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; /*判断条件有所不同*/ while (strlen(dev->buffer) && dev->rp == dev->wp) { up_interruptible(&dev->sem); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(&dev->outp)) return -ERESTARTSYS; down_interruptible(&dev->sem); } if (dev->wp > dev->rp) count = min(count, (size_t) (dev->end - dev->wp)); else count = min(count, (size_t) (dev->rp - dev->wp - 1)); if (copy_form_user(dev->wp, buffer, count)) { up_interruptible(&dev->sem); return -EFAULT; } dev->wp += count; if (dev->wp == dev->end) dev->wp = dev->buffer; up_interruptible(&dev->sem); wake_up_interruptible(&dev->inp); return count;}
上一篇:6.拨号计划

下一篇:CodeForces 322D 想法题

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表