/**
*此实例涉及到线程的挂起与竞态,字符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;
}

最新文章

  1. servlet(1)
  2. iptables基本操作
  3. 自定义头文件 No such file or directory
  4. listview的tag
  5. bash on windows
  6. javascript 模块化编程 1
  7. yahoo给出的关于网站优化的建议
  8. vue2.0实现分页组件
  9. 一个项目经理对主流项目管理工具的对比:禅道VS华为软件开发云
  10. kubernetes pod infra container网络原理
  11. HPS基本概念及其设计
  12. Flink - InputGate
  13. Advising controllers with the @ControllerAdvice annotation
  14. .NET Core 获取配置文件appsettings.json 方法
  15. Atitit 项目管理 提升开发效率的项目流程方法模型 哑铃型  橄榄型 直板型
  16. javascript生成m位随机数
  17. linux安装mysqlclient报错
  18. 那些ie6已支持的方法属性,成为事实标准。或者方便大家的api
  19. 洛谷P2464 [SDOJ2008]郁闷的小J
  20. spring与quartz整合

热门文章

  1. Python网络爬虫(三)
  2. KVM虚拟机CPU绑定性能调优(宿主机上操作)
  3. [Leetcode]005. Longest Palindromic Substring
  4. sql 时间函数用法
  5. 浅谈堆-Heap(一)
  6. Ubuntu安装LAMP环境(PHP5.6) 以及下载安装phpmyadmin
  7. Servlet高级部分Filter(过滤器)
  8. 洛谷P1397 [NOI2013]矩阵游戏(十进制矩阵快速幂)
  9. 并发访问sqlite数据库出现databse is locked的错误的一个解决办法
  10. UINavigationControlle 之 UINavigationBar及navigationItem关系探讨