一个正在运行的程序需要可以正常的(end())或者异常的(abort())的终止。如果一个系统调用使得当前运行的程序异常的终止,或者如果程序运行出现了问题并导致出现一个错误陷阱,那么会会获取内存转储并生成错误消息。转储被写入到磁盘上的一个特殊日志文件中,可以由debugger【调试器】(一个旨在帮助程序员查找和纠正错误或错误的系统程序)检查,以确定问题的原因。在正常或异常终止进程的情况下,操作系统必须将控制转移到调用的命令解释器。然后命令解释器读取下一个命令。在交互式系统中,命令解释器仅继续执行下一个命令;他会假定用户将会发出一个适当的命令来响应任何错误。在GUI系统中,一个弹出窗口可能会提醒用户错误并请求指导。有些系统可能允许在发生错误时进行特殊的恢复操作。如果程序在其输入中发现错误并希望终止异常,它可能还需要定义一个错误级别。更严重的错误可以用更高级别的错误参数表示。然后,通过将正常终止定义为0级的错误,可以将正常终止和异常终止结合起来。命令解释器或接下来的程序可以使用这个错误级别自动确定下一个动作。

执行一个程序的进程可能希望load()并execute()另一个程序。该特性允许命令解释器按照用户命令或鼠标单击的指示执行程序。一个有趣的问题是在加载程序终止时返回控制权到哪里。而这个问题会迁出处很多问题,比如当前进程是否已丢弃,或者是保存起来,或者是与该新程序并发运行。

we have effectively created a mechanism for one program to call another program.

如果当新进程结束的时候,需要将控制权返回给该进程的话,那么我们必须保存这个程序的内存镜像;因此,我们有效地建立了一个程序调用另一个程序的机制。如果两个程序需要并发运行,我们创建一个多道程序的新进程。通常,有一个系统调用专门用于此目的(create process()))。

如果我们创建一个新进程,或者甚至是一组进程,我们应该能够控制它的执行。该控制要求能够确定和重置进程的属性,包括进程的优先级、其最大允许执行时间,等等(get_process_attributes()和set_process_attributes())。如果我们发现创建的进程是不正确的,或者不再需要它,我们也可能希望终止它(terminal_attributes())。

创建了新进程之后,我们可能需要等待它们完成执行。我们可能希望等待一段指定的的时间(wait_time())。更可能的是,我们希望等待特定事件发生(wait_event())。然后,进程应该在事件发生时发出信号(signal event()))。

通常,两个或多个进程可能共享数据。为了确保共享数据的完整性,操作系统经常提供系统调用,允许进程锁定共享数据。然后,在释放锁之前,没有其他进程可以访问数据。通常,这样的系统调用包括acquire lock()和release lock()这些类型的系统调用,处理并发进程的协调,在第6章和第7章中详细讨论。

进程控制有许多方面和变化,因此我们接下来使用两个示例——一个涉及单任务系统,另一个涉及多任务系统——来阐明这些概念。Arduino是一个简单的硬件平台,它由一个微控制器和输入传感器组成,这些传感器对各种事件做出响应,比如对光线、温度和气压的变化,仅举几个例子。要为Arduino编写程序,我们首先在PC上编写程序,然后通过USB连接将编译好的程序(称为sketch【示意图】)从PC上传到Arduino的闪存上。标准的Arduino平台不提供操作系统;相反,一个称为引导加载程序的小软件将示意图加载到Arduino内存中的特定区域(见图2.9)。一旦草图被加载,它就开始运行,并等待它被编程响应的事件。例如,如果Arduino的温度传感器检测到温度已经超过某个阈值,那么这个草图可能会让Arduino启动风扇的电机。Arduino被认为是一个单任务系统,因为一次只能在内存中有一个草图;如果加载了另一个示意图,它将替换现有示意图。此外,Arduino除了提供硬件输入传感器外,不提供任何用户界面(UI)。

图2-9 (a)系统启动时(b)运行一个示意图

Free BSD(源自Berkeley UNIX)是一个多任务系统的示例。当用户登录到系统时,用户选择的shell将运行,等待用户请求的命令以运行程序。然而,由于Free BSD是一个多任务系统,命令解释器可能在执行另一个程序时继续运行(图2.10)。要启动一个新进程,shell将执行fork()系统调用。然后,通过exec()系统调用将所选程序加载到内存中,并执行该程序。根据命令的发出方式,shell要么等待进程完成,要么在后台运行进程。在后一种情况下,shell将立即等待另一个命令进入。当一个进程在后台运行时,它不能直接从键盘接收输入,因为shell正在使用这个资源。因此,I/O是通过文件或GUI界面完成的。同时,用户可以自由地要求shell运行其他程序,监视运行过程的进度,更改程序的优先级,等等。当进程完成时,它将执行exit()系统调用以终止,返回给调用进程一个为0的状态代码或非0的错误代码。然后shell或其他程序可以使用此状态或错误代码。第3章通过使用fork()和exec()系统调用的程序示例讨论了进程。

图2-10 FreeBSD上运行多个程序

results matching ""

    No results matching ""