每天一小步——自写服务器与信号处理僵尸子进程

来源:互联网 发布:艾薇儿已经去世 知乎 编辑:程序博客网 时间:2024/05/17 01:07

学习中写了一个简单的小服务器程序,可以用来上传备份文件。tcp/ip协议的三次握手是不变的,我们所要做的就是在这个框架上搭建自己想要的功能实现扩展,并优化程序!

虽然是一个小服务器程序,但是也是会遇到不少问题,但最后还是努力解决了!如文件名与文件内容出现交错,最后用传完文件名后,采用一个确认,然后再传送文件内容来解决了内容!

为了实现服务多用户的功能,采用了fork函数。但是采用fork后必然会出现僵尸子进程,处理好僵尸进程也为难了我一会!刚开始采用了wait和waitpid函数!

wait函数会阻塞住进程,影响了服务多用户的功能。子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可!但是我的程序在采用这个方法时遇到了一个至今没法解决的问题,老是无限循环一个错误!有兴趣的同学可以帮我实现!

waitpid函数虽然是封装了wait函数,但是比wait灵活许多,但是我用了 waitpid(0,&status,WNOHANG|WUNTRACED);时总是会残留一个僵尸进程,无法全部处理完全,有兴趣的高手,可以帮一下小弟!

由于UNIX的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理
掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略通常是没有区别的,但这是一个特例。
这个方法是方法我没出现错误,但此方法对于Linux可用,但不保证在其它UNIX系统上都可用

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include <sys/wait.h>#define MAXLINE 128#define SERV_PORT 8000void pid_action(int pid,int listenfd,int connfd,struct sockaddr_in *cliaddr){        int i,n,ret=0;        int dest;        char buf[MAXLINE],ibuf[MAXLINE];        char str[INET_ADDRSTRLEN];        char *copy=NULL;        close(listenfd);        bzero(buf,MAXLINE);        n=read(connfd,buf,MAXLINE);        dest=open(buf,O_RDWR|O_CREAT|O_TRUNC,0666);        if(dest<0){                perror("open");                exit(1);        }        write(connfd,"1",1);/*transmission on demand*/        bzero(buf,MAXLINE);        /*receive the file content*/        while((n=read(connfd,buf,MAXLINE))>0){                copy=buf;                while(n>0){                        ret=write(dest,copy,n);                        n=n-ret;                      copy=copy+ret;                }                write(dest,buf,n);                bzero(buf,MAXLINE);        }        printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr->sin_addr,str,sizeof(str)),ntohs(cliaddr->sin_port));        close(dest);        close(connfd);}int main(void){        struct sockaddr_in servaddr,cliaddr;        struct sigaction newact,oldact;        socklen_t cliaddr_len;        int listenfd,connfd,status;        pid_t pid;        /*sigaction configuration*/        newact.sa_handler=SIG_IGN;        sigemptyset(&newact.sa_mask);        newact.sa_flags=0;        sigaction(SIGCHLD,&newact,&oldact);        listenfd=socket(AF_INET,SOCK_STREAM,0);        /*net configuration*/        bzero(&servaddr,sizeof(servaddr));        servaddr.sin_family=AF_INET;        servaddr.sin_addr.s_addr=htonl(INADDR_ANY);        servaddr.sin_port=htons(SERV_PORT);        bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));  listen(listenfd,20);        printf("Accepting connections ..\n");        while(1){                cliaddr_len=sizeof(cliaddr);                connfd=accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len);                if((pid=fork())<0){                        perror("fork");                        exit(1);                }                if(pid==0){                        pid_action(pid,listenfd,connfd,&cliaddr);                        exit(1);                }                if(pid>0){                        close(connfd);                }        }}




原创粉丝点击