Chinaunix首页 | 论坛 | 博客
  • 博客访问: 126586
  • 博文数量: 36
  • 博客积分: 94
  • 博客等级: 民兵
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-23 17:34
文章分类
文章存档

2015年(1)

2013年(7)

2012年(3)

2011年(25)

分类:

2012-04-18 15:08:30

#include    "unp.h"

void
sig_chld(int signo)
{
    pid_t    pid;
    int        stat;

    while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)  /*参数 WNOHANG 表示采用非阻塞方式*/
        printf("child %d terminated\n", pid);
    return;
}


int
main(int argc, char **argv)
{
    int                    listenfd, connfd;
    pid_t                childpid;
    socklen_t            clilen;
    struct sockaddr_in    cliaddr, servaddr;
    void                sig_chld(int);

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    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, (SA *) &servaddr, sizeof(servaddr));

    Listen(listenfd, LISTENQ);

    Signal(SIGCHLD, sig_chld);    /* 为防止子进程产生僵尸进行,必须调用waitpid函数进行清理*/

    for ( ; ; ) {
        clilen = sizeof(cliaddr);
        if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
            if (errno == EINTR)
                continue;        /* back to for() */
            else
                err_sys("accept error");
        }

        if ( (childpid = Fork()) == 0) {    /* child process */
            Close(listenfd);    /* close listening socket */
            str_echo(connfd);    /* process the request */
            exit(0);
        }
        Close(connfd);            /* parent closes connected socket */
    }
}

备注:
1、采用fork复制进行,由于有两份资源,因此上面的描述符关闭都有两次,而描述符是被
内核引用计数的,因此,只有当两个都关闭时,内核才会真正关闭该描述符。
2、wait函数本身为阻塞方式,不足以防止僵尸进程出现,如,5个信号函数都在信号处理函数之前产生,
而信号处理函数只执行一次,剩下的就会成为僵尸。


阅读(1140) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~