linux僵死进程与并发服务器编程

僵死(zombie)进程简而言之就是:子进程退出时,父进程并未对其发出的SIGCHILD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程。

因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源。对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。

查找所有的僵死进程

 ps -A -o stat,ppid,pid,cmd | grep -e ‘^[Zz]‘

处理僵死进程

最简单的方法忽略SIGCHLD信号让系统处理

在Linux下调用signal(SIGCHLD, SIG_IGN),可以简单地将 SIGCHLD信号的操作设为SIG_IGN忽略。 这样可以让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。(Linux
Only)

父进程waitpid释放僵死进程

父进程在fork调用之前调用signal设置SIGCHLD信号处理函数。SIGCHLD处理函数如下:

void sig_chld(int signo)
{
	pid_t pid;
	int stat;
	//Unix下如果一个信号在被阻塞期间产生一次或多次,那么该信号被解阻塞之后通常只递交一次,也就是说Unix信号默认是不排队的。
	while ((pid=waitpid(-1, &stat, WNOHANG)) > 0)
	{
		pintf("child %d terminated\n", pid);
	}
	return;
}

通信注意事项

signal(SIGPIPE, SIG_IGN);

TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道,

但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, 因为TCP协议的限制,

一个端点无法获知对端的socket是调用了close还是shutdown.

对一个已经收到FIN包的socket调用read方法,

如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送).

但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以,

第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.

为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:

signal(SIGPIPE, SIG_IGN);

这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.



linux僵死进程与并发服务器编程

时间: 2024-10-11 13:27:55

linux僵死进程与并发服务器编程的相关文章

第15章 高并发服务器编程(2)_I/O多路复用

3. I/O多路复用:select函数 3.1 I/O多路复用简介 (1)通信领域的时分多路复用 (2)I/O多路复用(I/O multiplexing) ①同一线程,通过"拨开关"方式,来同时处理多个I/O流,哪个IO准备就绪就把开关拨向它.(I/O多路复用类似于通信领域中的"时分复用") ②通过select/poll函数可以实现IO多路复用,他们采用轮询的方式来监视I/O.而epoll是对select/poll的加强,它是基于事件驱动,epoll_ctl注册事件

用select单个进程处理并发服务器

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); void FD_CLR(int fd, fd_set *set); int  FD_ISSET(int fd, fd_set *set); void FD_SET(int fd, fd_set *set); void FD_ZERO(fd_set *set); 可读 套接口缓冲区有数据可读 连接的

Linux下几种并发服务器的实现模式

Linux下的几种并发服务器的设计模式 1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循环服务器:一个server只能一次只能接收一个client,当当前client结束访问之后才能进行下一个client的连接. 2.并发服务器:一个server同一时间可以响应很多客户端的访问. 3>select+多线程模式 并发服务器的三种实现方式 1.多进程并发

linux学习之高并发服务器篇(二)

高并发服务器 1.线程池并发服务器 两种模型: 预先创建阻塞于accept多线程,使用互斥锁上锁保护accept(减少了每次创建线程的开销) 预先创建多线程,由主线程调用accept 线程池 3.多路I/O转接服务器 三种模型性能分析 select模型 select用来阻塞监听4,5,6,7是否有数据传入,若7这个文件描述符有数据到达,select返回就绪文件描述符个数,若检测到7有数据接收,accept接收客户链接请求,创建一个新的文件描述符. select (1)select能监听的文件描述

linux 僵死进程

僵死进程简而言之就是:子进程退出时,父进程并未对其发出的SIGCHILD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程. 在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵死进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵死进程.补救办法是杀死僵尸进程的父进程(僵死进程的父进程必

linux僵死进程的产生与避免

作者:lingdxuyan来源:ChinaUnix技术博客,本文版权由lingdxuyan所有,如需转载,请注明出处. 一个进程在调用exit命令结束自己的生命的时候,其实它并没有真正的被销毁, 而是留下一个称为僵死进程(Zombie)的数据结构(系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵死进程,并不能将其完全销毁).“僵死进程的产生在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等,但是仍然为其保留一定的信息(包括进程号the pr

linux僵死进程zombie处理。

今天早上检查服务器的状况,发现有一个zombie的进程.现将处理过程,描述一下. 命令注解: -A 参数列出所有进程 -o 自定义输出字段 我们设定显示字段为 stat(状态), ppid(进程父id), pid(进程id),cmd(命令) 因为状态为 z或者Z的进程为僵尸进程,所以我们使用grep抓取stat状态为zZ进程 用 kill -HUP 子进程号和kill -HUP 父进程号均不能处理掉僵死进程.最后用kill -9 父进程号 搞定!

Linux环境下高并发服务器构建手记

最近用Golang做了一个项目,产品需求是"单服要达到5000并行处理" 硬件配置如下: CPU:Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz MEM:32G DISK:SCSI 600G 10000转/秒 OS:Centos 6.6 好了,先解决并发连接问题,对linux系统环境做了一些优化,优化过程如下: 优化内核参数: 1:修改系统资源限制文件:/etc/security/limit.conf 参照配置文件帮助描述,添加如下配置 * hard

并发服务器三种实现方式之进程、线程和select

前言:刚开始学网络编程,都会先写一个客户端和服务端,不知道你们有没有试一下:再打开一下客户端,是连不上服务端的.还有一个问题不知道你们发现没:有时启服务器,会提示“Address already in use”,过一会就好了,想过为啥么?在这篇博客会解释这个问题. 但现实的服务器都会连很多客户端的,像阿里服务器等,所以这篇主要介绍如何实现并发服务器,主要通过三种方式:进程.线程和select函数来分别实现. 一.进程实现并发服务器 先说下什么是并发服务器吧?不是指有多个服务器同时运行,而是可以同