文章目录
1 什么是进程
1.1 概念
进程是正在执行的程序。流程与程序代码不同,但远不止于此。与被认为是“被动”实体的程序相比,过程是“主动”实体。进程拥有的属性包括硬件状态,内存,CPU等。
进程存储器分为四个部分,以提高工作效率:
- 文本部分Text section由编译后的程序代码组成,在程序启动时从非易失性存储器中读取。
- 数据部分Data section 由全局变量和静态变量组成,在执行主变量之前进行分配和初始化。
- 堆Heap用于动态内存分配,并通过调用new,delete,malloc,free等进行管理。
- 堆栈Stack用于局部变量。声明局部变量时,将在堆栈上保留空间。
1.2 不同的进程状态
操作系统中的进程可以处于以下任何状态:
- NEW:正在创建过程。
- READY:进程正在等待分配给处理器。
- RUNNING:指令正在执行。
- WAITING:进程正在等待某些事件发生(例如I / O完成或信号接收)。
- TERMINATED:该过程已完成执行。
1.3 进程控制块
每个过程都有一个过程控制块,其中包含有关该过程的所有信息。它是一个数据结构,其中包含以下内容:
- 进程状态:同上。
- 进程ID和父进程ID。
- CPU寄存器和程序计数器。
- 程序计数器保存该进程要执行的下一条指令的地址。
- CPU调度信息:例如优先级信息和指向调度队列的指针。
- 内存管理信息:例如,页表或段表。
- 记帐信息:消耗的用户和内核CPU时间,帐号,限制等。
- I / O状态信息:分配的设备,打开的文件表等。
2 什么是进程的调度
2.1 概念
确定哪个进程处于 ready 就绪状态并应移至 running 运行状态的动作称为“进程计划”。
进程调度系统的主要目的是使CPU始终保持忙碌状态,并为所有程序提供最短的响应时间。为此,调度程序必须为交换CPU的输入和输出应用适当的规则。
调度属于以下两个常规类别之一:
- 非抢占式调度:当前执行的进程自愿放弃CPU时。
- 抢先式调度:当操作系统决定支持其他进程时,清空当前正在执行的进程。
2.2 什么是进程队列
进入系统后,所有进程都存储在作业队列中。
处于“就绪”状态的进程被放置在“就绪队列”中。
等待设备可用的进程位于设备队列中。每个I / O设备都有唯一的设备队列。
首先将一个新进程放入“就绪”队列中。它在就绪队列中等待,直到被选择执行(或调度)为止。一旦将进程分配给CPU并正在执行,就会发生以下几种事件之一:
- 该进程可以发出I / O请求,然后将其放置在I / O队列中。
- 该流程可以创建一个新的子流程并等待其终止。
- 可能由于中断而从CPU强行删除该进程,并将其放回到就绪队列中。
在前两种情况下,该过程最终从等待状态切换到就绪状态,然后将其放回到就绪队列中。一个过程会继续这个循环,直到终止为止,这时将其从所有队列中删除,并重新分配其进程控制块PCB和资源。
2.3 调度程序的类型
可以使用三种类型的调度程序:
- 长期计划者
- 短期计划者
- 中期计划者
让我们详细讨论所有不同类型的调度程序:
长期计划者
长期调度程序的运行频率较低。长期计划程序决定哪个程序必须进入作业队列。从作业队列中,作业处理器选择进程并将其加载到内存中以执行。 Job Scheduler的主要目的是保持良好的多程序程度。
最佳程度的多重编程意味着进程创建的平均速度等于进程从执行内存中的平均离开速度。
短期计划者
这也称为CPU Scheduler,并且运行非常频繁。该调度程序的主要目的是增强CPU性能并提高进程执行率。
中期计划者
该调度程序从内存(和CPU的活动争用)中删除进程,从而降低了多程序化的程度。在以后的某个时间,可以将该过程重新引入内存,并在中断处继续执行。此方案称为交换。该过程被换出,然后由中期调度程序交换:
2.4 进程的操作
2.4.1 进程的创建
通过适当的系统调用(如分叉或生成),进程可能会创建其他进程。创建其他进程的进程,则为另一个进程的父进程,而创建的子进程则将其子进程。
每个进程都得到一个整数标识符,称为进程标识符或 PID。父 PID (PPID) 也存储在每个进程。
在典型的 UNIX 系统上,进程调度程序称为PID 0。它在系统启动时做的第一件事是启动,这给出了这个过程PID1。进一步 Init 启动所有系统守护进程和用户登录名,并成为所有其他进程的最终父级。
子进程可能会收到与父进程共享资源的一些数量,具体取决于系统实现。为了防止失控的子级使用所有特定系统资源,子进程可能或不限于最初分配给父级的资源的子集。
创建子级后,父进程有两个选项:
-
等待子进程终止,然后再继续。父进程对特定子进程或任何特定子进程进行系统调用,这会导致父进程阻塞,直到返回。UNIX 外壳通常等待其子项完成,然后再发出新提示。
-
与子级同时运行,无需等待即可继续处理。当 UNIX shell 作为后台任务运行进程时,这是看到的操作。父级也可以运行一段时间,然后等待子级以后,这可能发生在并行处理操作的排序中。
就新流程的地址空间而言,还有两种可能性:
- 子进程是父进程的重复项。
- 子进程已加载到该进程中。
为了说明这些不同的实现,让我们考虑一下UNIX操作系统。
在UNIX中,每个进程由其进程标识符标识,这是一个唯一的整数。
由分叉系统调用创建新进程。新进程由原始进程的地址空间的副本组成。此机制允许父进程轻松地与其子进程通信。
两个进程(父进程和子进程)在分叉系统调用后继续在指令下执行,但一个区别是:对于new(子进程)进程,分叉系统调用的返回码为零;而子进程(非零)进程的标识符将被返回给父进程。
通常,执行系统调用在两个进程之一的分叉系统调用后使用,以新程序替换进程内存空间。
执行系统调用将二进制文件加载到内存中 - 销毁包含执行系统调用的程序的内存映像 - 并开始执行。以这种方式,这两个进程能够沟通,然后走各自的路。
2.4.2 进程终止
通过进行(系统调用),通常返回一个int,进程可以请求自己终止。
如果int正在执行int,则将其传递给父级,并且在成功完成时通常为零,如果出现任何问题则通常为一些非零代码。
系统也可能出于多种原因终止进程,包括:
- 系统无法传递必要的系统资源。
- 响应KILL命令或其他未处理的过程中断。
- 如果不再需要分配给他们的任务,即父母可以杀死孩子。
- 如果不再需要孩子。如果父级退出,则系统可能会或不允许子级在没有父级的情况下继续运行(在UNIX系统中,孤立进程通常由继承,然后继续杀死它们。)
进程结束时,将释放其所有系统资源,刷新并关闭打开的文件等。
如果父进程正在等待子进程终止,则将进程终止状态和执行时间返回给父进程;如果进程已经成为孤儿,则最终将其返回给init。
试图终止但由于其父级不等待而无法终止的进程称为“僵尸”。这些最终被init作为孤儿继承并杀死。