文章目录
- 前言
- 1. 进程状态
- 1.1. 轻量进程排队这件事情——队列
- 1.2. 进程状态的表述及其影响:
- 1.3. 挂起状态及处理:
- 1.4.理解 Linux 内核源代码中的状态表述:
- 2. 进程优先级
- Linux 为什么要调整优先级是要受限的?
- 3. Linux的调度与切换
- 3.1. 进程调度:
- 3.2. 进程切换(并发):
- Linux 实现进程调度和切换的机制主要包括以下几个方面:
- 总结
前言
在计算机操作系统中,进程状态、优先级和调度是非常重要的概念,它们直接影响着系统的性能、资源利用率和响应速度。理解这些概念不仅对于系统管理员和开发人员来说至关重要,对于任何对计算机系统有兴趣的人都是有益的。
本文将深入探讨进程状态的各种表述方式、影响因素以及在 Linux 内核源代码中的具体实现,以及进程优先级的概念及其在 Linux 中的实现方式。我们还将讨论进程调度和切换的原理,以及 Linux 内核是如何通过各种机制来管理和调度进程,确保系统资源的合理利用和进程之间的公平竞争。
1. 进程状态
1.1. 轻量进程排队这件事情——队列
- 进程由
task_struct
和可执行程序组成。 - 进程排队意味着
task_struct
排队,通常是等待某种资源。 - 一个
task_struct
可以被连接到多种数据结构中,底层队列通常使用链表实现,Linux 中记录偏移量。
1.2. 进程状态的表述及其影响:
- 状态本质上是 task_struct 中的一个整型变量。
#define New 1
#define Ready 2
#define runing 3
#define running 3
#define block 3
...
- 状态决定了什么?
状态决定了进程的后续动作,例如任务的调度。
Linux中可能会有很多个进程都要根据它的状态执行后续的动作(进程排队了!)
struct runqueue{
int num;
task_struct *q;
}
- Linux 中的状态包括运行、阻塞、挂起等,由整型变量表示,例如:
运行状态(R):表示进程准备好随时被调度。
阻塞状态(S):表示进程等待软硬件资源,可中断睡眠。
不可中断睡眠(D):表示进程等待硬件资源。
挂起状态(T):暂停进程的执行,让其处于暂停状态,等待其他事件发生。
一个 CPU 一个运行队列, 其中运行状态不仅仅是在CPU上跑,只要是在运行队列里排队的进程都属于运行状态 。
R状态:我以及准备好随时被调度了!
1.3. 挂起状态及处理:
- 挂起状态在计算机资源紧张时发生。
- 阻塞挂起状态是进程等待资源时的一种状态。
- 当进程等待软硬件资源时,如果资源未就绪,进程的
task_struct
可能被置为阻塞状态,并连接到资源提供的等待队列。 - 状态变迁导致
task_struct
被移动到不同的队列中,以便操作系统进行管理。
1.4.理解 Linux 内核源代码中的状态表述:
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面的状态在kernel源代码里定义:
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */ // 运行状态
"S (sleeping)", /* 1 */ // 阻塞状态(可中断睡眠:浅度睡眠)
"D (disk sleep)", /* 2 */ // 不可中断睡眠:深度睡眠
"T (stopped)", /* 4 */ // 让进程处于暂停状态
"t (tracing stop)", /* 8 */ // 被追踪专题
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
- Linux 内核中使用数组定义了进程的不同状态,如运行状态(R)、睡眠状态(S)、不可中断睡眠(D)等。
- 进程状态数组以位图形式表示,可以通过简单的位测试来检测状态组合。
- 例如,Z(zombie)状态表示进程已经退出,但其状态需要保持,以供上层读取,避免内存泄漏。
- 为什么要有Z状态? 创建进程是希望这个进程给用户完成工作的,子进程必须得有结果数据,pcb中的。
- 什么是Z?进程已经退出,但是当进程的状态需要维持住,供上层读取,必须处于Z
- 如果我父亲不读取呢?僵尸状态,会一直存在。task_struct 对象也一直存在,都是要占内存的。内存泄漏!
2. 进程优先级
- 进程优先级是什么?
前提:进程要访问某种资源,进程进行通过一定的方式(排队),确认享受资源的先后顺序。 - 为什么?资源过少!(相对的概念)
- 怎么办?
struct task_struct
{
// 优先级
int PRI;
int nice;
}
在Linux系统中,进程优先级由一个整数表示,范围一般在[60, 99]之间,默认优先级是80。数字越小,优先级越高,进程越有可能先获取系统资源。Linux允许用户调整进程的优先级,但通常不直接修改优先级值(PRI),而是通过调整nice值(nice是进程优先级的修正数据),范围在[-20, 19]之间。负值表示更高的优先级,正值表示更低的优先级。
Linux 为什么要调整优先级是要受限的?
这是因为如果不加限制,有可能出现某些进程将自己的优先级调整得非常高,而其他进程则调整得非常低的情况,从而导致系统资源被不合理地分配。高优先级的进程会优先获取CPU等系统资源,而低优先级的进程可能会长时间无法执行,造成资源饥饿问题。
任何的分时操作系统,在调度上,较为公平的调度。
3. Linux的调度与切换
在 Linux 中,进程调度和切换是操作系统中重要的机制,它们确保了系统资源的合理利用和进程之间的公平竞争。下面是关于进程调度和切换的一些概念:
3.1. 进程调度:
- 系统中的进程数目通常远远多于可用的 CPU 数目,因此进程之间存在竞争关系。为了高效地完成任务,系统通过进程调度算法来决定何时执行哪个进程。
- 进程调度算法通常基于进程的优先级、等待时间、历史运行情况等因素来进行决策,以最大程度地提高系统整体的效率和吞吐量。
概念准备:
- 进程在运行的时候,放在CPU上,直接必须把进程代码跑完,才行吗?不对。现代操作系统都是,基于时间篇进行轮转的。
- 关于竞争性、独立性、并行和并发的概念
- 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有- 竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
- 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
- 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
- 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。
3.2. 进程切换(并发):
- 在多任务操作系统中,多个进程会共享 CPU 资源。当一个进程的时间片用完或者发生阻塞等情况时,操作系统需要切换到另一个进程,以保证系统的响应性和效率。
- 进程切换涉及保存和恢复进程的上下文信息,包括寄存器状态、内存映射、进程状态等。这些信息被保存在操作系统内部数据结构中,以便在需要时进行切换和恢复。
进程在运行过程中产生的临时数据,以及关于硬件上下文的保存和恢复:
- 进程的临时数据:
- 在执行过程中,进程会产生大量的临时数据,例如变量、函数调用栈等。这些临时数据通常存储在内存中的堆栈段或堆段中,以供程序运行时使用。
- 硬件上下文:
- 当一个进程被调度执行时,CPU 需要保存当前进程的硬件上下文,包括寄存器中的数据、程序计数器(PC)等信息。这些信息构成了进程在 CPU 上运行的环境和状态,称为硬件上下文。
- 硬件上下文的保存和恢复:
- 当进程被调度暂停或切换时,CPU 会将当前进程的硬件上下文保存到内存中,以便稍后恢复。而当该进程再次被调度执行时,CPU 会从内存中恢复之前保存的硬件上下文,使得进程可以从上次执行的位置继续执行。
- 区分寄存器和寄存器的内容:
- CPU 内部的寄存器只有一组,它们用于存储当前正在执行的指令、操作数等关键信息。
- 寄存器内部保存的数据可以有多套,每个进程都有自己的一套寄存器数据,被称为进程的上下文信息。虽然这些寄存器都是在共享的 CPU 中,但不同进程的寄存器数据是相互隔离的,每个进程都无法直接访问其他进程的寄存器数据。
Linux 实现进程调度和切换的机制主要包括以下几个方面:
- 使用优先级队列管理进程,以确保高优先级进程优先执行。
- 考虑进程饥饿问题,避免低优先级进程长时间无法执行的情况发生。
- 实现时间片轮转调度算法,确保每个进程都有机会执行,并防止某个进程长时间占用 CPU 资源。
- 使用位图等数据结构记录不同优先级队列的状态,以便高效地选择下一个要执行的进程。
- 在进程切换时,保存和恢复进程的硬件上下文信息,确保进程能够从切换前的状态无缝地继续执行。
swap(&active, &expried);
总结
本文介绍了进程状态、优先级和调度在计算机操作系统中的重要性和原理。通过对进程状态的各种表述方式和影响因素的讨论,我们了解了进程在操作系统中的不同状态及其意义,以及在 Linux 内核源代码中的具体实现方式。进程优先级的概念及其在 Linux 中的实现方式也得到了阐述,包括通过调整 nice 值来调整进程的优先级。最后,我们深入探讨了进程调度和切换的原理,以及 Linux 内核是如何通过各种机制来管理和调度进程,确保系统资源的合理利用和进程之间的公平竞争。
通过对这些关键概念的理解,我们能够更好地管理和优化系统资源的利用,提高系统的性能和响应速度,从而为用户提供更好的计算机体验。