繁体   English   中英

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

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

我试图让UNIX管道正确提示用户输入。 我必须使用单个管道创建3个子进程。 每个子进程都要求用户输入一个整数并将其写入管道。 父进程显示所有三个整数以及将每个整数写入管道的进程的进程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);
}

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

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在子级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地方关闭花括号, // I am not quite sure发表的评论-很多人会认为这种样式更好,但是您不必。

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

但是,有许多方法可以改进此代码。 查看其他答案,并在警告下编译您的程序(-gcc带有Wall)

暂无
暂无

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

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