0

我试图让 UNIX 管道正确提示用户输入。我必须使用单个管道创建 3 个子进程。每个子进程要求用户输入一个整数并将其写入管道。父进程显示所有三个整数以及将每个整数写入管道的进程的 processid。

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

int main(int argc, char argv[]) {
    int input = 0;
    int pd[2];
    int i =0;
    int buffer[100];
    int output = 0;

    if (pipe(pd) == - 1) {
        fprintf(stderr, "Pipe Failed");
    }

    for (i=0; i<3; i++) {
        if (fork() == 0) { // child process
            printf("\nMy process id is: %d", getpid());
            printf("\nEnter an integer: ");  
            scanf("%d", &input);
            if (write(pd[1], &input, sizeof(int)) == -1) {
                fprintf(stderr, "Write Failed");
            }
            return (0); // Return to parent. I am not really sure where this should go 
        } // end if statement
    } // I am not quite sure where the for loop ends

    // Parent process
    close(pd[1]); // closing the write end

    for (i = 0; i < 3; i++) {
        if (read(pd[0], &output, sizeof(int) )== -1) {
            fprintf(stderr, "Read failed"); 
        }
        else {
            buffer[i] = output;
            printf("Process ID is: %d\n", pid);
        }
    } 
    printf("The numbers are %d, %d, %d", buffer[0], buffer[1], buffer[2]);
    return(0);
}

编辑后,我现在得到输出:

My process id is: 2897
Enter an integer: My process id is: 2896
Enter an integer: 
My process id is: 2898
Enter an integer: 4
Process ID is: 2898
78
Process ID is: 2898
65
Process ID is: 2898
The numbers are 4, 78, 65

这更接近,但我还不确定如何让父进程等待子进程。当尝试打印每个数字及其进程 ID 时,只会打印最近的进程 ID。

所有 printf 语句都在 scanf 语句之前执行,所以在它提示 3 次之前我不能输入任何内容。

4

2 回答 2

0

在任何给定时间,只有一个进程可以与用户交谈。您需要安排孩子 2 在孩子 1 完成之前不做任何事情,依此类推。最简单的方法是wait()在分叉下一个之前,让每个孩子连续拥有父母。 编辑:看起来像这样:

for (i = 0; i < 3; i++) {
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return 1;
    } else if (pid == 0) {
        // your existing child code goes here
    } else {
        // parent:
        int status;
        if (waitpid(pid, &status, 0) != pid) {
            perror("wait");
            return 1;
        } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
            fprintf(stderr, "child %d unexpected exit %d\n", i, status);
            return 1;
        }
    }
}

由于写入管道的数据量非常短(总共少于PIPE_BUF字节;PIPE_BUF保证至少为 512),您可以安全地延迟从管道读取,直到所有子节点都退出。如果孩子们发回更长的消息,情况就不会如此。

main返回一个整数。您return;在第一个循环中的语句应该是并且在最后(在 final 之后)return 0;需要有另一个。return 0;printf

你的第一个for循环在它应该结束的地方结束,即在嵌套if语句之后。你可以在它周围放置另一组花括号——在你有评论的地方紧跟着打开大括号for (...),在你有// I am not quite sure评论的地方关闭大括号——很多人会认为这种风格更好,但你不必这样做。

于 2013-05-21T00:09:18.737 回答
0
if (read(pd[0]), &output, sizeof(int) )== -1)
              ^ // this is wrong

你的括号不正确,但我认为这是一个错字。

仅在读取失败时才更新缓冲区...应该是:

if (read(pd[0], &output, sizeof(int) )== -1) {
    fprintf(stderr, "Read failed");
}
else {
    buffer[i] = output;
}

不过,有很多方法可以改进此代码。查看其他答案并编译带有警告的程序(-Wall with gcc)

于 2013-05-21T00:15:29.557 回答