代码如下所示。我试图理解为什么当孩子等待用户输入时,父母不继续执行。我期望父进程读取一些乱码并打印它,因为子进程和父进程将独立运行。但父级会等待子级扫描输入,然后才能正确打印。
#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;
}
默认情况下,使用管道
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