APUE学习笔记(7)-僵死进程
来源:互联网 发布:网络直播低俗 编辑:程序博客网 时间:2024/05/27 00:48
写在前面
1. 本文内容对应《UNIX环境高级编程》(第2版)》第8章。
2. 总结了进程终止方式和僵死进程的概念,以及使用wait函数获取子进程的终止状态。
3. 希望本文对您有所帮助,也欢迎您给我提意见和建议。
进程终止方式
进程有5种正常终止方式:
l 在main函数内执行return语句。
l 调用exit函数。此函数由ISO C定义,其操作包括调用各终止处理程序(用atexit函数注册),然后关闭所有标准IO流等。
l 调用_exit或_Exit函数,并不运行终止处理程序和信号处理程序。
l 进程的最后一个线程在其启动例程中执行返回语句。但是,该线程的返回值不会用作进程的返回值,进程以终止状态0返回。
l 进程的最后一个线程调用pthread_exit函数,进程终止状态总是0。
以及3种异常终止方式:
l 调用abort函数,产生SIGABRT信号。
l 接收一个信号并终止。
l 最后一个线程对取消请求做出响应。
僵死进程
一个已经终止,但是其父进程尚未对其进行善后处理(即获取终止子进程的有关信息,释放它仍占用的资源)的进程被称为僵死进程(zombie)。内核为每个终止子进程保存了一定量的信息,这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间总量,所以当终止进程的父进程调用wait或waitpid时(也就是大家常说的收尸或是超度),可以得到这些信息。同时,内核释放终止进程所使用的所有存储区,关闭其所有打开文件,僵死进程不可能再借尸还魂。
如果父进程在子进程之前终止,那么子进程将得不到超度,永远残留在内存中(参考仙剑3的龙葵姑娘)。为了避免发生这样的悲剧,所有这些子进程将由init进程(ID为1,在自举结束时由内核调用)领养。其过程大致如下:在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正要终止进程的子进程,如果是,则将该进程的父进程ID更改为1。无论何时,只要有一个子进程终止,init进程就会调用一个wait函数取其终止状态,从而防止了在系统中存在很多僵死进程。
如果一个进程fork一个子进程,但不要它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的技巧是调用fork两次。让原先的子进程成为孙子进程,并让其父进程英年早逝,从而交由init进程领养。其祖父进程则不再负责孙子进程的超度工作。
wait
父进程调用wait完成子进程的超度。如果所有子进程都还在运行,则wait阻塞。如果任意一个子进程终止,正等待父进程获取其终止状态,则取得该子进程的终止状态,并返回该子进程ID。如果没有任何子进程,则wait立即出错返回。与wait不同,waitpid可等待一个指定的进程,提供一个非阻塞版本,并且支持资源控制。wait得到的子进程终止状态可由WIFEXITED宏测试是否为正常终止,或由WIFSIGNALED宏测试是否为异常终止。正常终止时,可用WEXITSTATUS宏获取传递给exit参数的低8位。异常终止时,可由WTERMSIG宏获取使子进程终止的信号编号。
实验程序如下:
int main()
{
pid_t pid;
int stat;
printf("parent pid=%d/n", getpid());
if((pid = fork()) < 0)
{
printf("fork first child error./n");
exit(1);
}
else if(pid == 0)
{
if((pid = fork()) < 0)
{
printf("fork second child error./n");
exit(1);
}
else if(pid > 0)
{
printf("first child pid=%d ppid=%d/n", getpid(), getppid());
abort();
}
sleep(1);
printf("second child pid=%d ppid=%d/n", getpid(), getppid());
exit(0);
}
sleep(2);
if(waitpid(pid, &stat, 0) != pid)
{
printf("wait first child error./n");
exit(1);
}
if(WIFEXITED(stat))
{
printf("wait %d success: normal termination, exit status=%d/n",
pid, WEXITSTATUS(stat));
}
else if(WIFSIGNALED(stat))
{
printf("wait %d success: abnormal termination, signal number=%d/n",
pid, WTERMSIG(stat));
}
exit(0);
}
运行结果为:
pydeng@pydeng-laptop:~/apue.2e/mytest$ ./a.out
parent pid=6262
first child pid=6263 ppid=6262
second child pid=6264 ppid=1
wait 6263 success: abnormal termination, signal number=6
- APUE学习笔记(7)-僵死进程
- APUE学习笔记:第七章 进程环境
- APUE学习笔记:第八章 进程控制
- APUE学习笔记(6)-创建进程
- APUE学习笔记(9)-进程关系
- APUE学习笔记——进程环境
- APUE学习笔记——进程控制
- APUE学习笔记(19)-守护进程
- APUE 第八章《进程控制》学习笔记
- apue 8-5调用fork两次以避免僵死进程
- APUE 笔记 守护进程
- APUE学习--Ch.7 进程环境
- APUE学习(三):进程
- APUE学习:进程环境
- APUE学习:进程控制
- 僵死进程
- 僵死进程
- 僵死进程
- P2P - JXTA 介绍
- 科技论文的英文表达-----如何写好科技论文之我见(六)
- APUE学习笔记(5)-设置用户ID
- 迷路了
- APUE学习笔记(6)-创建进程
- APUE学习笔记(7)-僵死进程
- P2P技术体系结构与分类
- P2P安全问题
- NBA常规赛明天打响 决定欧美文化命运的战斗正式打响
- APUE学习笔记(8)-执行程序
- APUE学习笔记(9)-进程关系
- 简单事件驱动 (控制台程序)
- 中国企业飞鸽传书市场
- 又见不和谐之Live Mail