UNIT 8  Processes and the Scheduler 进程与调度
学习目标
A. CPU cache 与 Service time之间的关系
B. 分析应用程序使用 CPU cache时的情况(CPU使用率与CPU cache命中率)
C. 抢占 (根据优先级抢占)
D 根据进程优先级顺序进行调度与排序
E. 监控内核和进程的性能
 
8.1    Characterizing prosess states 进程状态 
查看进程状态:
ps axo pid,comm,stat –sort=-stat
 
TASK_INTERRUPTIBLE(可中断) :进程正在休眠,在等待某些条件的达成(比如等待I/O请求)。一旦达成某些条件,内核会把进程状态设置为运行。处于此状态的进程也会因为接收到信号而提前被唤醒并投入运行。
TASK_UNINERRUPTIBLE(不可中断) :此状态通常用在进程必须在等待时不受干扰或等待事件很快就会发生时出现,处于此状态的进程对信号不作响应。
TASK_RUNNABLE(运行 ):进程是可执行的,或正在执行,或者在运行队列中等待执行。
TASK_STOPPED(停止 ):进程停止执行或被挂起,进程没有运行也不能运行。
TASK_ZOMBIE(僵死) :进程已经结束了。为了父进程能获知它的消息PID还存在。父进程知道它的结束的消息后就会释放该进程所有资源(包括PID)。
注:每个进程都必然处于五种进程状态中的一种。
 
相关术语:
进程:处于执行期的程序以及它所包含的资源(代码段 ,数据段,址空间,打开的文件,信号,一个或几个线程)的总称
线程:在进程中活动的对象。每个线程都有一个独立的程序计数器及进程栈和一组进程寄存器。

父进程创建一个新的子进程
TASK_ZOMBIE ( 进程被终止 )
TASK_RUNNABLE (准备就绪但未运行)  
TASK_RUNNABLE( 正在运行 )
TASK_INTERRUPTIBLE TASK_UNINTERRPTIBL
      ( 等待 )
E
调度程序根据调度算法将进程投入运行
执行完成后退出 , PID 还在,直到被父进程释放
进程被优先级更高的进程抢占
为了等待特定事件,进程在等待队列上休眠。
等待的事件发生后进程被唤醒并被重新置入运行队列中。
父进程创建完后恢复执行,子进程开始执行。
 
 

父进程创建一个新的子进程

TASK_ZOMBIE (进程被终止)

TASK_RUNNABLE(准备就绪但未运行) 

TASK_RUNNABLE(正在运行)

TASK_INTERRUPTIBLE TASK_UNINTERRPTIBL

      (等待)

E

调度程序根据调度算法将进程投入运行

执行完成后退出,PID还在,直到被父进程释放

进程被优先级更高的进程抢占

为了等待特定事件,进程在等待队列上休眠。

等待的事件发生后进程被唤醒并被重新置入运行队列中。

父进程创建完后恢复执行,子进程开始执行。

 
进程状态转化图
 
8.2  Getting ready to run 程序如何运行
 
A. 程序在开始运行时必须先把数据读入 CPU缓存
Cache-hit (缓存命中率 ):CPU要访问的数据在缓存中的比例。
Cache-miss(缓存丢失率 ): CPU要访问的数据不在缓存中的比例。
    B. 把数据从内存移到缓存
         Cache line fill(缓存填充 ): 当缓存丢失率发生时,把数据从磁盘读到主存,再从内存写到CPU缓存。
C.把数据从缓存移到内存
   Write-through(直写法 ):命中时,不但要把新的内容写入Cache存储器中,必须同时写入主存,使主存与Cache中的内容同时修改,保证主存与副页内容一致。
   Write-back(回写法 ) :未命中时,系统只向主存写入信息,而不必把主存当中的整块内容调入Cache存储器。
D. SMP/NUMA架构下的缓存读写
   Cache snooping (缓存嗅探 )
   多 CPU之间的高速连接.
.
8.3  Types of CPU cache CPU cache 的类型
A. CPU cache类型对 service time 的影响
 术语
地址映象:把主存块映象到 Cache块
地址变换:把主存地址变换为 Cache地址(由于Cache的存储空间较小,因此Cache中的一个存储块要与主存中的若干个存储块相对应,即若干个主存块映象到一个Cache块)
根据不同的地址对应方法,地址映象的方式通常有直接映象( Direct mapped),全相联映象(Fully associative)和组相联映象(Set associative)三种。
     B. 多级缓存 (L1,L2,有的可能有L3)
       L2和 L3经常被多个CPU共享
       缓存有可能只存放指令,或者只放数据,或者两者都存放。
      C.查看缓存信息
        getconf  -a | grep –I cache
        x86info –c
        也可以在 /var/log/dmesg中查看缓存信息。
  
8.4 Locality of reference 寻址
     A. Cache unit stride 缓存单位步长
        应用程序在读取数据时,会按顺序的把数据写入到 Cache里。
        使用 Cache中已加载的数据,可以减少service time。
     B. 从 Cache中读取非循环数据是没有好处的。
        有些处理器指令直接绕过 Cache.
     C. 分析 Cache的使用情况
       valgrind --tool=cachegrind program_name 
参数    --I1
       --D1
       --L2
         Valgrind在使用时程序会运行比较慢。
 
8.5             Improving locality of reference 提高寻址能力
  1. 通过手工优化代码
