linux内核设计与实现 LINUX内核源代码情景分析( 三 )

孤儿进程的处理

  • 父进程如果在子进程之前退出,必须找到新的父亲,否则永远僵死
  • 寻找父亲的函数在do_exit中调用的notify_present函数,内部调用forget_original_parent,该函数实现具体寻找过程
  • 该函数设置父亲为线程组内的其他进程,没有就用init进程
Linux内核相关学习资料点击:正在跳转 获取
imgSpider 采集中…
imgSpider 采集中…
三. 进程调度1. 概述
  • 调度程序是内核组成部分,它负责选择下一个要运行的进程
  • 调度程序负责给可运行进程分配处理器时间资源
  • 多任务系统可分为:抢占式任务(linux等现代操作系统的方式)和非抢占式任务
  • 分配给每个进程的执行时间叫做时间片
2. 调度策略2.1 cpu密集型和IO密集型
  • cpu密集型:大部分时间执行代码
  • IO密集型:大部分时间提交io和等待io,经常可运行,但运行时间极短
  • 从系统响应速度考虑,linux调度策略更倾向于优先调度IO密集型进程
2.2 进程优先级
  • 调度算法中最基本的一类:基于优先级调度,根据进程的价值和其对处理器时间的需求分级的思想
  • 调度程序总是选择时间片未用完且优先级最高的进程运行
  • linux实现了一种基于动态优先级的调度算法 。一开始设置基本优先级,然后根据需要动态加,减优先级:如果一个进程IO等待时间多余运行时间,它属于IO密集型,会提高优先级;相反,如果进程时间片一下就别耗尽,属于cpu密集型,会降低优先级
  • linux提供两组独立的优先级范围: nice值:-20~19,默认为0 。标准优先级范围 。值越大,优先级越低,时间片越短 。task_struct的static_prio字段表示 实时优先级:0~99
2.3 时间片
  • 表明进程在被抢占之前能持续运行的时间
  • 调度策略必须规定默认时间片 。如果过长,交互式的响应表现欠佳;如果过短,会明显增大进程切换带来的处理器耗时
  • 很多系统默认时间片很短:20ms
  • linux提供动态调整优先级和时间片长度的机制,使得调度性能稳定且强健
  • 进程不一定要一次用完时间片,可分多次使用,尽可能长时间保证可运行
2.4 进程抢占
  • 当一个进程处于TASK_RUNNING状态,内核会检查它的优先级是否高于正在运行的进程,满足的话调度程序被唤醒重新选择进程运行
  • 当一个进程的时间片为0,它会被抢占,调度程序可以选择新的进程执行
3. 调度算法3.1 概述
  • linux调度程序定义与kernel/sched.c
  • 2.5版本内核重写调度算法,和以前版本区别很大,实现以下目标 充分实现O(1)调度,不管多少进程或什么输入,每个算法能在恒定时间内完成 每个处理器拥有自己的锁和自己的可执行队列 尽量将同一组任务分配给同一个cpu连续执行,减少在cpu间移动进程 加强交互性能,即使系统负载,也保证系统响应 保证公平 。消除饥饿线程,减少大量时间片进程
3.2 可执行队列
  • 可执行队列数据结构为kernel/sched.c文件下的runqueue
  • 表示给定处理器上的可执行进程链表,每个处理器一个
imgSpider 采集中…
  • 可执行队列是调度程序核心的数据结构,提供很多宏获取该指针 cpu_rq(processor):返回给定处理器可执行队列指针 this_rq:当前处理器可执行队列指针 task_rq:给定任务所在队列指针
  • 对队列进行操作时,需要锁住队列,加锁函数 task_rq_lock task_rq_unlock this_rq_lock this_rq_unlock double_rq_lock double_rq_unlock
3.3 优先级数组
  • 每个可执行队列都有两个优先级数组,一个活跃的和一个过期的
  • 数据结构为kernel/sched.c文件下的prio_array
  • 能提供O(1)级算法复杂度的数据结构
  • 优先级数组使可运行处理器的每一种优先级都包含一个相应的队列,该队列包含该优先级上可执行进程链表
  • 优先级数组还拥有一个优先级位图,帮助高效查询最高优先级可执行进程
imgSpider 采集中…