繁体   English   中英

关于Systm的问题在C中调用fork()和pipe()

[英]Questions about Systm calls like fork() and pipe() in C

   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   #include<sys/wait.h>
   #include<errno.h>

   int main(int argc, char **argv){
       int n = atoi(argv[1]);
       int superdaddy = getpid();
       int p[n+1][2];
       int i=0;
       int cpid,output;
       int result = 0;

       if(pipe(p[0])<0){
           perror("1");
           return 1;
       }
       if(pipe(p[n])<0){
           perror("2");
           return 1;
       }
       output = p[0][1];
       if(getpid()==superdaddy){
           if(write(p[0][1],&result,sizeof(result))<0){
               perror("3");
               return 1;
           }
           if(close(p[0][1])<0){
               perror("4");
               return 1;
           }
       }
       while(1){
           if(i==n){
               if(read(p[n-1][0],&result,sizeof(result)<0)){
                   perror("5");
                   return 1;
               }
               result++;
               output = p[n][1];
               if(write(output,&result,sizeof(result))<0){
                   perror("6");
                   return 1;
               }
               if(close(p[n-1][0])<0){
                   perror("7");
                   return 1;
               }
               if(close(p[n][1])<0){
                   perror("8");      
                   return 1;
               }
               break;
           }
           i++;
           cpid = fork();
           if(cpid==0){
               if(i==n)
                   continue;
               if(pipe(p[i])<0){
                   perror("9");
                   return 1;
               }
               if(read(p[i-1][0],&result,sizeof(result))<0){
                   perror("10");
                   return 1;
               }
               result++;
               output = p[i][1];
               if(write(output,&result,sizeof(result))<0){
                   perror("11");
                   return 1;
               }
               if(close(p[i-1][0])<0){
                   perror("12");
                   return 1;
               }

               if(close(p[i][1]<0)){
                   perror("13");
                   return 1;
               }
               continue;
           }
           else if(cpid<0){
               perror("14");
               return 1;
           }
           break;
       }

       if(getpid()==superdaddy){
           wait(NULL);
           if(read(p[n][0],&result,sizeof(result))<0){
               perror("15");
               return 1;
           }
           printf("Result: %d\n",result);
           if(close(p[n][0])<0){
               perror("16");
               return 1;
           }
       }
       return 0;
   }

该程序旨在从命令行读取数字n,然后分叉子进程并创建n个管道。 进程p0将是进程p1父进程, p1将成为p2父进程,依此类推。 一个变量(在这里命名为result)将通过管道传递,每次传递时它都将被添加1.因此输出也应该是n。 Pipe Fi连接PiP(i+1) 附上是我的代码。

n = 1n = 2时 ,程序可以正确输出,相应地为1和2。 但是,当n = 3时 ,它在错误5时给出了错误的文件错误。我已经整个下午手动跟踪代码,但不知道它有什么问题。 有人可以帮忙吗? 首先欣赏它!

当n = 3时,它在错误5时给出了错误的文件错误。

这可以通过删除你的代码中的if(close(p[i][1]<0)){来修复,因为你需要在上一次迭代中从p[i][0]读取,即

if (i == n) {
    if(read(p[n-1][0],&result,sizeof(result)<0)){
        ...
    }
}

这是您的想法的实现,我希望它可能会有所帮助:

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s N\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int n = atoi(argv[1]);
    int pipes[n][2];
    int i, val;
    pid_t pid;

    val = 0;

    for (i = 0; i < n; i++) {
        if (pipe(pipes[i]) < 0) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
        if ((pid = fork()) < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        else if (pid == 0) {
            close(pipes[i][1]);
            if (read(pipes[i][0], &val, sizeof(val)) != sizeof(val)) {
                perror("read");
                exit(EXIT_FAILURE);
            }

            printf("C %d read %d\n", getpid(), val);

            val++;
        }
        else {
            close(pipes[i][0]);

            printf("P %d writes %d\n", getpid(), val);

            if (write(pipes[i][1], &val, sizeof(val)) != sizeof(val)) {
                perror("write");
                exit(EXIT_FAILURE);
            }

            if (waitpid(pid, NULL, 0) != pid) {
                perror("waitpid");
                exit(EXIT_FAILURE);
            }
            printf("%d is going to leave.\n", getpid());
            exit(EXIT_SUCCESS);
        }
    }

    printf("%d is going to leave.\n", getpid());
    exit(EXIT_SUCCESS);
}

测试运行:

$ ./a.out 3
P 2005 writes 0
C 2006 read 0
P 2006 writes 1
C 2007 read 1
P 2007 writes 2
C 2008 read 2
2008 is going to leave.
2007 is going to leave.
2006 is going to leave.
2005 is going to leave.

说明:

该代码的帧是for (i = 0; i < n; i++) { pipe(); fork(); } for (i = 0; i < n; i++) { pipe(); fork(); } for (i = 0; i < n; i++) { pipe(); fork(); } ,这意味着它将创建n管道和n新进程。 在每次迭代中,父级将写入pipes[i][1] ,子级将从pipes[i][0]读取。 最终,它将创建一个由一系列管道连接的流程链,并通过该系列管道将值从第一个流程传递到最后一个流程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM