简体   繁体   English

如何使UNIX管道正确提示用户输入?

[英]How to make a UNIX pipe prompt for user input correctly?

I am trying to have UNIX pipes correctly prompt for user input. 我试图让UNIX管道正确提示用户输入。 I have to create 3 child processes using a single pipe. 我必须使用单个管道创建3个子进程。 Each child process asks the user to enter an integer and writes it to the pipe. 每个子进程都要求用户输入一个整数并将其写入管道。 The parent process displays all three integers as well as the processid's of the process that wrote each to the pipe. 父进程显示所有三个整数以及将每个整数写入管道的进程的进程ID。

#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);
}

After editing, I now get as output: 编辑后,我现在得到输出:

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

which is a lot closer but I am not yet sure how to make the parent wait for the child processes. 这离我们很近,但我还不确定如何让父级等待子级进程。 When trying to print each number along with it's process id, only the most recent process id is getting printed. 当尝试打印每个数字及其进程ID时,只会打印最新的进程ID。

All of the printf statements execute before the scanf statements so I can't type anything until it prompts 3 times. 所有printf语句在scanf语句之前执行,因此我无法键入任何内容,直到提示3次为止。

Only one process can be talking to the user at any given time. 在任何给定时间,只有一个进程可以与用户对话。 You need to arrange so that child 2 doesn't do anything until child 1 is done, and so on. 您需要进行安排,以使子级2在子级1完成之前不会执行任何操作,依此类推。 The simplest way to do this is to have the parent wait() for each child in succession, before forking off the next one. 最简单的方法是在派生下一个孩子之前,先让每个孩子都拥有父wait() EDIT: That would look something like this: 编辑:看起来像这样:

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;
        }
    }
}

Since the amount of data written to the pipe is very short (less than PIPE_BUF bytes in total; PIPE_BUF is guaranteed to be at least 512), you can safely delay reading from the pipe until after all children have exited. 由于写入管道的数据量非常短(总共少于PIPE_BUF字节;保证PIPE_BUF至少为512),因此可以放心地从管道中读取数据,直到所有子项都退出为止。 This would not be the case if the children were sending back longer messages. 如果孩子们发回更长的消息,情况就不会如此。

main returns an integer. main返回一个整数。 Your return; 您的return; statement inside the first loop should be return 0; 第一个循环中的语句应return 0; and there needs to be another return 0; 并且需要另一个return 0; at the very end (after the final printf ). 在最后(最后一次printf )。

Your first for loop ends right where it ought to end, ie after the nested if statement. 您的第一个for循环在应该结束的地方结束,即在嵌套的if语句之后。 You can put another set of curly braces around it - open brace right after the for (...) , close brace right where you have the // I am not quite sure comment - and lots of people would consider that better style, but you don't have to. 可以在其周围放置另一组花括号-在for (...)之后打开花括号,在您拥有// I am not quite sure地方关闭花括号, // I am not quite sure发表的评论-很多人会认为这种样式更好,但是您不必。

if (read(pd[0]), &output, sizeof(int) )== -1)
              ^ // this is wrong

your parenthesis are incorrect but I assume that's a typo. 您的括号不正确,但我认为这是一个错字。

You also update buffer only if read fails... It should be: 您还只有在读取失败的情况下才更新缓冲区...应该是:

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

There are many ways this code could be improved though. 但是,有许多方法可以改进此代码。 Look at other answers and compile your programs with warnings on (-Wall with gcc) 查看其他答案,并在警告下编译您的程序(-gcc带有Wall)

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

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