确定数据结构是否与 Cashe适应
在数据循环工作时:
a.展开循环
b.限制 if循环结构的范围
   B.使用自动化编译选项
       a.通常采用的方式比较保守
b.必须在以下方面采用折衷方式
 编译时间
 运行时间
 代码大小
例 : gcc   -f
-O1 减少代码大小和执行时间
-O2 减少运行时所需空间,提高速度
-O3 增加在线库函数和重置寄存器
 
8.6  Multitasking and the run queue 多进程与运行队列
A.     每个 CPU都有两个运行队列: active 和expired
B.     在以下情况下进程才会被加入活动队列
a.     进程状态必须是 TASK_RUNNABLE
b.     活动队列中的第一个进程被放到 CPU中
队列会根据优先级进行排序
 c.    当前进程会一直运行直到被抢占
       C. 进程被抢占后会被移到过期队列
       D.   当活动队列中没有进程时,活动队列与过期队列会进行切换 (为了重新计算时间片)。
     相关命令 :
      grep  ‘CONFIG.*SMP’ /boot/config-*   查看系统 CPU数
      grep   CONFIG_NR_CPUS /boot/config-* 查看是多少位的系统
 
 
8.7  Preempting the current process 抢占当前进程
A.     标准抢占规则:(在下列情况下进程会被抢占)
a.     CPU收到一个硬中断时
b.     进程在等待 IO请求时
c.     通过调用 sched_yield函数自动放弃CPU时间
d.     调度算法决定进程被抢占
             注:Linux 通过sched_yield()系统调用,提供了一种让显式地将处理器时间让给其它等待执行进程的机制    
      B.查看进程策略和优先级
         Chrt -p pid
          ps axo pid,comm,rtprio,policy
         top
C.      init 进程是从 SCHED_OTHER算法开始的
a.     每个进程在创建时都会继承父进程的调度策略与优先级 .
查看 init进程调度策略与优先级。
Chrt –p `pidof init` 或 chrt -p 1
 
   
8.8 Sorting the run queue 运行队列的排序
A.    每个进程都可以对它进行调度策略和与优先级的调度 .
a.     静态优先级( 1-99):
实时调度策略 ==>SCHED_FIFO 和SCHED_RR
b.     静态优先级 (0)及动态优先级(100-139):
普通调度策略 ==》SCHED_OTHER和SCHED_BATCH
B.    SCHED_FIFO 先入先出
注: 不基于时间片,一旦此级进程处于可执行状态,会一直执行下去,直到它自己被抢占或显式地释放处理器为止。
a.     简单策略:只适用于标准抢占规则
b.     重新排列时永远排在相同优先级队列的最前面。
C.    SCHED_RR
a.     与 SCHED_FIFO大体相同,只是它是基于时间片的。
注:SCHED_RR级进程在耗尽事先分配给它的时间后就不能接着执行下去了。
b.     优先级越高的进程分配到的时间片就越长。
c.     当进程时间片用尽时就会被抢占。
d.     重新排列时会被放到相同优先级队列的最后面 .
D.    SCHED_OTHER         
          a. 进程每次被抢占后,会计算出一个新的优先级值。
         b. 优先级取值范围是从 100到199(对应nice值-20到+19)
 
PS:  
     a. 实时优先级范围是从 0到MAX_RT_PRIO减1,默认情况下MAX_RT_PRIO的值是100,所以默认的实时优先级是0到99,SCHED_OTHERF进程的nice值共享这个取值空间,它的取值范围是从MAX_RT_PRIO到(MAX_RT_PRIO+40).。也就是说,在默认情况下,nice值从-20到+19直接对应的是从100到140。
     b. SCHED_FIFO和 SCHED_RR这两种实时算法实现的是静态优先级,内核不为实时进程计算动态优先级。这能保证给定优先级别的实时进程总能抢占优先级比它低的进程.
    
 
8.9 SCHED_OTHER 调度算法
 A. 在下列情况下优先级会发生变化:
         a.当两个进程有相同优先级时,每 20秒轮循一次,以防CPU    饿死。
         b.当进程此次运行占用过多 CPU时间,当该进程被抢占后,优先级会加5以示处罚。
 B. 交互式任务等待 IO请求时所花时间
         a. 调度算法会跟踪进程等待 IO请求时所花的时间,并计算其出平均休眠时间。 
         b. 较高的平均休眠时间表明进程:
            ( 1)交互式进程会重新插入到活动队列
            ( 2)如果没有,其进程优先级会-5并移到过期队列。
 
 
8.10 Tuning scheduler policy 调度策略
A. SCHED_FIFO
         chrt –f [1-99] /path/to/prog arguments
B.     SCHED_RR
chrt –r [1-99] /path/to/prog arguments
C.     SCHED_OTHER
nice
renice
 
8.11       Viewing CPU performance data 查看CPU性能数据
A.     平均负载:运行队列平均长度
a.     只考虑任务状态在 TASK_RUNNABLE 和TASK_UNINTERRUPTABLE情况下
相关命令:
            sar  -q 1 2
            top
            w
            uptime
B.     CPU 利用率
mpstat 1 2
sar -P ALL 1 2
iostat -c 1 2
cat /proc/stat
 
             用 ps命令查看指定线程的CPU利用率:
                ps -Amo user,pid,tid,psr,pcpu,pri,vsz,rss,stat,time,comm.