Linux进程阻塞的相关知识
1.如果驱动程序无法立即满足要求,该如何响应?
当数据不可用时,用户可能调用read;或者进程试图写入数据,但因为输出缓冲区已满,设备还未准备好接受数据。调用进程通常不会关心这类问题,程序员只会简单调用read和write,然后等待必要的工作结束后返回调用。因此,在这种情况下,我们的驱动程序应该(默认)阻塞该进程,将其置入休眠状态直到请求可继续。
2.“休眠(sleep)”对进程来讲意味着什么?
当一个进程被置入休眠时,它会被标记为一种特殊状态并从调度器的运行队列中移走。直到某些情况下修改了这个状态,进程才会在任意CPU上调度,也即运行该进程。休眠中的进程会被搁置在一边,等待将来的某个事件发生。对Linux设备驱动程序来讲,让一个进程进入休眠状态很容易。但是,为了将进程以一种安全的方式进入休眠,我们需要牢记两天规则:
1) 永远不要在原子上下文中进入休眠
2) 当我们被唤醒是,我们永远无法知道休眠了多长时间,或者休眠期间都发生了什么事。
等待队列:就是一个进程链表,其中包含了等待某个特定事件的所有进程。在Linux中,一个等待队列通过一个“等待队列头”来管理,等待队列头是一个类型为wait_queue_head_t的结构体。
DECLARE_WAIT_QUEUE_HEAD(name);//静态定义并初始化一个等待队列头
动态方法:
Wait_queue_head_t my_queue;
Init_waitqueue_head(&my_queue);
3.简单休眠
当进程休眠时,它将期待某个条件会在未来成为真。当一个休眠的进程被唤醒时,它必须再次检查它所等待的条件的确为真。Linux内核中最简单的休眠方式是称为wait_event的宏(以及它的几个变种);在实现休眠的同时,它也检查进程等待的条件。
Wait_event(queue,condition);//非中断休眠,通常不用
Wait_event_interruptible(queue,conditon);//常用,可被信号中断
Wait_event_timeout(queue,condition,timeout);
Wait_event_interruptible_timeout(queue,condition,timeout);
其中,queue是等待队列头,condition是一个布尔表达式,上面的宏在休眠前后都要对该表达式求值;在条件为真之前,进程会休眠。
唤醒进程
Voidwake_up(wait_queue_head_t *queue);//会唤醒等待在queue上的所有进程
Voidwake_up_interruptible(wait_queue_head_t *queue);//只会唤醒那些执行可中断休眠的进程。
在实践中,约定做法是在使用wait_event时使用wake_up,而在使用wait_event_interruptible时使用wake_up_interruptible。
举例:任何试图从该设备上读取的进程均被置于休眠。只要某个进程向该设备写入,所有休眠的进程就会被唤醒。
StaticDECLARE_WAIT_QUEUE_HEAN(wq);
Static int flag=0;
Ssize_sleep_read(structfile *filp, char __user *buf,size_t count, loff_t *pos)
{
printk(KERN_DEBUG “process %i (%s) going to sleep\n”,current->pid,current->com);
wait_event_interruptible(wq,flag!=0);
flag=0;
printk(KERN_DEBUG “awaken %i (%s) going to sleep\n”,current->pid,current->com);
return 0;
}
Ssize_sleep_write(structfile *filp, char __user *buf,size_t count, loff_t *pos)
{
printk(KERN_DEBUG “process %i (%s) going to sleep\n”,current->pid,current->com);
flag=1;
wake_up_interruptible(&wq);
return count;
}
注意flag变量的使用,因为wait_event_interruptible要检查改变为真的条件,因此我们使用flag来构造这个条件。
4.阻塞和非阻塞操作
显式地非阻塞I/O由filp->f_flags中的O_NONBLOCK标志决定。如果指定了O_NONBLOCK标志,read和write的行为就会有所不同。如果数据没有就绪时调用read或是在缓冲区没有空间时调用write,则该调用简单的返回-EAGAIN(try it again).例如,在磁带还没有插入时打开一个磁带设备通常会阻塞,如果磁带驱动程序是用O_NONBLOCK打开的,则不管磁带在不在,open都会立即成功返回。
Linux进程阻塞的相关知识的更多相关文章
- Linux 启动流程及相关知识
基础知识 linux系统的组成 内核(kerner) 根文件系统(rootfs) 内核提供操作系统的功能,根文件系统包含常用的一些工具,这些工具.这些工具的运行离不开glibc库文件. 程序:二进制程 ...
- linux进程 阻塞和非阻塞操作
在我们看全功能的 read 和 write 方法的实现之前, 我们触及的最后一点是决定何时使 进程睡眠. 有时实现正确的 unix 语义要求一个操作不阻塞, 即便它不能完全地进行下去. 有时还有调用进 ...
- linux学习笔记-目录相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! linux的目录结构及作用是根据fhs标准定制的,以下列出一些常用的目录的作用,以及fhs官方网站的连接 FHS官方网站的连接: ...
- linux学习笔记-shell-script相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.shell script的执行方法 条件:shell脚本文件必须具备可读可执行权限 1.直接命令执行 (1)使用绝对路径执行 ...
- linux学习笔记-文件相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.文件属性 在当前用户家目录下以ls -al命令输出为例: -rw-r--r-- 1 renren ...
- 面试4——java进程和线程相关知识
1.线程和进程的概念.并行和并发的概念
- Linux 系统及编程相关知识总汇
Linux C function() 参考手册 STL 学习文档 Linux内核
- 好记性不如烂笔头-linux学习笔记4apache相关知识
apache 启动有2种模式 1是prefork模式,每个进程对应一个线程,如果是比较稳定的平台,那么prefork模式是worker模式 比较好,效率高,但是吃的内存比较大. 2 如果是高负载高并发 ...
- linux学习笔记-wget相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! wget是非交互式的网络文件下载工具,这里参考帮助文档,记录下实用参数和使用方法. 一.wget的实用参数: wget: 用法: ...
随机推荐
- java concurrency: ThreadLocal及其实现机制
转载:http://shmilyaw-hotmail-com.iteye.com/blog/1703382 ThreadLocal概念 从字面上来理解ThreadLocal,感觉就是相当于线程本地的. ...
- COM编程-注册DLL形式的COM服务器
这篇文章不涉及任何的有关COM的技术的讲解,仅仅的说一下写好的DLL形式的COM怎么使用.如下图所示,我已经有了一个DLL形式的COM服务器和一个使用COM服务器的COM客户端: 现在这个DLL的CO ...
- YII框架实现排序
YII框架实现排序 用YII2实现批量修改排序功能,如下图 控制器: /** * Lists all CollectionAlbum models. * @return mixed */ public ...
- shell 脚本中$$,$#,$?分别代表什么意思?
$0 这个程式的执行名字$n 这个程式的第n个参数值,n=1..9$* 这个程式的所有参数,此选项参数可超过9个.$# 这个程式的参数个数$$ 这个程式的PID(脚本运行的当前进程ID号)$! 执行上 ...
- linux系统调用和库函数调用的区别(转)
Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).可以参考<Linux程序设计>(英文原版为<Beginning ...
- javascript 检测密码强度
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- mmc一维下料例子
数据来自维基, 长度 = 5600; l切割长度= {1380, 1520, 1560, 1710, 1820, 1880, 1930, 2000, 2050, 2100, 2140, 215 ...
- puppet安装和使用
puppet是一种Linux.Unix.windows平台的集中配置管理系统,使用自有的puppet描写叙述语言,可管理配置 文件.用户.cron任务.软件包.系统服务等.puppet把这些系统实体称 ...
- 队列的定义与实现(C语言实现)
小时候.我们做早操的时候或者军训的时候,都排成一列,有头有尾.如果你迟到了,仅仅能站到最后面一个.退场的时候.都是由第一个先走的.这就是队列雏形. 队列的定义 队列是一种特殊的线性表 队列仅在线性表的 ...
- [转]组合数取模 Lucas定理
对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况.就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 这里用到Lusac定理 ...