管道卡在读取中(C-系统调用)

管道卡在读取中(C-系统调用),c,pipe,system-calls,C,Pipe,System Calls,这是我第一次使用C语言,所以到目前为止它非常困难。 我的程序读取一个file.txt文件。 在第一行中,我必须创建var:NPROC的子进程数,在其余行中,我必须读取子进程id、两个整数和一个字符,这是我必须计算的操作: 例: 我必须使用工作正常的消息队列将操作逐行发送给孩子,然后孩子应该使用管道返回结果 代码如下: 父亲 //other code for(i=0; i < NPROC; i++) { if(pipe(p) == -1) { perror("pip

这是我第一次使用C语言,所以到目前为止它非常困难。 我的程序读取一个file.txt文件。 在第一行中,我必须创建var:NPROC的子进程数,在其余行中,我必须读取子进程id、两个整数和一个字符,这是我必须计算的操作: 例:

我必须使用工作正常的消息队列将操作逐行发送给孩子,然后孩子应该使用管道返回结果

代码如下:

父亲

//other code
for(i=0; i < NPROC; i++) {

    if(pipe(p) == -1) {
        perror("pipe");
        exit(1);
    }

    switch(currentPid = fork()){
        case 0:

            execl("./child", "./child", NULL);

            return 0;
        case -1:
            printf("Error when forking\n");
            break;
        default:

            // in the father
            childrenPids[i] = currentPid; // store current child pid
            wait(NULL);

            printf("\nParentpid:  %d, Childpid: %i \n", getpid(), currentPid);

            //close(p[1]);

            if(read(p[0], &val, sizeof(val) == -1){
                perror("read()\n");
                exit(1);
            }

            printf("Parent(%d) received value: %d\n", getpid(), val);

            break;         
    }

   //other code


(child)
 //other code
 while (1) {

        long msgtype = m->mtype;
        if(msgrcv(msgid, m, sizeof(message) - sizeof(m->mtype), msgtype, IPC_NOWAIT) == -1) {
            // if(close (p[1]) == -1){
            //     perror("close p[1] of the child\n");
            // } 
            //perror("\nmsgrcv");
            exit(1);
        }
        result[i] = calcolate_results(m);
        // printf("%i %i %c %i", m->id, m->num1, m->op, m->num2);
        printf("\nresult: %i\n", result[i]);

        val = result[i];

        if(write (p[1], &val, sizeof(val)) == -1) { 
            perror("write\n");
            exit(1);
        }
        printf("Child(%d) send val: %d\n", getpid(), val);
    }
 //other code
现在我的问题是,父亲的阅读似乎没有得到这个信息。 当我执行的程序没有退出时,它在父循环中的读取处保持stuch。 我试图将读取内容放在for之外,这样它至少应该读取最后一条消息,但程序仍然停留在读取中。
因此,如果有人能帮助我,我将非常感激。

您的代码充满了问题

switch(currentPid = fork()){
    case 0:
在此,您需要关闭管道的读取端:

        close(p[0]);
通常在这里执行前会有一个dup2。通常,如果您的子进程要加载另一个程序,您希望将其stdout重定向到管道的写入端,如dup2p[1],1;关闭[1]

这个等待电话打错地方了。如果子级输出的数据超过管道一次可以容纳的数据量,则会出现死锁,子级将在写入时阻塞,等待父级读取管道的一些数据,然后才能退出;父级将阻塞等待,等待子级退出,然后再从管道中读取

在你给孩子做任何事情之前,等待孩子离开也是没有意义的。这不应该是一种类似于协进程的设计吗?也就是说,孩子们应该继续沿着父代运行,根据请求进行算术运算,然后将结果发送回来

        printf("\nParentpid:  %d, Childpid: %i \n", getpid(), currentPid);

        //close(p[1]);
为什么会有这样的结局?父进程关闭管道的写入端是至关重要的,因为在本例中,由于写入端在同一进程中的某个位置仍然打开,因此从管道的读取端读取将被阻塞

        if(read(p[0], &val, sizeof(val) == -1){
这一行甚至没有编译。少了一个

你少了一张EOF支票。read在到达数据末尾时将返回0,并保持val未初始化


您应该使用管道中的所有可用数据,直到read返回0,然后才使用waitpidcurrentPid,NULL,0

代码中可能有一些拼写错误,因为我用英语翻译了代码。翻译是个好主意。但请验证它是否仍按所述运行。也就是说,确保它仍然是一个。@Yunnosch我只翻译了变量、函数、注释的名称。尽管如此,显示的代码肯定不是一个,但这使问题偏离了主题:问题寻求调试帮助为什么这段代码不起作用?必须包括所需的行为、特定的问题或错误以及在问题本身中重现这些问题所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请看:如何创建一个。我已经发布了一个答案,列出了我可以从您的代码摘录中看到的问题。读阻塞的常见问题是忘记关闭子级中的[0]和父级中的[1]。
        printf("\nParentpid:  %d, Childpid: %i \n", getpid(), currentPid);

        //close(p[1]);
        if(read(p[0], &val, sizeof(val) == -1){
            perror("read()\n");
            exit(1);
        }