尝试理解为什么这段代码中的父进程从子进程中获取正确的值

问题描述 投票:0回答:1

代码如下所示。我试图理解为什么当孩子等待用户输入时,父母不继续执行。我期望父进程读取一些乱码并打印它,因为子进程和父进程将独立运行。但父级会等待子级扫描输入,然后才能正确打印。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    int pipe_fd[2];
    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        return 1;
    }

    pid_t child_pid = fork();
    if (child_pid == -1) {
        perror("fork");
        return 1;
    }

    if (child_pid == 0) {
        // Child process
        close(pipe_fd[0]); // Close the reading end in the child
        
        int numberToSend;
        printf("Enter a number to send to parent: ");
        scanf("%d", &numberToSend);
        
        write(pipe_fd[1], &numberToSend, sizeof(numberToSend));
        close(pipe_fd[1]);
        exit(0);
    } else {
        // Parent process
        close(pipe_fd[1]); // Close the writing end in the parent
        int receivedNumber;
        read(pipe_fd[0], &receivedNumber, sizeof(receivedNumber));
        close(pipe_fd[0]);

        printf("Parent received number: %d\n", receivedNumber);
    }

    return 0;
}
c pipe fork
1个回答
0
投票

默认情况下,使用管道

read()
是一个阻塞操作,这意味着它会停止并等待文件描述符中的数据变得可用。

fcntl
(
F_SETFL
) 可以与
O_NONBLOCK
标志一起使用,将管道更改为非阻塞。

例如:

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

int main(void)
{
    int pipe_fd[2];
    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        return 1;
    }

    int flags = fcntl(pipe_fd[0], F_GETFL);
    if (-1 == fcntl(pipe_fd[0], F_SETFL, flags | O_NONBLOCK)) {
        perror("fcntl");
        return 1;
    }

    pid_t child_pid = fork();
    if (child_pid == -1) {
        perror("fork");
        return 1;
    }

    if (child_pid == 0) {
        close(pipe_fd[0]);

        int numberToSend;

        printf("Enter a number to send to parent: ");

        if (1 == scanf("%d", &numberToSend))
            write(pipe_fd[1], &numberToSend, sizeof(numberToSend));

        close(pipe_fd[1]);
        exit(0);
    } else {
        close(pipe_fd[1]);

        int receivedNumber;
        ssize_t rc = read(pipe_fd[0], &receivedNumber, sizeof(receivedNumber));

        if (rc == sizeof receivedNumber)
            printf("Parent received number: %d\n", receivedNumber);
        else if (EAGAIN == errno)
            fprintf(stderr, "Parent did not wait for data!!\n");
        else
            perror("read");

        close(pipe_fd[0]);
    }

    int status;

    while (wait(&status) > 0);

    printf("Child(%ld) exited with status: %d\n",
            (long) child_pid, WEXITSTATUS(status));
}
$ ./a.out 
Parent did not wait for data!!
Enter a number to send to parent: 42
Child(67023) exited with status: 0
© www.soinside.com 2019 - 2024. All rights reserved.