在一次考试中指出:
给出进程正常终止的两种不同方式。描述差异。
是什么意思正常终止?
答案1
在此上下文中使用的术语“通常”通常意味着正在执行的进程在成功完成其所有指令时退出,而不会被信号杀死或意外崩溃。例如:Ctrl+C
在命令find
运行且find
进程接收到SIGINT
信号时被命中。处理此信号是特定于实现的,但这通常意味着正常终止进程。程序的正常终止发生在从程序中最后执行的语句的C
函数成功返回时。main
这与例如未完成所有指令并以非确定性方式退出的进程形成对比。这可能是由程序错误引起的,也可能是由其他进程发出杀死它的信号引起的。异常终止通常是在程序中实现的逻辑中确定的,例如子进程中止/退出到父进程并带有某个返回值x
,表明执行中的某些状态或事件不“正常”。例如:一个进程接收到SIGKILL
信号。该信号无法被处理并终止进程。
这里,进程抽象类似于编程函数,因为它们都共享向调用进程(例如 shell)返回值的能力。这些返回值的语义定义了“成功”或“不成功”调用的条件。因此,在这种情况下,程序员负责定义或使用这些语义。
举一个具体的例子:执行的命令bash
最终将在终止时向其调用者返回一个值。这里,除了任何值都0
表示命令异常终止。您bash
可以检查变量$?
以查看最后执行的语句的返回值。当控制脚本中的执行流程时,使用此返回值非常有用,例如防止读取不存在的文件等。
在谈论终止进程时,还需要考虑其他事情,例如释放分配的地址空间以及内存中的相关资源,以及作业的 cpu 调度,但那是另一章了。
答案2
我不确定现在学校教什么,但我猜正常终止意思是“以 0(零)状态退出”。
我可以想到 3 种方法来做到这一点(至少在 C 程序中):
return 0; /* 1 */
exit(0); /* 2 */
_exit(0); /* 3 */
我认为(1)和(2)几乎是等价的,但是(3)导致进程退出而不刷新其输出缓冲区。在 fork/exec 情况下,您可以使用它来避免子进程退出之前缓冲的任何字节(通过内核或 stdio)的双重输出。