【问题标题】:pipe(), fork(), and sleep()pipe()、fork() 和 sleep()
【发布时间】:2014-05-14 11:52:53
【问题描述】:

在多个客户端请求上,给定的服务器代码应响应每个客户端请求的序列号。同样对于每个客户端请求,服务器应该分叉一个进程。然后子进程等待 5 秒并减少客户端请求计数。所以基本上它是一个令牌系统。

代码中的问题是,当我发送多个客户端请求时,除了第一个请求之外,其他请求会被阻止 5 秒,这是我不想要的。

static int num = 0;

int main(int ac, char *av[]){

    struct sockaddr_in saddr;
    struct hostent *hp;
    char hostname[HOSTLEN];
    int sock_id, sock_fd;
    FILE *sock_fp;
    int pid, fd[2];
    pipe(fd);

    sock_id = socket(PF_INET, SOCK_STREAM, 0);
    if(sock_id == -1)
            oops("Socket");

    bzero((void *)&saddr, sizeof(saddr));

    gethostname(hostname, HOSTLEN);
    hp = gethostbyname(hostname);

    bcopy((void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);
    saddr.sin_port = htons(PORTNUM);
    saddr.sin_family = AF_INET;

    if(bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0)
            oops("bind");

    if(listen(sock_id, 5) != 0)
            oops("listen");
    while(1) {
            sock_fd = accept(sock_id, NULL, NULL);
            printf("got a call\n");
            if(sock_fd == -1)
                    oops("accept");

            num++;

            sock_fp = fdopen(sock_fd, "w");
            if(sock_fp == NULL)
                    oops("fdopen");
            fprintf(sock_fp, "Your token number is: %d\n", num);
            fclose(sock_fp);

            pid = fork();

            if(pid == 0){
                    close(sock_id);
                    sleep(5);
                    num--;

                    close(fd[0]);
                    write(fd[1], &num, sizeof(num));
                    printf("Sent: %d\n", num);
                    close(fd[1]);
                    exit(0);
            }
            else if(pid > 0){
                    close(fd[1]);
                    read(fd[0], &num, sizeof(num));
                    printf("Received %d\n", num);
                    close(fd[0]);
                    close(sock_fd);
            }

    }

【问题讨论】:

  • 您的代码似乎丢失了,例如一个pipe 电话。 sock_id 是什么?你知道当你关闭sock_fp 时,你也关闭了sock_fd
  • 为了清楚起见,我已经发布了整个代码。

标签: c fork pipe


【解决方案1】:

在父进程中,您尝试从空管道读取,read() 将阻塞直到数据可用,因此它阻塞直到子进程唤醒并调用write()。调用pipe()后向管道写入一些东西,

pipe(fd);
write(fd[1], &num, sizeof(num));

它会解决你的问题。

Joachim Pileborg 关于处理子进程收获的说法很重要。

【讨论】:

  • 它解决了阻塞问题,但产生了新问题。我发送了 3 个客户端请求并得到以下输出:
  • 它解决了阻塞问题,但产生了新问题。我发送了 3 个客户端请求并得到以下输出: 在客户端:您的令牌编号为 1,您的令牌编号为 1,您的令牌编号为 2 在服务器中我得到以下输出:接听电话,接听电话 0,接听电话,接听电话1,接到电话,已接 2,已发送:0,已发送:1,已发送应执行 3 次,但这里只有 2。也已发送不反映共享内存编号。
  • 由于我们不知道父子进程的执行顺序,所以输出是不确定的。而read()write() 可能会失败,您应该检查返回值。 num 不被多个进程共享,整个地址空间在fork() 期间复制,父子进程拥有自己的静态数据副本。
【解决方案2】:

问题可能是在fork 之后,在父级中您关闭了管道的两端,因此在无限循环的下一次迭代中您尝试使用管道但它已经关闭了。


您还应该处理子进程的收割,否则它们会变成僵尸,直到父进程退出。这可以通过为SIGCHLD 安装信号处理程序并在信号处理程序调用wait 中完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 2012-09-12
    相关资源
    最近更新 更多