您的位置:首页 > 运维架构 > Linux

linux下处理僵尸进程

2016-09-30 10:14 302 查看
很好写博客,今天手闲拿了一血。大家都知道,在Linux下,所有的进程都是有关系的,不是父子关系就是兄弟关系。然后而子进程退出后或者直接kill它,不会马上被系统收回来,而是变成defunct,处理方式也很简单,从网上查找资料,都说得很笼统,用wait方法等等,要不然就是直接杀死父进程,僵尸进程也随即消失。这样做肯定是不符合我们要求的,下面附上一个tcp的server端的代码,多进程处理。客户端断开后,,不会产生defunct进程。测试有效。。。。

</pre><pre name="code" class="cpp">
#include <stdio.h>  

#include <stdlib.h>  

#include <string.h>                         

#include <unistd.h>  

#include <sys/socket.h>  

#include <netinet/in.h>  

#include <arpa/inet.h>   

#include <fcntl.h>

#include <signal.h>

#define buffer_size 1024   

#define port 5200 
</pre><pre name="code" class="cpp">//主函数,用进程建立一个TCP Echo Server
int main(int argc, char *argv[])

{

int Count = 0;

int connfd;

int sockfd,lenght=0,flag=0;

int i,j;

char c='@';
//  char src[28];

  //  char dst[28];

  //  memset(src,0,sizeof(src));

  //  memset(dst,0,sizeof(dst));
char *p = NULL;

char *q = "exit";

//1.创建tcp套接字

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if(sockfd < 0)

{

perror("socket");

exit(-1);

}

//配置本地网络信息

struct sockaddr_in my_addr;

bzero(&my_addr, sizeof(my_addr));     // 清空

my_addr.sin_family = AF_INET;         // IPv4

my_addr.sin_port   = htons(port);     // 端口

my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip

//2.绑定

int err = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));

if( err != 0)

{

perror("binding error");

close(sockfd);

exit(-1);

}

//3.监听,套接字变被动

err = listen(sockfd, 10);

if(err != 0)

{

perror("listen error");

close(sockfd);

exit(-1);

}

printf("listen....\n");

char client_ip[INET_ADDRSTRLEN] = {0};

struct sockaddr_in client_addr;

socklen_t addr_len = sizeof(client_addr);

while(1) //主进程 循环等待客户端的连接

{

// 取出客户端已完成的连接

connfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);

if(connfd < 0)

{

perror("accept fail");

close(sockfd);

exit(-1);

}

pid_t pid = fork();  //产生一个子进程

if(pid < 0){

perror("fork error");

exit(-1);

}

else if(0 == pid){ //子进程 接收客户端的信息,并发还给客户端

close(sockfd);   // 关闭监听套接字,这个套接字是从父进程继承过来

char recv_buf[1024] = {0};

int recv_len = 0;

// 打印客户端的 ip 和端口

memset(client_ip, 0, sizeof(client_ip)); // 清空

inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);

//   printf("----------------------------------------------\n");

printf("client ip=%s,port=%d,ppid=%d,pid=%d,fd=%d\n", client_ip,ntohs(client_addr.sin_port),getppid(),getpid(),connfd);

// 接收数据

while( (recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0 )

{

printf("recv_buf: %s  len:%d\n", recv_buf,recv_len); // 打印数据

send(connfd, recv_buf, recv_len, 0); // 给客户端回数据

for(i=0;i<recv_len;i++) {

if(recv_buf[i]==c)

{

lenght = i;

flag = 1;

}

}

if(flag>0) {

/*for(j=0;j<recv_len;j++) {

if(j<=len_l)  src[j]=recv_buf[j];

if((len_l+1)<j) dst[j-len_l-2]=recv_buf[j];

}*/

//	strncpy(src,recv_buf,lenght);

//	strncpy(dst,recv_buf+lenght+1,recv_len);

//	printf("src : %s\n",src);

//	printf("dst : %s\n",dst);

//	open_replace(src,dst);

//	memset(src,0,sizeof(src));

//	memset(dst,0,sizeof(dst));

}

p = strstr(recv_buf , q); //收到exit字符串就退出客户端

if(p != NULL) {

printf("recvice exit client is close\n");

close(connfd);

exit(0);

}

flag = 0;

memset(recv_buf,0,sizeof(recv_buf));

}

<span style="white-space:pre">		</span>Count--;  //可以处理子进程退出时,数量-1,当然要用到信号量或者管道等等的进程通信传参方法。否则Count--对父进程
<span style="white-space:pre">			</span>//没效,因为子进程属于父进程的蓝本复制,必须要用进程间的通信方法处理。我就省略此处了。
<span style="white-space:pre">	</span>//<span style="white-space:pre">	</span>pipe(fd);

printf("client_port %d closed!\n", ntohs(client_addr.sin_port));

close(connfd);    //关闭已连接套接字

kill(getpid(),SIGKILL); //杀死子进程,此处可省略,编程规范还是写吧。

exit(0);

}

else if(pid > 0){    // 父进程

<span style="white-space:pre">	</span>   Count++; <span style="white-space:pre">	</span>//子进程数量
printf("----------------------------------------------\n");

printf("I am parent process,pid=%d,Count=%d\n",getpid(),Count);

signal(SIGCHLD,SIG_IGN);  //这句代码就是处理僵尸进程的,第一个参数处理子进程信号,第二个参数就是处理方式,内核直接回收defunct

close(connfd);    //关闭已连接套接字

}

}

close(sockfd);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息