fork出来的子进程最好总是用_exit退出
来源:互联网 发布:红警扫矿软件手机 编辑:程序博客网 时间:2024/04/30 04:04
摘要
fork家族函数(fork, vfork)所创建的子进程最好用_exit()
退出,不管是通过 man vfork还是通过看相关网站都能得到这一结论。本文主要介绍一些案例来说明使用 exit()
函数退出进程会引起弊病。
正文
linux下man vfork可以看到这样一句话:
The child must not return from the current function or call exit(), but may call _exit().
下面举几个因使用exit从fork出来的子进程退出而导致各种蛋疼的例子
atexit()掉包返回值
#include <stdio.h> #include <stdlib.h> void end(void) { exit(-1); } int main() { int pid = 0; atexit(end); pid = fork(); if (pid == 0) { exit(0); } else if (pid > 0) { int status = 0; wait(&status); printf("%d\n", status); } return 0; }
大家猜它输出什么?有的同学可能一下子就看出应该输出0,headool曾经也这么相信爱卿。实际上它输出为65280((unsigned char)-1 * 256)。现在headool带你走进科学:
- main函数进来不久,程序用atexit将end设置成收尾函数(headool自创名词, 它在main函数return或exit()之后被调用);
- 接着fork,进程一分为二;
- 父进程 等待的子进程退出。子进程exit()退出后调用收尾函数end(),再次调用exit(-1)( 不会再递归调用end())。
退出码本来是妥妥的0,现在被调包成-1。
这样的exit,能靠谱吗?把它换成_exit
(头文件unistd.h)或_Exit
(头文件 stdlib.h)试试。
不要以为只有C语言有这问题,python有这问题,perl估计也有(这个headool没试过)。 python中解决此问题有对应的os._exit
,perl中有对应的POSIX::_exit
。
伤不起的printf
下面的程序输出什么?
#include <stdio.h>#include <stdlib.h>int main(){ int pid = 0; printf("headool"); pid = fork(); if (pid == 0) { exit(0); } else if (pid > 0) { int status = 0; wait(&status); } return 0;}
和直觉相反,它输出为: headoolheadool(没有回车)
理解上一结果需要知道以下几个unix的事实:
- fork是父子进程间的全拷贝(写时才复制),包括io缓存数据。
- printf所打印的数据会经过行缓冲,只有在遇到\n时才会真正刷到文件(stdout)。
- exit时进程所有文件将关闭,所有缓存数据会因此刷到文件。
明白上一例子到底怎么回事了吧。怎么办?将exit换成_exit!
最后说一个看上去更离奇的例子,它stdout的结果和重定向到文件里的不一样,但exit 换成_exit
后天下又重新太平。
#include <stdio.h>#include <stdlib.h>int main(){ int pid = 0; printf("headool\n");//较上个示例程序仅仅加了一个\n pid = fork(); if (pid == 0) { exit(0); } else if (pid > 0) { int status = 0; wait(&status); } return 0;}
其中的原因以后再细说,查查setvbuf函数吧。 headool提醒你:用fork,记得_exit
。
- fork出来的子进程最好总是用_exit退出
- fork子进程使用_exit而不是用exit函数
- fork子进程使用_exit而不是用exit函数
- 用fork创建进程时,在子进程中 使用getppid 得到的返回值为啥总是1
- 多线程程序中fork容易导致fork出来的子进程中死锁(转载)
- 多线程程序中fork容易导致fork出来的子进程中死锁
- 为何在一个fork的子进程分支中使用_exit函数而不使用exit函数?
- Linux退出进程exit/_exit和等待子进程退出wait函数分析
- 子进程等待父进程退出及fork使用
- linux进程退出的时exit,_exit区别和联系
- 十、Linux系统编程-进程(三)父子进程共享文件、fork和vfork、exit和_exit、atexit注册退出事件
- 进程学习:进程退出_exit()和exit()
- 进程编程—fork,getpid,exit,_exit
- 进程编程—fork,getpid,exit,_exit
- 进程编程—fork,getpid,exit,_exit
- 退出子进程的办法
- 子进程里要用_exit(),请不要用exit()
- 进程,函数退出exit和_exit
- Android Handler机制
- Collision probability of p-stable LSH
- window7+openni的kinect配置
- 谷歌地图为何完胜苹果地图:员工超7000人
- 使用 Apache CXF 实现 Web Service 详解
- fork出来的子进程最好总是用_exit退出
- 2012网赛杭州赛区
- 云风详解网易网络游戏服务器的构架
- 编码常识
- 形参和实参的区别
- short与int型在内存中的存储形式
- 希望大家支持“有深度的程序员面试题”
- 反射(二) 笔记
- makefile的简要分析