是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位。线程作为进程的细分,是系统任务调度的最小单位。
三种基本状态。运行-就绪-阻塞。Linux中还分的更细,有挂起态、僵死态等,不过总体还是能归为基础三态。
普通进程:用户的可以创建额进程,采用动态优先级来调度,周期性修改优先级;
实时进程:用户不能创建,由内核创建的进程,优先级预先指定不会改变。
有的调度器开启了抢占,有的禁用了抢占。抢占就是指进程运行时,剥夺了其CPU使用权。出现抢占的两种情况:时间片用完了或出现了优先级更高的进程。内核抢占,理想情况只要出现优先级更高的进程就会立即抢占cpu,但实际上内核中有很多临界区,不可能随时随地抢占。
为了在计算机中更好的描述进程,一个进程不仅仅包含了程序运行的信息,还有一个PCB头部,包含了进程的基本信息和用于调度的信息。Linux中的进程PCB结构体称为task_struct。该结构主要元素如下:
pid:进程的唯一标识,id号;
state:进程的状态,指示进程是在运行还是阻塞等;
policy:调度策略,主要有5种;
rt_priority:用于保存实时优先级;
static_prio:用于保存静态优先级,与nice值相关,系统提供了修改nice的接口,因此可以修改;
normal_prio:用于统一静态优先级和实时优先级;
prio:用于保存动态优先级;
nice:进程的基本时间片,用于修改静态优先级;
还有很多其他的信息,如时间数据,用于记录生存周期;进程通信有关信息,关于锁和能收到什么信号等;进程关系信息,父子关系记录;地址内存信息,上下文信息,进程队列指针信息等等,可以找到该结构体源码阅读一下。
linux中的优先级用数字分成140档,分别是0-130,数字越小,代表优先级越高。其中0-99分给实时进程使用,100-139分给普通进程使用。进程PCB中定义了一个常量MAX_RT_PRIO=100。
Linux的v2.4以前,可执行进程挂在一个链表里,每次调度,扫描链表找出优先级最高的,复杂度为O(n),发展成多处理器机器后,效率变得很低。
v2.5作了改进,可执行程序挂在N(N=140)个链表中,每个链表代表一个优先级,调度从第一个不为空的链表中取进程,复杂度为O(1),但是实际在交互进程中响应时间较差。
v2.6及以后作了改进,改为现在一直沿用的调度策略。即经典的CFS完全公平调度。
Linux对于普通进程和实时进程采用不同的调度策略。
普通进程策略:
§ SCHED_NORMAL:有的地方又为OTHER,用于普通进程,是标准的分时调度策略。
§ SCHED_BATCH:类似OTHER,但调度器会假设线程是CPU密集型的。
§ SCHED_IDLE:nice值不会影响改策略,用于运行优先级最低的任务
实时进程策略:
§ SCHED_FIFO:先进先出调度,不使用时间片进行调度,如果没有优先级更高的进程,它会一直运行完毕。
§ SCHED_RR:轮询调度,和FIFO一样,只是加了时间片,优先级不改变的情况下,进程固定时间片轮流运行。
§ SCHED_DEADLINE:针对突发性计算,且对延迟和完成时间高度敏感的任务。
调度器就是根据不同的调度策略调度算法,具体实现的一种类。linux提供了5种调度器。Stop调度器、Deadline调度器、RT调度器、CFS调度器、IDLE-Task调度器等。根据task_struct的不同调度策略,内核会选择不同的调度器。下面简单介绍CFS调度器。
CFS调度器就是完全公平调度,是Linux从2.6版本沿用至今的调度器。其采用的是时间片调度,CFS通过虚拟时间来实现平衡,每个进程拥有一个虚拟时间,用于记录该进程运行了多久。每次调度该进程,用完一个时间片就增加它的虚拟时间变量。而每次调度的时候,挑出虚拟时间最小的进程来执行。新的进程虚拟时间设置为内存中进程最小的虚拟时间,以便让它能尽快运行。CFS让每个进程都能有运行机会,相对公平。
原文:https://www.cnblogs.com/cpcpp/p/13377145.html