进程控制-进程终止(exit、_exit)
2017-05-18 18:32
253 查看
知道了进程怎么创建,接下来就来看看怎么终止一个进程终止函数exit()和_exit()。
参数作用:可以利用这个参数传递进程退出状态。0表示正常退出,其他情况表示非正常结束。可以用wait接受来自子进程的退出码。在任意
⼀种情况下,该终⽌状态的⽗进程都能使⽤wait或waitpid函数取得其终⽌状态
1. exit()、_exit()
首先,exit()和_exit()都是用来终止进程的。当进程执行exit()或_exit()函数时,系统会立即停止所以操作,清除进程相关的各种数据结构,包括进程PCB,并且终止当前进程的运行。
可以看到,exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。
那么exit()在结束调用它的进程之前都做了什么呢?
exit调用系统调用exit()前先对文件的打开情况进行检查,关闭所有打开的流,这将导致写所有被缓冲的输出,删除用TMPFILE函数建立的所有临时文件。这里的缓冲就是图中的“I/O缓冲”。系统会为每个已经打开的文件,在内存定义一片缓冲区,这样我们每次写入数据都是先写入到缓冲区中,然后满足一定条件后再由缓冲区一次性写入到文件中。这样大大加快了文件读写的速度。
简单的说就是,exit函数将终止调用进程。在退出程序之前,所有文件关闭,缓冲输出内容将刷新定义,并调用所有已刷新的“出口函数”(由atexit定义)。
而_exit同样终止调用进程,但不关闭文件,不清除输出缓存,也不调用出口函数。
所以当文件进行读写操作后,数据有可能在缓冲区,而这时候调用_exit则会将缓冲区的数据丢失,使得出现错误,数据不完整。因此当读写文件操作后,尽量使用exit()终止进程,避免意想不到的错误。
使用实例:
结果:
2. 进程终止的特殊情况
1)子进程终止时,父进程并不正在执行 wait()调用。
2)当子进程尚未终止时,父进程却终止了。
在第一种情况中,要终止的进程就处于一种过渡状态 ,称为 僵死状态(zombie ),处于这种状态的进程不使用任何内核资源,但是要占用内核中的进程处理表那的一项。当其父进程执行wait()等待子进程时,它会进入睡眠状态,然后把这种处于过渡状态的进程从系统内删除,父进程仍将能得到该子进程的结束状态。
第二种情况中,对于⽗进程已经终⽌的所有子进程,他们的⽗进程都改变为init进程。我们称这些子进程由init领养。⼀个init的⼦进程(包括领养进程)终⽌时, init会调⽤⼀个wait函数取得其终⽌状态。
函数 | 头文件 | 声明 |
---|---|---|
exit | stdlib.h | void exit(int status) |
_exit | unistd.h | void _exit(int status) |
⼀种情况下,该终⽌状态的⽗进程都能使⽤wait或waitpid函数取得其终⽌状态
1. exit()、_exit()
首先,exit()和_exit()都是用来终止进程的。当进程执行exit()或_exit()函数时,系统会立即停止所以操作,清除进程相关的各种数据结构,包括进程PCB,并且终止当前进程的运行。
可以看到,exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。
那么exit()在结束调用它的进程之前都做了什么呢?
exit调用系统调用exit()前先对文件的打开情况进行检查,关闭所有打开的流,这将导致写所有被缓冲的输出,删除用TMPFILE函数建立的所有临时文件。这里的缓冲就是图中的“I/O缓冲”。系统会为每个已经打开的文件,在内存定义一片缓冲区,这样我们每次写入数据都是先写入到缓冲区中,然后满足一定条件后再由缓冲区一次性写入到文件中。这样大大加快了文件读写的速度。
简单的说就是,exit函数将终止调用进程。在退出程序之前,所有文件关闭,缓冲输出内容将刷新定义,并调用所有已刷新的“出口函数”(由atexit定义)。
而_exit同样终止调用进程,但不关闭文件,不清除输出缓存,也不调用出口函数。
所以当文件进行读写操作后,数据有可能在缓冲区,而这时候调用_exit则会将缓冲区的数据丢失,使得出现错误,数据不完整。因此当读写文件操作后,尽量使用exit()终止进程,避免意想不到的错误。
使用实例:
#include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <stdlib.h> int g_val = 0; int main() { pid_t id = fork(); if( id < 0 ){ exit(1); } else if( id == 0 ){ printf("clild is run, child pid is : %d\n",getpid()); sleep(1); exit(100); } else{ printf("father is run,father pid is : %d\n",getpid()); } int ret; if( wait(&ret) < 0 ){ printf("wait error, error code is : %d\n", errno); return 1; } printf("wait success, status code is : %d\n",ret); return 0; }
结果:
2. 进程终止的特殊情况
1)子进程终止时,父进程并不正在执行 wait()调用。
2)当子进程尚未终止时,父进程却终止了。
在第一种情况中,要终止的进程就处于一种过渡状态 ,称为 僵死状态(zombie ),处于这种状态的进程不使用任何内核资源,但是要占用内核中的进程处理表那的一项。当其父进程执行wait()等待子进程时,它会进入睡眠状态,然后把这种处于过渡状态的进程从系统内删除,父进程仍将能得到该子进程的结束状态。
第二种情况中,对于⽗进程已经终⽌的所有子进程,他们的⽗进程都改变为init进程。我们称这些子进程由init领养。⼀个init的⼦进程(包括领养进程)终⽌时, init会调⽤⼀个wait函数取得其终⽌状态。
相关文章推荐
- 进程—异常控制流之故障、终止篇
- 进程终止函数:abort, atexit, exit, _exit, _Exit
- APUE笔记---第八章 进程控制(函数fork、exit、wait等)
- 父进程等待子进程终止 wait, WIFEXITED, WEXITSTATUS
- 计算机的异常控制:中断、陷阱、故障、终止、进程上下文切换、信号
- linux进程控制-exit()
- 进程控制(fork和exit)
- 进程控制之exit和waitpid(wait)函数
- 父进程等待子进程终止 wait, WIFEXITED, WEXITSTATUS
- 小何讲进程: 终止进程函数 exit()和_exit()
- 计算机的异常控制:中断、陷阱、故障、终止、进程上下文切换、信号
- 父进程等待子进程终止 wait, WIFEXITED, WEXITSTATUS
- 父进程等待子进程终止 wait, WIFEXITED, WEXITSTATUS
- 进程的开始与终止(exit和_exit区别)
- linux进程控制-exit()
- 第七章 进程控制开发[fork() exec exit _exit wait waitpid 守护进程]
- Unix进程控制之2---exit进程退出函数
- 进程终止函数:abort, atexit, exit, _exit, _Exit http://blog.sina.com.cn/s/blog_605f5b4f0100x3v0.html
- perl进程终止函数die/warn/exit/kill
- 进程控制【创建、等待、终止和替换】