免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2483 | 回复: 5
打印 上一主题 下一主题

[C] waitpid,子进程的一些问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-15 15:41 |只看该作者 |倒序浏览
这个是我从mini_snmpd修改过来的main函数。我的想法是通过select来判断是否有网络请求,然后再fork一个子进程去处理,但是waitpid会是父进程阻塞,这样的话如果我有几个客户端同时访问snmpd服务器,比没有用fork时候的响应还慢。用ps看也只有两个进程在运行,没有达到我想要的当访问的连接就fork多个进程的结果。
我也试过用下面这个函数来处理SIGCHLD来回收子进程,但是效果都还不如没有用多进程的响应快。
static void handle_child(int signo)
{
    int status;
    pid_t pid;
    while(1)
    {
        pid = waitpid((pid_t) -1,&status,WNOHANG);
        if((int) pid == 0)
            break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( (int) pid < 0 )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( errno == EINTR || errno == EAGAIN )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ECHILD shouldn't happen with the WNOHANG option,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// but with some kernels it does anyway.  Ignore it.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( errno != ECHILD )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;syslog( LOG_ERR, "child wait - %m" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror( "child wait" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}


int main(int argc, char *argv[])
{
    struct sockaddr_in sockaddr;
    socklen_t socklen;
    fd_set rfds;
    fd_set wfds;
    int nfds;
    int i;
    int ret;
    struct timeval tv;
    oid_t oid;
    pid_t pid;
    int status;

    /* Prevent TERM and HUP signals from interrupting system calls */
    signal(SIGTERM, handle_signal);

    signal(SIGHUP, handle_signal);
    siginterrupt(SIGTERM, 0);
    siginterrupt(SIGHUP, 0);

    if(fork() > 0)
        exit(0);
   

    /* Open the server's UDP port and prepare it for listening */
    g_udp_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (g_udp_sockfd == -1) {
        lprintf(LOG_ERR, "could not create UDP socket: %m\n");
        exit(EXIT_SYSCALL);
    }
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(g_udp_port);
    sockaddr.sin_addr.s_addr = INADDR_ANY;
    socklen = sizeof (sockaddr);
    if (bind(g_udp_sockfd, (struct sockaddr *)&sockaddr, socklen) == -1) {
        lprintf(LOG_ERR, "could not bind UDP socket to port %d: %m\n", g_udp_port);
        exit(EXIT_SYSCALL);
    }
   

    /* Handle incoming connect requests and incoming data */
    while (!g_quit) {
        /* Sleep until we get data or a connection request */        
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        FD_SET(g_udp_sockfd, &rfds);
        nfds = g_udp_sockfd;
        tv.tv_sec = 0;
        tv.tv_usec = 800000;
        ret = select(nfds + 1, &rfds, &wfds, NULL, &tv);
        if (ret == -1) {
            if (g_quit) {
                break;
            }
//            lprintf(LOG_ERR, "could not select from sockets: %m\n");

//            exit(EXIT_SYSCALL);

        }
        else if(ret)
        {
            /* Handle UDP packets, TCP packets and TCP connection connects */
            if (FD_ISSET(g_udp_sockfd, &rfds)) {
                if( (pid = fork()) == 0)
                {
                    handle_udp_client();
                    exit(0);
                }
                waitpid(pid,&status,0);            
            }
        }

    }
    /* We were killed, print a message and exit */
    lprintf(LOG_INFO, "mini_snmpd stopped\n");

    return EXIT_OK;
}


[ 本帖最后由 snakewind 于 2009-10-15 15:42 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-10-15 15:52 |只看该作者
你程序中怎么两个地方调用了waitpid,只在SIGCHLD的处理函数中调用就可以了

论坛徽章:
0
3 [报告]
发表于 2009-10-15 15:54 |只看该作者
而且UDP你总共就一个fd,还用多进程干什么啊,就一个主进行轮着来不就行了

论坛徽章:
0
4 [报告]
发表于 2009-10-15 16:07 |只看该作者
调用两个waitpid,两个不是同时调用的,一个调用了,另外一个就注释了,只是测试用的
接收的时候是从指定端口接收的,但是接受数据比较快,处理数据比较慢,所以想用多个子进程来处理数据,这样会不会快点?

论坛徽章:
0
5 [报告]
发表于 2009-10-15 16:34 |只看该作者
UDP只从一个端口往出读,你多个进程一体读和一个进程读意义不大,多个进程同时读一个端口会不会冲突还是个问题

论坛徽章:
1
黑曼巴
日期:2020-02-27 22:54:26
6 [报告]
发表于 2009-10-15 16:34 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP