如何正确地为用户输入创建UNIX管道提示?

时间:2013-05-20 23:56:12

标签: c unix pipe

我正在尝试正确提示用户输入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次之前我不能输入任何内容。

2 个答案:

答案 0 :(得分: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;语句应为return 0;,最后需要另一个return 0;(最后printf之后)。

您的第一个for循环在它应该结束的位置结束,即在嵌套的if语句之后。你可以在它周围放置另一组花括号 - 在for (...)之后打开大括号,在你有// I am not quite sure注释的右大括号 - 很多人会考虑到更好的风格,但你不必。

答案 1 :(得分: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)

上编辑警告程序