高级字符驱动之堵塞与非堵塞IO
2017-02-28 19:25
204 查看
/** *此实例涉及到线程的挂起与竞态,字符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; }
相关文章推荐
- Linux设备驱动第六篇:高级字符驱动操作之iotcl
- Linux设备驱动第六篇:高级字符驱动操作之iotcl
- Linux设备驱动第七篇:高级字符驱动操作之阻塞IO
- Linux设备驱动第七篇:高级字符驱动操作之阻塞IO
- 高级字符驱动学习--阻塞型I/0
- 字符设备驱动高级篇6——内核提供的读写寄存器接口
- 高级字符设备驱动-Ioctl设备控制笔记
- 高级字符设备驱动--中断下半部机制之workqueue(二)
- linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】
- 国嵌视频学习——高级字符设备驱动
- linux驱动:[3]高级字符设备驱动之ioctl
- 【Linux 驱动】第六章 高级字符驱动程序操作 ----阻塞型I/O
- linux 高级字符设备驱动 ioctl操作介绍 例程分析实现
- Linux高级字符设备驱动
- 高级字符设备驱动--中断下半部机制之tasklet(一)
- 高级字符设备驱动-Ioctl设备控制笔记
- linux 驱动——高级字符驱动程序操作
- 高级字符设备驱动--中断下半部机制之workqueue(二)
- 黑马程序员学习笔记JAVA高级视频 IO输入输出字符流之Writer类