在linux 中, 使用多进程时,大家都知道, 子进程和父进程的结束顺序不同, 会出现不同的情况, 如下:
1. 当父进程比子进程先结束时, 子进程会自动依托于跟进程(init进程)管理, 这时子进程叫做"孤儿进程", 程序没有任何问题.
孤儿进程: 是完善的进程, 无任何危害的.
2. 当子进程比父进程先结束时, 子进程就会成为 Z 进程(僵尸进程).
僵尸进程: 不占用内存和CPU, 但是会占用进程任务管理树上的一个节点(这个节点很重要, 如一些CPU中允许创建固定数量进程, 占用一个就会少一个 了),
这时应该如何去回收这个僵尸进程呢? linux 提供了wait()函数数据去回收僵尸进程, 使用signal()函数来接收子进程返回的信号量(子进程结束时发出的信号量为17).
如下代码:
#include
#include
#include
void sigfun(int sig)
{
int status;
printf("%s[%d]:recv sig = %d\n", __FUNCTION__, __LINE__, sig);
wait(&status); // 回收子进程
printf("%s[%d]:status = %d\n", __FUNCTION__, __LINE__, WEXITSTATUS(status));
}
int main()
{
if (fork()) // 父进程
{
signal(17, sigfun); // 注册信号量接收, 当接收到17的信号量时会执行sigfun函数
printf("parent process doing while(1)\n");
while(1);
}
else // 子进程
{
printf("child process doing sleep(5)\n");
sleep(5);
printf("child process exit(10)\n");
exit(10);
}
return 0;
}
如两个有关系的进程A 和B , 当B 执行到进一个特别的地方时, 就发送一个固定的信号给A, A再做出现应的处理.
再如, 与数据库/php程序交互时, 你的程序不知道什么时候数据库什么时候有更新, 也不知道什么时候去取数据库, 如果是定时1分钟去取数据库, 可能会一次取到很多数据, 但更多的时候可能是什么也取不到. 这时就可以使用signal函数,来接收数据库/PHP传过来的固定信号量, 当收到信号时再去取数据库, 这样就方便很多很多.
如下代码, 是一个测试程序来接收用户对其进行发送的信号量, 程序中测试了50-54 这5个信号量, 当在终端中, 使用killall 进程名 -n (n 为信号量) 对进程发送信号量
#include
#include
#include
void sigfun(int sig)
{
int status;
printf("%s[%d]:recv sig = %d\n", __FUNCTION__, __LINE__, sig);
}
int main()
{
signal(50, sigfun); // 注册信号量接收, 当接收到17的信号量时会执行sigfun函数
signal(51, sigfun);
signal(52, sigfun);
signal(53, sigfun);
signal(54, sigfun);
// TODO: do something
while(1); // 使程序不退出
return 0;
}