2024年4月16日发(作者:)

、Unix进程控制

1、进程的创建与终止

进程是操作系统中活跃着的“生命”,从创建到终止一代又一代,生生不息。UNIX 系统中创建进程的方法是用系统调

用fork()。调用系统调用 fork()的进程是父进程,所创建的新进程为子进程。除进程0 之外,系统中所有的进

程都是系统调用fork()创建的。

系统调用 fork()的实现过程首先是由内核为新进程在进程表中分配一个表项并给新进程一个唯一的进程标识

符PID;然后通过拷贝父进程的进程映象来创建一新进程,新进程将获得其父进程地址空间的一份拷贝;最后增加与

该进程相关联的文件表和索引节点表的引用数并将子进程的进程标志返回给父进程,收到父进程返回信号则标志新进

程创建完毕。

fork()系统调用生成子进程的步骤见图8.2-1,包含如下步骤:

(1)如果系统内存够,则能创建进程;否则调用退出;

(2)为要创建的进程分配一个空闲的进程表项和唯一的进程标识符PID;

(3)如果进程所在的用户其进程数没超过系统限制,则能创建进程;否则调用退出;

(4)设置进程状态为创建,拷贝父进程表项中数据到进程表项中;

(5) 将当前目录的索引节点和改变的根目录的引用数加 1,文件表中打开文件的引用数加1;

(6) 拷贝父进程上下文到进程的上下文;

(7) 如果正在执行的是其父进程则设置进程状态为就绪,否则初始化u 区的计时域。

2、 子进程创建后拷贝其父进程的上下文,并且还可用父进程的当前目录和根目录以及已打开的文件,只是这些的引

用计数要加1。

3、 当父进程创建子进程时希望子进程结束后能把控制返回给父进程,所以子进程不能覆盖父进程给予的控制区。

当进程任务完成后,为了收回进程所占用的系统资源和减少父进程的负担,进程可以用系统调用exit()来实现进程

的自我终止。进程终止可以是正常情况下,也可以在非正常情况下。有如下几个步骤:

(1) 关闭进程的软中断信号;

(2) 如果是与控制终端相连的进程组组长,则向本组进程发出挂起信号。

(3) 关闭所有打开的文件;

(4) 释放进程的上下文、当前目录和改变的根目录;

(5) 记录进程运行时的统计信息;

(6) 进程状态转换为进入僵死状态;

(7) 将自己尚未结束的子进程交给 init 进程,使这些子进程成为init 的合法子进程;

(8) 保留进程表项,通知父进程并等待父进程;

在子进程和父进程的终止关系上系统调用wait()起着非常特

殊的作用。父进程调用wait()的目的是自己要结束。但是面对自

己的子进程,父进程应该怎么做呢?父进程是这样处理自己的子进

程的:

1、 如果父进程调用wait()将自己挂起,而此时自己又无子进程,则调用wait()会返回一出错码;

2、 如果父进程调用wait()将自己挂起,而此时其子进程已进入僵死状态,则调用wait()的结果是收回子进程

的进程表项并将子进程的执行时间加到父进程的执行时间上;

3、 如果父进程调用wait()将自己挂起,而此时其子进程不能

结束,则父进程等待子进程终止,接收子进程的返回状态和返回参数。

另外系统调用 exec()也与进程创建有一定的关系,在系统调用一章中会和系统调用fork、wait、exit 在程序设计

中的应用一起介绍

三、进程调度

进程调度的任务是决定具备执行条件的进程,即处于内存就绪状态的进程,哪个可以获得CPU 的执行权。

由于UNIX 是分时操作系统,用户作业是直接提交到系统内存,除批处理作业之外,在系统中不存在用户作业调度。

所以UNIX 系统中发生最多的是进程调度。

在进程调度中,系统内核给每个进程分配一个CPU 处理的时间片,当时间片到后内核抢占该进程并调度另一进

程。在系统中每个进程都被分配一个优先级。UNIX 进程调度采用的策略是多级反馈循环调度法(Round Robin with

Multiple feedback)。该方法的思想是将处于内存就绪状态的进程按进程优先级排成就绪队列,即就绪队列1,将就

绪队列1 中的进程按优先级调入CPU 中运行,给一个时间片S1,如果该进程运行时间片S1 到时没有完成,则放弃

在CPU 中运行进入就绪队列2;同样,对就绪队列2 中的进程按优先级调度,如果运行时间片S2 到时没有完成,则

进入就绪队列3;以此类推,直到进程完成结束。

需要补充的是:

1、 只有就绪队列1 中的进程全部调度完后才能调度就绪队列2中的进程,同样,只有就绪队列2 中的进程全部调

度完后才能调度就绪队列3 中的进程,依此下去,直至最后的就绪队列;

2、 就绪队列1 的优先权等级最高,时间片最短,就绪队列2 的优先权等级次之,时间片长之;随着就绪队列往下,

优先权逐个下降,时间片逐个增长。一般情况下一个较长的用户进程的执行要经过多次反馈循环调度才能完成。而在

UNIX 系统设计上选取时间片时会尽量将绝大多数Shell 命令执行放在一个时间片内完成。