fork()函数的执行过程、孤儿进程和僵尸进程
说起fork就不得不提COW(Copy On Write),就是“写时拷贝”。也就是当fork发生时,子进程根本不会去拷贝父进程的内存页面,而是与父进程共享。当子进程或父进程需要修改一个内存页面时,Linux就将这个内存页面复制一份给修改者,然后再去修改,这样从用户的角度看,父子进程根本就没有共享什么内存。COW也就是进程要写共享的内存页面,先复制再改写。
采用了COW技术后,fork时,子进程还需要拷贝父进程的页面表。这种拷贝的代价就非常小了,对于CPU来说用不了几个时钟周期。
1.孤儿进程
孤儿进程:就是没有父进程的进程。一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
2.僵尸进程
僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。
3.危害
僵尸进程会占用系统资源,如果很多,则会严重影响服务器的性能
孤儿进程不会占用系统资源,最终是由init进程托管,由init进程来释放它。
处理流程:
只要老爹不等wait(sys/wait.h)儿子,儿子都将成为孤魂野鬼zombie(zombie),unix中默认老爹总是想看儿子死后的状态(以便报仇)
if 老爹比儿子先再见
儿子将被init(id = 1)收养,最后的结果是zombie儿子彻底再见,系统资源释放
else
{
儿子的zombie将一直存在,系统资源占用...
if 老爹dead
儿子将被init(id = 1)收养,最后的结果是zombie儿子彻底再见,系统资源释放
else 类似的儿子zombie越来越多,系统就等死了!!!
}
signal(SIGCHLD, SIG_IGN); //忽略SIGCHLD信号,这常用于并发服务器的性能的一个技巧
//因为并发服务器常常fork很多子进程,子进程终结之后需要
//服务器进程去wait清理资源。如果将此信号的处理方式设为
//忽略,可让内核把僵尸子进程转交给init进程去处理,省去了
//大量僵尸进程占用系统资源。(Linux Only)
4.如何防止僵尸进程
首先明白如何产生僵尸进程:
1、子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它
2、父进程没有调用wait()或waitpid()函数来等待子进程的结束
第一种方法: 捕捉SIGCHLD信号,并在信号处理函数里面调用wait函数
转贴Richard Steven的Unix Network Programming代码
int
main(int argc, char **argv)
{
...
Signal(SIGCHLD, sig_chld);
for(;
}
...
}
void
sig_chld(int signo)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) >; 0)
printf("child %d terminated/n", pid);
return;
}
第二种方法:两次fork():转载
在《Unix 环境高级编程》里关于这个在8.6节有非常清楚的说明。
实例
回忆一下8 . 5节中有关僵死进程的讨论。如果一个进程要fork一个子进程,但不要求它等待
子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍是调用f o r k
两次。程序8 - 5实现了这一点。
在第二个子进程中调用s l e e p以保证在打印父进程I D时第一个子进程已终止。在f o r k之后,
父、子进程都可继续执行——我们无法预知哪一个会先执行。如果不使第二个子进程睡眠,则
在f o r k之后,它可能比其父进程先执行,于是它打印的父进程I D将是创建它的父进程,而不是
i n i t进程(进程ID 1)。
#include <sys/types.h>
#include <sys/wait.h>
#include "ourhdr.h"
int main(void)
{
pid_t pid;
if ( (pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0) { /* first child */
if ( (pid = fork()) < 0)
err_sys("fork error");
else if (pid > 0)
exit(0); /* parent from second fork == first child */
/* We're the second child; our parent becomes init as soon
as our real parent calls exit() in the statement above.
Here's where we'd continue executing, knowing that when
we're done, init will reap our status. */
sleep(2);
printf("second child, parent pid = %d/n", getppid());
exit(0);
}
if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
err_sys("waitpid error");
/* We're the parent (the original process); we continue executing,
knowing that we're not the parent of the second child. */
exit(0);
}
fork()函数的执行过程、孤儿进程和僵尸进程的更多相关文章
- 1.1 Linux中的进程 --fork、孤儿进程、僵尸进程、文件共享分析
操作系统经典的三态如下: 1.就绪态 2.等待(阻塞) 3.运行态 其转换状态如下图所示: 操作系统内核中会维护多个队列,将不同状态的进程加入到不同的队列中,其中撤销是进程运行结束后,由内核收回. 以 ...
- linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
本节目标: 复制进程映像 fork系统调用 孤儿进程.僵尸进程 写时复制 一,进程复制(或产生) 使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文.进程堆栈. ...
- wait函数返回值总结,孤儿进程与僵尸进程[总结]
http://blog.csdn.net/astrotycoon/article/details/41172389 wait函数返回值总结 http://www.cnblogs.com/Anker/p ...
- PHP7 网络编程(三)孤儿进程与僵尸进程
基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 ...
- python学习笔记—— 多进程中的 孤儿进程和僵尸进程
1 基本概述 1.1 孤儿进程和僵尸进程 父进程创建子进程后,较为理想状态是子进程结束,父进程回收子进程并释放子进程占有的资源:而实际上,父子进程是异步过程,两者谁先结束是无顺的,一般可以通过父进程调 ...
- 什么是PHP7中的孤儿进程与僵尸进程
什么是PHP7中的孤儿进程与僵尸进程 基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法 ...
- 并发编程(二)--利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道
一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似. 2.mu ...
- 并发编程(二)——利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道
Process类与开启进程.守护进程.互斥锁 一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模 ...
- [Linux] 孤儿进程与僵尸进程[总结]
转载: http://www.cnblogs.com/Anker/p/3271773.html 1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两 ...
- 020_Linux的孤儿进程与僵尸进程(Unix系统编程)
1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两个概念比较模糊.今天被人问到什么是孤儿进程和僵尸进程,会带来什么问题,怎么解决,我只停留在概念上 ...
随机推荐
- [bzoj]1930 pacman吃豆豆
Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他 ...
- OwinStartupAttribute出错
尝试加载应用时出现了以下错误.- 找不到包含 OwinStartupAttribute 的程序集.- 找不到包含 Startup 或 [AssemblyName].Startup 类的程序集.若要禁用 ...
- MySQL中 IFNULL、NULLIF和ISNULL函数的用法
mysql 中 ifnull().nullif().isnull()函数的用法讲解: 一.IFNULL(expr1,expr2)用法: 假如expr1不为NULL,则 IFNULL() 的返回值为ex ...
- PHP-redis命令之 列表(lists)
三.列表(lists) 1.lpush:将所有指定的值插入到存于 key 的列表的头部.如果 key 不存在,那么在进行 push 操作前会创建一个空列表. 如果 key 对应的值不是一个 list ...
- Apache ant 配置
ANT_HOME C:\Program Files(D)\apache-ant-1.10.1Path %ANT_HOME%/binant -v
- 2019年北航OO第四次博客总结<完结撒花>
一.UML单元架构设计 1. 类图解析器架构设计 1.1 UML类图 这次作业的目标是要解析一个UML类图,首先为了解耦,我新建了一个类UmTree进行解析工作,而Interaction类仅仅作为实现 ...
- jdk生成证书,网站请求变成https
生成证书的步骤 1.进入jdk的bin目录 keytool -genkey -alias tomcat -keyalg RSA 命名证书的名字叫tomcat 2.将证书拷贝至tomcat的bin目 ...
- .NET开发时让人头痛的SESSION超时
前言 不知道大家在使用用.NET的SESSION的时候有没有遇到过很奇怪的问题,不时候不知道怎么回事,这个SESSION就无缘无故的丢失了 怎么也想不通,不是说SESSION很可靠的吗?这个问题要好好 ...
- oracle整体结构-内存结构、物理结构、逻辑结构、进程
Oracle的体系结构大体上分为两部分:Instance(实例)和Database(数据库). Instance(实例) :在Oracle Instance中主要包含了SGA以及一些进程(例如:PMO ...
- python中用exit退出程序
在python中运行一段代码,如果在某处已经完成整次任务,可以用exit退出整个运行.并且还可以在exit()的括号里加入自己退出程序打印说明.不过注意在py3中要加单引号或双引号哦!