解读Linux系统中的进程调度
Linux中的进程调度技巧使用nice和renice命令进行优先级调整

Linux中的进程调度技巧使用nice和renice命令进行优先级调整在Linux操作系统中,进程调度是一项至关重要的任务。
通过合理地调整进程的优先级,可以实现对系统资源的有效管理和任务的顺利执行。
在Linux中,可以使用nice和renice命令来进行进程的优先级调整。
本文将介绍Linux中的进程调度技巧以及如何使用nice和renice命令进行优先级调整。
一、进程调度技巧的重要性在多任务操作系统中,同时有多个进程运行,各个进程之间需要共享和竞争系统资源。
为了保证系统的稳定性和响应性,操作系统需要合理地分配和调度这些进程。
进程调度策略的好坏直接影响到系统的效率和性能。
在Linux中,进程调度技巧有很多,包括进程优先级的调整、调度策略的设置等。
其中,使用nice和renice命令来进行进程的优先级调整是一种较为常见和方便的方式。
二、nice命令的使用1. 什么是nice命令nice命令是Linux中用来设置进程调度优先级的命令。
通过nice命令可以为某个进程设置一个优先级值,优先级值越低,进程的优先级越高。
2. nice命令的语法nice命令的基本语法如下:nice [OPTION] [COMMAND [ARG]...]其中,OPTION为可选参数,COMMAND为要执行的命令,ARG 为命令的参数。
3. nice命令的实例下面是几个使用nice命令的实例:- 将进程的优先级设置为10:```nice -n 10 command```- 将进程的优先级设置为-10:```nice -n -10 command```- 将进程的优先级设置为默认值:```nice --adjustment 0 command三、renice命令的使用1. 什么是renice命令renice命令是Linux中用来修改已运行进程优先级的命令。
通过renice命令可以为已运行的进程重新设置一个优先级值。
2. renice命令的语法renice命令的基本语法如下:renice [OPTION] [-g|-p|-u] PRIORITY [PID...]其中,OPTION为可选参数,-g、-p、-u用于指定设置优先级的方式(组、进程、用户),PRIORITY为优先级值,PID为进程ID。
理解Linux的进程调度和优先级

理解Linux的进程调度和优先级Linux是一种广泛使用的开源操作系统,它采用了多任务处理的方式,能够同时运行多个进程。
进程调度是Linux操作系统中非常重要的一部分,它决定了进程之间如何共享CPU资源,使得操作系统能够高效地运行。
进程调度是操作系统的核心功能之一,它负责按照一定的调度算法从就绪队列中选择一个进程并将其分配给CPU执行。
Linux操作系统采用了时间片轮转法作为默认的调度算法,即每个进程被分配一个时间片,当时间片用完之后,如果进程还未执行完毕,就会被挂起,将执行机会分配给下一个就绪进程。
这样可以保证多个进程之间的平等性,防止某个进程长时间占用CPU资源。
除了时间片轮转法,Linux操作系统还支持其他的调度算法,如优先级调度、实时调度等。
优先级调度是一种根据进程的优先级来进行调度的方法,优先级高的进程会优先获得CPU执行权。
在Linux中,每个进程都有一个静态优先级和一个动态优先级,静态优先级由进程创建时指定,而动态优先级会根据进程执行情况进行动态调整。
实时调度是一种对实时任务进行优先调度的方法,可以保证实时任务的响应时间。
Linux操作系统中,进程的优先级范围是-20到19,数值越小表示优先级越高。
根据进程的优先级,Linux操作系统按照先运行高优先级进程的原则来进行调度。
当有多个具有相同优先级的进程时,Linux会采用时间片轮转法来进行调度。
通过灵活调整进程的优先级,可以合理分配CPU资源,提高系统的整体性能和响应速度。
除了优先级调度算法外,Linux操作系统还支持实时调度算法。
实时任务对响应时间要求非常高,需要保证任务在规定的时间内完成。
为了实现实时调度,Linux操作系统引入了实时进程和实时调度策略。
实时进程是一类对时间敏感的进程,它们可以获得更高的执行优先级和更快的响应时间。
实时进程的调度策略有FIFO(先进先出)调度、循环调度等。
理解Linux的进程调度和优先级对于系统管理员和开发人员来说非常重要。
请描述linux下常见的调度策略及调度原理

请描述linux下常见的调度策略及调度原理在Linux下,常见的进程调度策略包括:1.CFS(Completely Fair Scheduler)完全公平调度器:CFS是Linux内核默认的调度策略。
它通过使用红黑树数据结构来维护进程队列,以确保公平分配CPU时间片。
CFS基于进程的虚拟运行时间(vruntime)进行调度,根据进程的优先级和历史执行情况来分配CPU时间。
2.实时调度策略:Linux提供了多种实时调度策略,包括先来先服务(FIFO)和轮转(Round Robin)调度策略。
实时任务具有较高的优先级,可以实时响应系统事件,适用于对时间敏感的应用,如嵌入式系统和实时视频处理等。
3.基于优先级的调度策略:Linux还支持基于静态优先级和动态优先级的调度策略。
这些策略根据进程的优先级决定调度顺序,优先级较高的进程将获得更多的CPU时间。
调度原理是指操作系统如何决定哪个进程获得CPU资源的分配。
Linux的调度器使用时间片轮转和优先级调度等策略来实现公平和高效的调度。
调度器会根据不同的调度策略和优先级,分配给每个进程一定的CPU时间片。
时间片指定了进程能够运行的时间段。
当一个进程的时间片用完或发生了阻塞事件时,调度器会将CPU 分配给下一个就绪状态的进程。
CFS调度器基于虚拟运行时间(vruntime)来分配CPU时间。
vruntime表示进程所需的实际运行时间,CFS通过比较进程的vruntime来决定下一个运行的进程。
较长时间没有运行的进程会被赋予更长的时间片,以实现公平调度。
实时调度策略将优先级更高的实时任务放在优先级队列的前面,以确保它们及时地响应系统事件。
在实时任务运行期间,其他普通优先级的任务将被暂时挂起。
总的来说,Linux的调度器通过多种调度策略和优先级,根据不同类型的任务和进程的要求,合理分配CPU资源,以实现公平、高效和响应及时的调度。
这样可以确保系统的正常运转并提高性能。
简述进程调度的主要功能。

简述进程调度的主要功能。
进程调度是操作系统中的一个重要功能,其主要作用是合理地分配和利用系统资源,提高系统的效率和响应速度。
进程调度的目标是使得系统的CPU利用率高、响应时间短、吞吐量大,并且能够保证各个进程按照一定的优先级顺序得到执行。
进程调度的主要功能包括以下几个方面:1. 实现进程的创建和终止:进程调度需要负责管理系统中的各个进程,包括进程的创建和终止。
当一个新的进程被创建时,进程调度会为其分配合适的资源,并将其加入到就绪队列中等待执行。
当一个进程完成任务或者发生异常时,进程调度会将其从执行队列中移除,并释放其占用的资源。
2. 决定进程的执行顺序:进程调度需要根据一定的调度算法决定进程的执行顺序。
常见的调度算法包括先来先服务(FCFS)、短作业优先(SJF)、优先级调度、时间片轮转等。
不同的调度算法有不同的优势和适用场景,可以根据实际情况选择合适的调度算法。
3. 分配CPU时间片:进程调度需要根据系统的运行状态和进程的优先级,合理地分配CPU时间片。
时间片是指每个进程在CPU上执行的时间段,时间片的长度可以根据实际情况进行调整。
较高优先级的进程可以获得更长的时间片,而较低优先级的进程则获得较短的时间片。
4. 处理进程的状态转换:进程调度需要根据进程的状态变化,进行相应的处理。
进程的状态包括就绪状态、运行状态、阻塞状态等。
当一个进程由就绪状态转变为运行状态时,进程调度需要将其从就绪队列中移除,并将其放入执行队列中。
当一个进程由运行状态转变为阻塞状态时,进程调度需要将其从执行队列中移除,并将其放入阻塞队列中等待条件满足后再次调度。
5. 处理进程的优先级调整:进程调度需要根据进程的优先级进行调整。
优先级可以根据进程的重要性、紧急程度、资源需求等因素来确定。
进程调度可以根据实时情况动态地调整进程的优先级,以便更好地满足系统的需求。
进程调度是操作系统中的一个核心功能,对于提高系统的性能和响应能力至关重要。
linux系统中调度的基本单位

linux系统中调度的基本单位一、进程调度进程调度是操作系统中的一个重要组成部分,用于决定在多个进程同时竞争CPU资源时,应该选择哪个进程来执行。
Linux系统中的进程调度采用了时间片轮转调度算法。
时间片轮转调度是一种公平的调度算法,它将CPU的执行时间划分为一个个固定长度的时间片,每个进程在一个时间片内执行一段时间,然后切换到下一个进程。
这样可以保证每个进程都有机会执行,并且避免了长时间占用CPU 的情况。
二、线程调度线程调度是指在多线程应用程序中,操作系统决定哪个线程应该被执行的过程。
Linux系统中的线程调度和进程调度类似,同样采用时间片轮转调度算法。
不同的是,线程是共享同一个进程的资源,因此线程的切换相对于进程的切换来说更加轻量级。
线程调度的目标是尽可能地提高CPU利用率和系统响应速度。
三、任务调度任务调度是指在Linux系统中,操作系统决定何时执行某个任务的过程。
任务可以是周期性的,也可以是非周期性的。
周期性任务是指按照一定的时间间隔重复执行的任务,而非周期性任务则是指只执行一次的任务。
Linux系统中的任务调度使用了多种算法,如最早截止时间优先算法和最短作业优先算法等。
这些算法的目标是根据任务的优先级和执行时间来决定任务的执行顺序,以提高系统的性能和响应速度。
四、总结在Linux系统中,进程调度、线程调度和任务调度是操作系统中的重要组成部分。
进程调度决定在多个进程竞争CPU资源时的执行顺序,线程调度决定在多线程应用程序中哪个线程应该被执行,任务调度决定何时执行某个任务。
这些调度的基本单位都采用了时间片轮转调度算法,并根据不同的调度目标采用不同的调度策略。
通过合理的调度算法,可以提高系统的性能和响应速度,保证各个任务的执行顺序和时间片的分配合理。
linux的任务调度机制

linux的任务调度机制摘要:1.Linux任务调度机制简介2.Linux任务调度器的工作原理3.调度策略和队列4.进程优先级和调度算法5.总结正文:Linux任务调度机制是操作系统中负责分配处理器时间片给各个进程的核心组件。
它依据特定的策略和算法,确保公平、高效地管理进程的执行。
本文将详细介绍Linux任务调度机制的各个方面。
1.Linux任务调度机制简介Linux采用基于优先级的抢占式调度算法,以确保处理器资源得到充分利用。
调度器通过周期性地在就绪队列中选择一个或多个进程,将它们分配给处理器执行。
调度器主要依据进程的优先级和当前的负载情况来决定哪个进程获得处理器资源。
2.Linux任务调度器的工作原理Linux任务调度器的核心组件是调度实体(scheduler entity),它包括进程队列、调度策略和调度算法。
调度实体根据系统的当前状态,按照策略和算法来选择下一个要执行的进程。
调度实体的工作过程分为以下几个步骤:- 进程创建:当一个新进程被创建时,调度器会为其分配一个初始优先级,并将其加入就绪队列。
- 进程执行:调度器从就绪队列中选择一个或多个进程,将它们分配给处理器执行。
执行过程中,进程可能因时间片用完或被阻塞而放弃处理器资源。
- 进程更新:调度器周期性地更新进程的优先级和状态,以反映其当前的执行情况。
- 进程退出:当进程完成执行或被终止时,调度器会将其从进程队列中移除。
3.调度策略和队列Linux调度器支持多种调度策略,如FIFO(先进先出)、SJF(短作业优先)和RR(时间片轮转)。
调度策略决定了进程在队列中的排列顺序,从而影响了调度器选择下一个进程的依据。
Linux中有两个主要的进程队列:就绪队列和运行队列。
就绪队列包含了所有等待处理器资源的进程,而运行队列则存放了当前正在执行的进程。
调度器会根据策略从就绪队列中选择一个或多个进程,将其加入运行队列。
4.进程优先级和调度算法Linux中的进程优先级是一个0-139的整数,优先级数值越低,进程获得处理器资源的机会越高。
linux下常见的调度策略及调度原理

linux下常见的调度策略及调度原理Linux是一种开源的操作系统,广泛应用于服务器和嵌入式设备中。
在Linux系统中,进程调度策略是操作系统的核心组成部分之一,它决定了进程的执行顺序和时间分配。
本文将介绍Linux下常见的调度策略及其调度原理。
在Linux系统中,常见的进程调度策略包括先来先服务(FCFS)、最短作业优先(SJF)、时间片轮转(RR)和优先级调度(Priority Scheduling)等。
先来先服务(FCFS)是一种简单而直观的调度策略,它按照进程到达的先后顺序进行调度。
即当一个进程到达系统时,它将被放入就绪队列的末尾,并等待CPU的分配。
当CPU空闲时,系统将选择就绪队列中的第一个进程分配给CPU执行。
这种调度策略的优点是公平性强,但缺点是无法处理长作业和短作业的差异,容易产生"饥饿"现象。
最短作业优先(SJF)调度策略是根据进程的执行时间来决定优先级的调度策略。
即系统会选择执行时间最短的进程先执行,以减少平均等待时间。
这种调度策略的优点是能够最大程度地减少平均等待时间,但缺点是可能会出现长作业等待时间过长的问题。
时间片轮转(RR)是一种基于时间片的调度策略,每个进程被分配一个固定长度的时间片。
当一个进程的时间片用完时,系统将把CPU分配给下一个进程。
这种调度策略的优点是能够有效地平衡进程之间的响应时间,但缺点是可能会导致频繁的上下文切换。
优先级调度(Priority Scheduling)是一种根据进程优先级来决定调度顺序的策略。
每个进程被分配一个优先级,优先级越高的进程越容易被调度执行。
这种调度策略的优点是能够根据不同进程的需求进行灵活调度,但缺点是可能会导致低优先级进程的"饥饿"问题。
在Linux系统中,调度算法的实现是通过内核的进程调度器来完成的。
内核中的调度器会根据不同的调度策略来选择下一个要执行的进程,并将其上下文切换到CPU中执行。
linux的任务调度机制

linux的任务调度机制(实用版)目录1.Linux 任务调度机制概述2.Linux 任务调度的算法3.进程调度的依据4.调度算法的复杂性5.引入线程机制后的进程管理6.Linux 与 VxWorks 任务调度机制的对比7.总结正文一、Linux 任务调度机制概述Linux 任务调度机制是操作系统中负责分配 CPU 时间片给各个进程的机制。
在 Linux 系统中,任务调度主要通过两个函数实现:周期性调度函数和主调度函数。
这些函数根据现有进程的优先级分配 CPU 时间,因此整个方法称之为优先调度。
二、Linux 任务调度的算法Linux 任务调度的算法有很多,其中最常用的是基于优先级的时间片轮转算法。
这种算法为每个进程分配一个时间片,当时间片用完时,系统会挂起当前进程,并挑选下一个优先级较高的进程来执行。
在实际应用中,进程的优先级会根据其类型、静态优先级、实时优先级等因素进行调整。
三、进程调度的依据进程调度的依据主要包括以下几点:1.进程的类型:实时进程和普通进程。
实时进程具有较高的优先级,优先于普通进程运行。
2.进程的静态优先级:静态优先级是根据进程的类型和特性来设定的,优先级较高的进程更容易获得 CPU 时间片。
3.进程的剩余时间片:每个进程都有一个时间片,当时间片用完时,进程会被挂起。
剩余时间片越多,进程获得 CPU 时间片的可能性越大。
4.进程的I/O和计算负载:进程的I/O负载和计算负载也会影响进程的调度。
I/O负载较重的进程会优先获得CPU时间片,以提高系统的响应速度。
四、调度算法的复杂性调度算法非常复杂,需要综合考虑多个因素。
在实际应用中,操作系统通常采用动态调度算法,根据系统的实时状态和任务需求来调整调度策略。
五、引入线程机制后的进程管理引入线程机制后,进程管理主要负责管理线程之间的数据共享、进程地址空间和交换空间等资源。
线程之间共享资源,而进程则负责资源分配和管理。
六、Linux 与 VxWorks 任务调度机制的对比Linux 和 VxWorks 的任务调度机制有很多不同之处。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
解读Linux系统中的进程调度解读Linux系统中的进程调度有人说,进程调度是操作系统中最为重要的一个部分。
我觉得这种说法说得太绝对了一点,就像很多人动辄就说"某某函数比某某函数效率高XX倍"一样,脱离了实际环境,这些结论是比较片面的。
而进程调度究竟有多重要呢?首先,我们需要明确一点:进程调度是对TASK_RUNNING状态的进程进行调度(参见《linux进程状态浅析》)。
如果进程不可执行(正在睡眠或其他),那么它跟进程调度没多大关系。
所以,如果你的系统负载非常低,盼星星盼月亮才出现一个可执行状态的进程。
那么进程调度也就不会太重要。
哪个进程可执行,就让它执行去,没有什么需要多考虑的。
反之,如果系统负载非常高,时时刻刻都有N多个进程处于可执行状态,等待被调度运行。
那么进程调度程序为了协调这N个进程的执行,必定得做很多工作。
协调得不好,系统的性能就会大打折扣。
这个时候,进程调度就是非常重要的。
尽管我们平常接触的很多计算机(如桌面系统、网络服务器、等)负载都比较低,但是linux作为一个通用操作系统,不能假设系统负载低,必须为应付高负载下的进程调度做精心的设计。
当然,这些设计对于低负载(且没有什么实时性要求)的环境,没多大用。
极端情况下,如果CPU的负载始终保持0或1(永远都只有一个进程或没有进程需要在CPU上运行),那么这些设计基本上都是徒劳的。
优先级现在的操作系统为了协调多个进程的“同时”运行,最基本的手段就是给进程定义优先级。
定义了进程的优先级,如果有多个进程同时处于可执行状态,那么谁优先级高谁就去执行,没有什么好纠结的了。
那么,进程的优先级该如何确定呢?有两种方式:由用户程序指定、由内核的调度程序动态调整。
(下面会说到)linux内核将进程分成两个级别:普通进程和实时进程。
实时进程的优先级都高于普通进程,除此之外,它们的调度策略也有所不同。
实时进程的调度实时,原本的涵义是“给定的操作一定要在确定的时间内完成”。
重点并不在于操作一定要处理得多快,而是时间要可控(在最坏情况下也不能突破给定的时间)。
这样的“实时”称为“硬实时”,多用于很精密的系统之中(比如什么火箭、导弹之类的)。
一般来说,硬实时的系统是相对比较专用的。
像linux这样的通用操作系统显然没法满足这样的要求,中断处理、虚拟内存、等机制的存在给处理时间带来了很大的不确定性。
硬件的cache、磁盘寻道、总线争用、也会带来不确定性。
比如考虑“i++;”这么一句C代码。
绝大多数情况下,它执行得很快。
但是极端情况下还是有这样的可能:1、i的内存空间未分配,CPU触发缺页异常。
而linux在缺页异常的处理代码中试图分配内存时,又可能由于系统内存紧缺而分配失败,导致进程进入睡眠;2、代码执行过程中硬件产生中断,linux进入中断处理程序而搁置当前进程。
而中断处理程序的处理过程中又可能发生新的硬件中断,中断永远嵌套不止……;等等……而像linux这样号称实现了“实时”的通用操作系统,其实只是实现了“软实时”,即尽可能地满足进程的实时需求。
如果一个进程有实时需求(它是一个实时进程),则只要它是可执行状态的,内核就一直让它执行,以尽可能地满足它对CPU的需要,直到它完成所需要做的事情,然后睡眠或退出(变为非可执行状态)。
而如果有多个实时进程都处于可执行状态,则内核会先满足优先级最高的实时进程对CPU的需要,直到它变为非可执行状态。
于是,只要高优先级的实时进程一直处于可执行状态,低优先级的实时进程就一直不能得到CPU;只要一直有实时进程处于可执行状态,普通进程就一直不能得到CPU。
那么,如果多个相同优先级的实时进程都处于可执行状态呢?这时就有两种调度策略可供选择:1、SCHED_FIFO:先进先出。
直到先被执行的进程变为非可执行状态,后来的进程才被调度执行。
在这种策略下,先来的进程可以执行sched_yield系统调用,自愿放弃CPU,以让权给后来的进程;2、SCHED_RR:轮转调度。
内核为实时进程分配时间片,在时间片用完时,让下一个进程使用CPU;强调一下,这两种调度策略以及sched_yield系统调用都仅仅针对于相同优先级的多个实时进程同时处于可执行状态的情况。
在linux下,用户程序可以通过sched_setscheduler系统调用来设置进程的调度策略以及相关调度参数;sched_setparam系统调用则只用于设置调度参数。
这两个系统调用要求用户进程具有设置进程优先级的能力(CAP_SYS_NICE,一般来说需要root权限)(参阅capability相关的文章)。
通过将进程的策略设为SCHED_FIFO或SCHED_RR,使得进程变为实时进程。
而进程的优先级则是通过以上两个系统调用在设置调度参数时指定的。
对于实时进程,内核不会试图调整其优先级。
因为进程实时与否?有多实时?这些问题都是跟用户程序的应用场景相关,只有用户能够回答,内核不能臆断。
综上所述,实时进程的调度是非常简单的。
进程的优先级和调度策略都由用户定死了,内核只需要总是选择优先级最高的实时进程来调度执行即可。
唯一稍微麻烦一点的只是在选择具有相同优先级的实时进程时,要考虑两种调度策略。
普通进程的调度实时进程调度的中心思想是,让处于可执行状态的最高优先级的实时进程尽可能地占有CPU,因为它有实时需求;而普通进程则被认为是没有实时需求的进程,于是调度程序力图让各个处于可执行状态的普通进程和平共处地分享CPU,从而让用户觉得这些进程是同时运行的。
与实时进程相比,普通进程的调度要复杂得多。
内核需要考虑两件麻烦事:一、动态调整进程的优先级按进程的行为特征,可以将进程分为“交互式进程”和“批处理进程”:交互式进程(如桌面程序、服务器、等)主要的任务是与外界交互。
这样的进程应该具有较高的优先级,它们总是睡眠等待外界的输入。
而在输入到来,内核将其唤醒时,它们又应该很快被调度执行,以做出响应。
比如一个桌面程序,如果鼠标点击后半秒种还没反应,用户就会感觉系统“卡”了;批处理进程(如编译程序)主要的任务是做持续的运算,因而它们会持续处于可执行状态。
这样的进程一般不需要高优先级,比如编译程序多运行了几秒种,用户多半不会太在意;如果用户能够明确知道进程应该有怎样的优先级,可以通过nice、setpriority系统调用来对优先级进行设置。
(如果要提高进程的优先级,要求用户进程具有CAP_SYS_NICE能力。
)然而应用程序未必就像桌面程序、编译程序这样典型。
程序的行为可能五花八门,可能一会儿像交互式进程,一会儿又像批处理进程。
以致于用户难以给它设置一个合适的优先级。
再者,即使用户明确知道一个进程是交互式还是批处理,也多半碍于权限或因为偷懒而不去设置进程的优先级。
(你又是否为某个程序设置过优先级呢?)于是,最终,区分交互式进程和批处理进程的重任就落到了内核的调度程序上。
进程的优先级被动态调整后,就出现了两个优先级:1、用户程序设置的优先级(如果未设置,则使用默认值),称为静态优先级。
这是进程优先级的基准,在进程执行的过程中往往是不改变的;2、优先级动态调整后,实际生效的优先级。
这个值是可能时时刻刻都在变化的;二、调度的公平性在支持多进程的系统中,理想情况下,各个进程应该是根据其优先级公平地占有CPU。
而不会出现“谁运气好谁占得多”这样的不可控的情况。
linux实现公平调度基本上是两种思路:1、给处于可执行状态的进程分配时间片(按照优先级),用完时间片的进程被放到“过期队列”中。
等可执行状态的进程都过期了,再重新分配时间片;2、动态调整进程的优先级。
随着进程在CPU上运行,其优先级被不断调低,以便其他优先级较低的进程得到运行机会;后一种方式有更小的调度粒度,并且将“公平性”与“动态调整优先级”两件事情合而为一,大大简化了内核调度程序的代码。
因此,这种方式也成为内核调度程序的新宠。
强调一下,以上两点都是仅针对普通进程的。
而对于实时进程,内核既不能自作多情地去动态调整优先级,也没有什么公平性可言。
普通进程具体的调度算法非常复杂,并且随linux内核版本的演变也在不断更替(不仅仅是简单的调整),所以本文就不继续深入了。
调度程序的效率“优先级”明确了哪个进程应该被调度执行,而调度程序还必须要关心效率问题。
调度程序跟内核中的很多过程一样会频繁被执行,如果效率不济就会浪费很多CPU时间,导致系统性能下降。
在linux2.4时,可执行状态的进程被挂在一个链表中。
每次调度,调度程序需要扫描整个链表,以找出最优的那个进程来运行。
复杂度为O(n);在linux2.6早期,可执行状态的进程被挂在N(N=140)个链表中,每一个链表代表一个优先级,系统中支持多少个优先级就有多少个链表。
每次调度,调度程序只需要从第一个不为空的链表中取出位于链表头的进程即可。
这样就大大提高了调度程序的效率,复杂度为O(1);在linux2.6近期的版本中,可执行状态的进程按照优先级顺序被挂在一个红黑树(可以想象成平衡二叉树)中。
每次调度,调度程序需要从树中找出优先级最高的进程。
复杂度为O(logN)。
那么,为什么从linux2.6早期到近期linux2.6版本,调度程序选择进程时的复杂度反而增加了呢?这是因为,与此同时,调度程序对公平性的`实现从上面提到的第一种思路改变为第二种思路(通过动态调整优先级实现)。
而O(1)的算法是基于一组数目不大的链表来实现的,按我的理解,这使得优先级的取值范围很小(区分度很低),不能满足公平性的需求。
而使用红黑树则对优先级的取值没有限制(可以用32位、64位、或更多位来表示优先级的值),并且O(logN)的复杂度也还是很高效的。
调度触发的时机调度的触发主要有如下几种情况:1、当前进程(正在CPU上运行的进程)状态变为非可执行状态。
进程执行系统调用主动变为非可执行状态。
比如执行nanosleep 进入睡眠、执行exit退出、等等;进程请求的资源得不到满足而被迫进入睡眠状态。
比如执行read系统调用时,磁盘高速缓存里没有所需要的数据,从而睡眠等待磁盘IO;进程响应信号而变为非可执行状态。
比如响应SIGSTOP进入暂停状态、响应SIGKILL退出、等等;2、抢占。
进程运行时,非预期地被剥夺CPU的使用权。
这又分两种情况:进程用完了时间片、或出现了优先级更高的进程。
优先级更高的进程受正在CPU上运行的进程的影响而被唤醒。
如发送信号主动唤醒,或因为释放互斥对象(如释放锁)而被唤醒;内核在响应时钟中断的过程中,发现当前进程的时间片用完;内核在响应中断的过程中,发现优先级更高的进程所等待的外部资源的变为可用,从而将其唤醒。
比如CPU收到网卡中断,内核处理该中断,发现某个socket可读,于是唤醒正在等待读这个socket的进程;再比如内核在处理时钟中断的过程中,触发了定时器,从而唤醒对应的正在nanosleep系统调用中睡眠的进程。