Linux退出进程exit/_exit和等待子进程退出wait函数分析
2013-04-04 21:31
399 查看
在说明exit和_exit函数之前,先解释下Linux的缓冲I/O操作。所谓“缓冲I/O”就是对于每一个打开的文件,系统都会在内存中开辟一块区域作为其缓冲区,每次读取文件时,将连续的读取N条记录到这个缓冲区中,这样下次再进行读取操作时,将自动的去读取开辟的这段缓冲区,而不是每次都是读取文件。在写文件时,也只是将内容先写入到这段缓冲区中,当满足某个条件(如达到一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入到文件。这样所带来的好处就是大大提高了效率,不必在读取或写入文件时,每次都对文件进程操作,而是只操作内存。弊端就是有时在写入操作时,我们认为已经将内容写入到文件中了,而实际上还只是存在于内存中,如果此时强行退出,必然会导致文件丢失。
exit函数
头文件:#include <stdlib.h>
函数原型:void exit(int status);
参数说明:status=0表示正常退出,status != 0表示异常退出
函数说明:调用该函数结束一个进程。它检查文件的打开情况,把文件缓冲区的内容写回文件。
示例代码:
Use exit to exit
exit can print me
结果分析:printf函数就是使用缓冲I/O的方式,该函数在遇到“\n”换行符时自动的从缓冲区中将记录读出。第二个printf没有用\n说明其没有将数据从缓冲区中读出,此时调用exit函数,将检查缓冲区,发现有数据,所有将数据读出。
_exit函数
头文件:#include <unistd.h>
函数原型:void _exit(int status);
参数说明:status=0表示正常退出,status != 0表示异常退出
函数说明:调用该函数结束一个进程。它不检查文件的打开情况,强行退出进程。
示例代码:
Use _exit to exit
结果分析:调用_exit函数退出进程,不检查缓冲区,所有缓冲区中的数据无法被读出,也就没有打印出_exit can not print me了。
因此为了确保文件操作正常,都使用exit函数。
wait函数
头文件:#include <sys/types.h>
#include<sys/wait.h>
函数原型:pid_t wait (int * status);
函数参数:int *status子进程结束状态值
返回值:执行成功则返回子进程pid,发发生错误,返回-1。错误原因存于errno 中。
函数说明:调用wait()函数的进程会一直阻塞,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。
示例代码:
This is child progress, my pid = 2312
This is parent progress, my child progess pid = 2312, his status = 0
结果分析:父进程会在wait函数那阻塞,直到子进程结束,也就是说,打印This is child progress, my pid = 2312这句之后,大约要过10s才打印This is parent progress, my child progess pid = 2312, his status = 0。
注意点:如果父进程先于子进程退出,这样会产生孤儿进程,这时候子进程是无法退出的,比如下面这段代码就可能会产生这种情况
waitpid函数
头文件:同wait函数
函数原型:pid_t waitpid(pid_t pid,int * status,int options);
参数参数:1)pid_t pid:等待的子进程识别码,可取如下值
pid<-1 等待进程组识别码为pid 绝对值的任何子进程。
pid=-1 等待任何子进程,此时相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid 的子进程。
2)int *status子进程结束状态值
3)int options:可以为0或者如下几个取值的“或”
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0 值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
返回值:同wait函数
函数说明:用于等待任何的进程结束,通过设定不同的参数,等待的方式也将不同
示例代码:
This is child, my pid = 3051
This is parent, my child's pid = 3051
child process exited with status 0
结果分析:父进程会在waitpid函数那阻塞,直到子进程结束。
初学者笔记,有错误请指出,谢谢!
exit函数
头文件:#include <stdlib.h>
函数原型:void exit(int status);
参数说明:status=0表示正常退出,status != 0表示异常退出
函数说明:调用该函数结束一个进程。它检查文件的打开情况,把文件缓冲区的内容写回文件。
示例代码:
#include <stdlib.h> #include <stdio.h> int main(void) { printf("Use exit to exit\n"); printf("exit can print me"); exit(0); return 0; }执行结果:
Use exit to exit
exit can print me
结果分析:printf函数就是使用缓冲I/O的方式,该函数在遇到“\n”换行符时自动的从缓冲区中将记录读出。第二个printf没有用\n说明其没有将数据从缓冲区中读出,此时调用exit函数,将检查缓冲区,发现有数据,所有将数据读出。
_exit函数
头文件:#include <unistd.h>
函数原型:void _exit(int status);
参数说明:status=0表示正常退出,status != 0表示异常退出
函数说明:调用该函数结束一个进程。它不检查文件的打开情况,强行退出进程。
示例代码:
#include <stdlib.h> #include <stdio.h> #include <unistd.h> int main(void) { printf("Use _exit to exit\n"); printf("_exit can not print me"); _exit(0); return 0; }执行结果:
Use _exit to exit
结果分析:调用_exit函数退出进程,不检查缓冲区,所有缓冲区中的数据无法被读出,也就没有打印出_exit can not print me了。
因此为了确保文件操作正常,都使用exit函数。
wait函数
头文件:#include <sys/types.h>
#include<sys/wait.h>
函数原型:pid_t wait (int * status);
函数参数:int *status子进程结束状态值
返回值:执行成功则返回子进程pid,发发生错误,返回-1。错误原因存于errno 中。
函数说明:调用wait()函数的进程会一直阻塞,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。
示例代码:
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(void) { pid_t pid = 0; pid_t ChildPid = 0; int ChildStatus = 0; pid = fork(); if(pid > 0) { ChildPid = wait(&ChildStatus); printf("This is parent progress, my child progess pid = %d, his status = %d\n", ChildPid, ChildStatus); } else { printf("This is child progress, my pid = %d\n", getpid()); sleep(10); exit(0); } return 0; }执行结果:
This is child progress, my pid = 2312
This is parent progress, my child progess pid = 2312, his status = 0
结果分析:父进程会在wait函数那阻塞,直到子进程结束,也就是说,打印This is child progress, my pid = 2312这句之后,大约要过10s才打印This is parent progress, my child progess pid = 2312, his status = 0。
注意点:如果父进程先于子进程退出,这样会产生孤儿进程,这时候子进程是无法退出的,比如下面这段代码就可能会产生这种情况
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { pid_t pid = 0; pid_t ChildPid = 0; int ChildStatus = 0; pid = fork(); if(pid > 0) { printf("This is parent\n"); exit(0); } else { printf("This is child progress, my pid = %d\n", getpid()); exit(0); } return 0; }如果父进程先被执行了,那么父进程退出后,子进程变成了孤儿进程,无法退出,程序会一直卡住。因此一般情况下要求子进程先于父进程退出(在父进程中调用wait函数,或者使用信号),这样就可以防止孤儿进程的产生。
waitpid函数
头文件:同wait函数
函数原型:pid_t waitpid(pid_t pid,int * status,int options);
参数参数:1)pid_t pid:等待的子进程识别码,可取如下值
pid<-1 等待进程组识别码为pid 绝对值的任何子进程。
pid=-1 等待任何子进程,此时相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid 的子进程。
2)int *status子进程结束状态值
3)int options:可以为0或者如下几个取值的“或”
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0 值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
返回值:同wait函数
函数说明:用于等待任何的进程结束,通过设定不同的参数,等待的方式也将不同
示例代码:
#include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main(void) { pid_t pid = 0; int status = 0; pid = fork(); if(pid < 0) { perror("fork()"); exit(1); } else if(pid > 0) { waitpid(pid, &status, 0); printf("This is parent, my child's pid = %d\n", pid); printf("child process exited with status %d \n", status); exit(0); } else { printf("This is child, my pid = %d\n", getpid()); sleep(3); exit(0); } exit(0); }执行结果:
This is child, my pid = 3051
This is parent, my child's pid = 3051
child process exited with status 0
结果分析:父进程会在waitpid函数那阻塞,直到子进程结束。
初学者笔记,有错误请指出,谢谢!
相关文章推荐
- linux下的wait()实现等待一个子进程和所有子进程退出
- linux中父进程退出时如何通知子进程
- Linux 下用vfork()创建进程,子进程用return和exit返回的区别
- linux c 父进程判断子进程退出状态
- linux中父进程退出时如何通知子进程
- linux系统编程之进程(四):进程退出exit,_exit区别即atexit函数
- LINUX退出当前进程——比较return、exit()和_exit()函数
- 子进程等待父进程退出及fork使用
- Linux父进程对于子进程的异步等待
- linux 让父进程等待并检查子进程的退出状态
- linux系统编程之进程(四):进程退出exit,_exit区别即atexit函数(转载)
- linux系统编程之进程(四):进程退出exit,_exit区别即atexit函数
- Linux下父进程异步等待子进程
- linux系统编程之进程(四):进程退出exit,_exit区别即atexit函数
- vb6创建子进程并等待子进程的退出。
- Linux下多线程编程__线程的创建pthread_create与退出pthread_exit,等待当前线程退出pthread_join,获取线程ID pthread_self
- linux 线程等待与退出 pthread_join pthread_exit 函数
- exit--进程退出;wait--进程等待;execl--执行程序
- linux进程退出的时exit,_exit区别和联系
- Linux kernel 3.10内核源码分析--进程退出exit_code