正常只需将state域的值设为以下两种状态就可进入睡眠状态:
状态 描述TASK_INTERRUPTIBLE 进程处于睡眠状态,正在等待某些事件发生。进程可以被信号中断。接收到信号或被显式的唤醒呼叫唤醒之后,进程将转变为 TASK_RUNNING 状态。
TASK_UNINTERRUPTIBLE 此进程状态类似于 TASK_INTERRUPTIBLE,只是它不会处理信号。中断处于这种状态的进程是不合适的,因为它可能正在完成某些重要的任务。 当它所等待的事件发生时,进程将被显式的唤醒呼叫唤醒。
而在Linux2.6.25以后,新增了一条睡眠状态 : “TASK_KILLABLE”:
状态 描述TASK_KILLABLE 当进程处于这种可以终止的新睡眠状态中,它的运行原理类似于 TASK_UNINTERRUPTIBLE,只不过可以响应致命信号。
由代码的line 31可以看出,TASK_UNINTERRUPTIBLE + TASK_WAKEKILL = TASK_KILLABLE。
1.4.4进程转换图:因此,通过对以上数据的操作,操作系统便可以对进程进行组织和管理。
2.进程是怎么被调度的? 2.1什么是调度器?一台个人电脑,最直观的资源便是你的硬盘、磁盘、内存等等,但其实CPU也是一个资源,每个程序在跑的时候都需要占用CPU一定时间。因此,如何让每个程序合理、公平地跑一定的时间,是一个很重要的问题,需要设计一个专门的地方去分配,这就是调度器。调度器的一个重要目标是有效地分配 CPU 时间片,同时提供很好的用户体验。调度器还需要面对一些互相冲突的目标,例如既要为关键实时任务最小化响应时间, 又要最大限度地提高 CPU 的总体利用率。
2.2进程的分类.当涉及有关调度的问题时, 传统上把进程分类为”I/O受限(I/O-dound)”或”CPU受限(CPU-bound)”.
类型 别称 描述 示例I/O受限型 I/O密集型 频繁的使用I/O设备, 并花费很多时间等待I/O操作的完成 数据库服务器, 文本编辑器
CPU受限型 计算密集型 花费大量CPU时间进行数值计算 图形绘制程序
另外一种分类法把进程区分为三类:
类型 描述 示例交互式进程(interactive process) 此类进程经常与用户进行交互, 因此需要花费很多时间等待键盘和鼠标操作. 当接受了用户的输入后, 进程必须很快被唤醒, 否则用户会感觉系统反应迟钝 shell, 文本编辑程序和图形应用程序
批处理进程(batch process) 此类进程不必与用户交互, 因此经常在后台运行. 因为这样的进程不必很快相应, 因此常受到调度程序的怠慢 程序语言的编译程序, 数据库搜索引擎以及科学计算
实时进程(real-time process) 这些进程由很强的调度需要, 这样的进程绝不会被低优先级的进程阻塞. 并且他们的响应时间要尽可能的短 视频音频应用程序, 机器人控制程序以及从物理传感器上收集数据的程序
2.3调度器的演变.
一开始的调度器是复杂度为O(n)的始调度算法(实际上每次会遍历所有任务,所以复杂度为O(n)), 这个算法的缺点是当内核中有很多任务时,调度器本身就会耗费不少时间,所以,从linux2.5开始引入赫赫有名的O(1)调度器。然而,linux是集全球很多程序员的聪明才智而发展起来的超级内核,没有最好,只有更好,在O(1)调度器风光了没几天就又被另一个更优秀的调度器取代了,它就是CFS调度器(Completely Fair Scheduler). 这个也是在2.6内核中引入的,具体为2.6.23,即从此版本开始,内核使用CFS作为它的默认调度器,O(1)调度器被抛弃了, 其实CFS的发展也是经历了很多阶段,最早期的楼梯算法(SD), 后来逐步对SD算法进行改进出RSDL(Rotating Staircase Deadline Scheduler), 这个算法已经是”完全公平”的雏形了, 直至CFS是最终被内核采纳的调度器, 它从RSDL/SD中吸取了完全公平的思想,不再跟踪进程的睡眠时间,也不再企图区分交互式进程。它将所有的进程都统一对待,这就是公平的含义。CFS的算法和实现都相当简单,众多的测试表明其性能也非常优越。
O(n)的始调度算法 linux-0.11~2.4
O(1)调度器 linux-2.5
CFS调度器 linux-2.6~至今
2.4调度器的设计. Linux的2种调度器: 调度器 描述
主调度器 直接根据进程的状态进行调度,比如当其打算睡眠或出于其他原因放弃占用CPU时
周期调度器 通过周期性的机制, 以固定的频率运行, 不时地去检测是否有必要进行调度
其中这两者统称为通用调度器(generic scheduler)或核心调度器(core scheduler)。