Linux内核学习-进程调度二

    计算优先级和时间片:进程拥有一个初始的优先级,叫做nice值,该数值变化范围由-20到+19,默认值为0,19优先级最低,-20最高,他一开始由用户指定后就不能修改,所以称作静态优先级,动态优先级通过一个关于静态优先级和进程交互性的函数关系计算而来,这个函数为effective_prio()函数可以返回一个进程的动态优先级,这个函数以nice值为基础,加上-5到+5之间的进程交互性的奖励或惩罚,得到动态优先级。

      如何判断一个进程的交互性强不强?最明显的标准就是通过进程休眠时间的长短,如果一个进程长时间都在休眠,它就是 I/O消耗型的,若一个进程的执行时间比休眠时间长则是处理器消耗型的。Linux纪录一个用于休眠和用于执行的时间,该值存放在sleep_avg中。它的范围从0到MAX当进程休眠时,该值会增长,当进程每运行一个节拍时,该值会减短。

      重新计算时间片:以静态优先级为基础(nice值)在一个进程创建的时候,新建的子进程和父进程均分父进程剩余的时间片,可以防止用户不断创建进程来截获时间片。优先级最低的进程(+19)为5ms优先级最高的进程(-20)为800ms,默认优先级(0)为100ms。

      休眠和唤醒:休眠的进程处于一个特殊的不可执行的状态,一般进程休眠都是为了等待一些事件,如I/O文件读取更多数据,或某个硬件事件,或获取键盘的输入等,当进程需要休眠时,内核都会把该进程从可执行队列中移除放入等待队列,然后调用Schedule()调用其他进程。唤醒则是把进程从等待队列移到可执行队列。休眠有两种状态:TASK——INTERRUPTIBLE(会接受信号提前唤醒)和TASK _UNINTERRUPTIBLE(会忽略信号)

       负载均衡策略:当处理器之间可执行队列的负载出现不均衡的状态,负载平衡程序会进行合理的调度。由kernel/sched.c中函数load_balance()实现。该函数有两种调用方法(情况)1.在shcedule执行的时候发现当前可执行队列为空,会调用一次。

            2.他会被定时器调用,系统空闲时每隔1ms调用一次,或者在其他情况下每隔200ms被调用一次。

        load_balance()的逻辑:首先找到最繁忙的可执行队列,与当前队列比较,若进程数目多于25%以上,则从该最繁忙的可执行队列中抽取进程到当前队列中来。抽取进程的原则:过期数组-》活动数组-》优先级最高-》满足:没有执行,与处理器无关,不在高速缓存等条件-》抽取

        抢占和上下文切换:(1)上下文切换,就是从一个可执行进程切换到另一个可执行进程,context_switch(),被schedule()调用,完成两项工作:

                                           1.switch_mm()负责把虚拟内存从上一个进程切换到新进程。

                                           2.switch_to()负责从上一个进程的处理器状态切换到新进程的处理器状态。内核通过检查need_resched标志来决定是否调用schedule()。                                        (2)抢占:

                                           1. 用户抢占:内核在即将返回用户空间的时候如果need_resched被设置会导致schedule()被调用,发生抢占,用户抢占发生在系统调用返回用户空间时和从中断处理程序返回用户空间

                                           2.内核抢占:只要重新调度是安全的,也就是只要没有持有锁内核就可以进行抢占。是否持有锁,通过thread_info中的preempt_count计数器来判断,该值为0时没有持有锁。当中断返回内核空间时会检查need_resched和preempt_count,若need_resched被设置,preempt_count为0时说明需要并且可以抢占。内核抢占发生在:(中断处理程序正在执行返回内核空间前),(内核代码再一次具有可抢占性的时候),(如果内核中的任务显示调用schedule),(内核中人物阻塞的时候)

        实时调度策略:两种策略,SCHED_FIFO和SCHED_RR。非实时的策略为SCHED_NORMAL

                                1.SCHED_FIFO先入先出的调度算法,SCHED_FIFO级的进程只要处于可执行状态就会一直执行,优先级低的或者非实时的进程只能等待其执行完才能继续执行,只有具有较高SCHED_FIFO或者SCHED_RR任务才能进行抢占。

                                2. SCHED_RR是带有时间片分配的SCHED_FIFO,需要耗尽它所分配的时间片才会让出处理器。其他与SCHED_FIFO相同。且这两种算法都是依靠静态优先级,内核不会为实时进程计算动态优先级(可以保证实时进程总可以抢占优先级低的进程)

        软实时:内核调度进程,尽力使进程在它的限定时间到来前运行,但内核不保证总能满足这些进程的需求。硬实时则可以满足任何需求,linux提供了一种软实时的工作方式。且实时优先级的范围从0到(MAX_RT_PRIO(默认100)-1),SCHED_NORMAL(非实时,优先级低)共享这一取值空间其nice值-20到+19则对应MAX_RT_PRIO到(MAX_RT_PRIO+40)即100到139.

        一些调度相关的系统调用:1.与调度策略和优先级相关的:设置获取调度策略sched_setscheduler()和sched_getscheduler(),设置获取实时进程的实时优先级sched_setparam()和sched_getparam(),对于普通进程nice()可以将给定的进程的静态优先级增加一个给定的量。

                                            2.与处理器绑定系统调用,sched_setaffinity()和sched_getaffinity()设置和获取位掩码。

                                            3.放弃处理器时间:sched_yield()提供一种进程显式将处理器时间让给其他等待执行进程的机制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章