/首页
/开源
/关于
困难人生之CLang的wait以及waitpid
发表@2018-11-26 00:07:23
更新@2023-01-21 22:47:40
我们用一种严肃的口吻和语言来描述关于进程的善后工作 . 妈进程在有了子进程后 , 一般有两种结局 : - 妈进程退出了 , 子进程都还在 , 这会儿子进程都变成了孤儿进程 . 孤儿进程会直接进" 孤儿院 " , 也就是被\*UNIX init进程收养 . 有很多子进程都是这样的 . - 子进程退出了 , 但是妈进程不管 , 这种情况就比较严重了 . 这种可怜的子进程都是横尸街头没人管 , 时间长了就是僵尸进程 . 我们看下下面这坨代码 : ``` #include
#include
#inlucde
#include
int main( int argc, char * argv[] ) { pid_t pid; int i; for ( i = 1; i <= 5; i++ ) { pid = fork(); if ( 0 == pid ) { // 每个子进程都休息十秒钟 sleep( 10 ); exit( -1 ); } } // 妈进程长期保持不退出 sleep( 1111111 ); return 0; } ``` 我们将上述代码保存编译 , 然后运行 . 我们是要用ps -ef | grep a.out来观察子进程在十秒钟生命周期内的状态 , 然后我们再看看过了十秒钟生命周期后的进程状态 . ![](https://ti-node.com/static/upload/6472478418976899073) 两次执行ps -ef | grep a.out有两种不同的结果 , 第二次进程后面多了一个defunct的关键字 , 这就是僵尸进程 . 娘不管孩子了 ... ... 所以得管 , 用什么管 ? i一般说来 , 有两个方法 : wait和waitpid . wait函数的参数是一个整数类型的指针 , 返回的是被回收的子进程的进程ID . 一定要注意 : - 如果妈进程生出的所有子进程都在运行未推出 , 那么wait将会阻塞妈进程 - 如果有子进程退出了 , 那么该函数就会立马返回被回收的子进程的id 然后是这个进程退出的状态会被保存到wait唯一的参数 , 既那个status整形的指针中 . ``` #include
#include
#include
#include
#define true 1 #define false 0 int main( int argc, char * argv[] ) { pid_t pid; int i; int status; for ( i = 1; i <= 5; i++ ) { pid = fork(); if ( 0 == pid ) { sleep( 10 ); exit( -1 ); } } while ( true ) { sleep( 1 ); wait( &status ); } return 0; } ``` 将上面代码保存编译后运行 , 我就不截图了 , 总之那些defunct状态的子进程都会被一一回收掉 . 不过值得注意的是 , CLang中并没有布尔类型变量 , 布尔变量本质上就是int类型 , 所以一般说来我们在CLang中使用define true 1和define false 0来解决布尔变量即可 . waitpid是比wait更加高级的一个回收方式 , waitpid的原型如下 : - waitpid( pid_t pid, int * status, int option ) 其中 , 第一个参数有如下几种情况 : - 如果为-1 , 表示回收任何进程ID的子进程 - 如果为大于0 , 只回收与该pid相同的子进程 , 其余一律不回收 - 如果为0 , 表示要回收与调用进程进程组相同的i进程 - 如果为小于-1 , 等待组id等于pid绝对值的任意子进程 其中 , 最后一个参数有如下几种情况 : - WCONTINUED , 不好意思 , 反正我没搞明白 - WNOHANG , 这个明白 , 这个可以使waitpid变为非阻塞 , 这点与wait调用后就会阻塞是非常地不同 ! - WUNTRACED , 不好意思 , 这个是迷迷糊糊 ``` #include
#include
#include
#include
#define true 1 #define false 0 int main( int argc, char * argv[] ) { pid_t pid; int i; int status; for ( i = 1; i <= 5; i++ ) { pid = fork(); if ( 0 == pid ) { sleep( 10 ); exit( -1 ); } } while ( true ) { sleep( 1 ); pid = waitpid( -1, &status, WNOHANG ); printf( "%d\n", pid ); } return 0; } ```