为什么子进程在使用父输出的标准输入的 fork 和管道时等待?
Why child process is waiting while using fork and pipes for stdin from parent's output?
我了解 fork 和管道的工作原理,但我对子进程和父进程的流程有疑问 process.Since 我们正在使用 fork,父进程和子进程的执行顺序未定义,但为什么子进程是如果子进程先执行,就会等待来自父 process.What 的标准输入?它必须在控制台中打印为空?但它没有发生我能知道为什么吗?
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main () {
int fds[2]; pid_t pid;
/* File descriptors for the two ends of the pipe are placed in fds. */
pipe (fds);
/* Fork a child process. */
pid = fork ();
if (pid == (pid_t) 0) {
/* Child proces -. Close the write end of the file descriptor. */
close (fds[1]);
/* Connect the read end of the pipe to standard input. */
dup2 (fds[0], STDIN_FILENO);
/* Replace the child process with the “rev” program. */
execlp("rev", "rev", 0); }
else {
/* This is the parent process. */
FILE* stream;
/* Close the read end of the file descriptor. */
close (fds[0]);
/* Convert the write file descriptor to a FILE object */
stream = fdopen (fds[1], "w");
fprintf (stream, ",ereh ot ereht morF\n");
fprintf (stream, ",ereht ot ereh dna\n");
fprintf (stream, ".erehwyreve era sgniht ynnuf\n");
fprintf (stream, "ssueS .rD - \n");
fflush (stream);
close (fds[1]);
/* Wait for the child process to finish. */
waitpid (pid, NULL, 0);
}
return 0;
}
您在 child 中没有关闭足够的文件描述符。
经验法则:如果你
dup2()
管道的一端连接到标准输入或标准输出,同时关闭
返回的原始文件描述符
pipe()
尽早。
特别是,您应该在使用任何
exec*()
函数族。
如果您使用以下任一方式复制描述符,则该规则也适用
dup()
或者
fcntl()
F_DUPFD
在这种情况下,child需要在复制后关闭fds[1]
。因为它仍然是打开的,rev
将永远不会收到 EOF,因为理论上有一个进程(rev
child 进程)可以写入输入。
您应该使用 fclose(stream)
而不是 close(fds[1])
,因为输出是缓冲的并且 fclose()
知道刷新缓冲区,但 close()
不知道。但是,通过在被误导的 close()
之前使用 fflush(stream)
,您确实可以避免问题。
这导致:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if (pid == (pid_t)0)
{
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[1]);
execlp("rev", "rev", 0);
}
else
{
FILE *stream;
close(fds[0]);
stream = fdopen(fds[1], "w");
fprintf(stream, ",ereh ot ereht morF\n");
fprintf(stream, ",ereht ot ereh dna\n");
fprintf(stream, ".erehwyreve era sgniht ynnuf\n");
fprintf(stream, "ssueS .rD - \n");
fclose(stream);
waitpid(pid, NULL, 0);
}
return 0;
}
产生输出:
From there to here,
and here to there,
funny things are everywhere.
- Dr. Seuss
我了解 fork 和管道的工作原理,但我对子进程和父进程的流程有疑问 process.Since 我们正在使用 fork,父进程和子进程的执行顺序未定义,但为什么子进程是如果子进程先执行,就会等待来自父 process.What 的标准输入?它必须在控制台中打印为空?但它没有发生我能知道为什么吗?
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main () {
int fds[2]; pid_t pid;
/* File descriptors for the two ends of the pipe are placed in fds. */
pipe (fds);
/* Fork a child process. */
pid = fork ();
if (pid == (pid_t) 0) {
/* Child proces -. Close the write end of the file descriptor. */
close (fds[1]);
/* Connect the read end of the pipe to standard input. */
dup2 (fds[0], STDIN_FILENO);
/* Replace the child process with the “rev” program. */
execlp("rev", "rev", 0); }
else {
/* This is the parent process. */
FILE* stream;
/* Close the read end of the file descriptor. */
close (fds[0]);
/* Convert the write file descriptor to a FILE object */
stream = fdopen (fds[1], "w");
fprintf (stream, ",ereh ot ereht morF\n");
fprintf (stream, ",ereht ot ereh dna\n");
fprintf (stream, ".erehwyreve era sgniht ynnuf\n");
fprintf (stream, "ssueS .rD - \n");
fflush (stream);
close (fds[1]);
/* Wait for the child process to finish. */
waitpid (pid, NULL, 0);
}
return 0;
}
您在 child 中没有关闭足够的文件描述符。
经验法则:如果你
dup2()
管道的一端连接到标准输入或标准输出,同时关闭
返回的原始文件描述符
pipe()
尽早。
特别是,您应该在使用任何
exec*()
函数族。
如果您使用以下任一方式复制描述符,则该规则也适用
dup()
或者
fcntl()
F_DUPFD
在这种情况下,child需要在复制后关闭fds[1]
。因为它仍然是打开的,rev
将永远不会收到 EOF,因为理论上有一个进程(rev
child 进程)可以写入输入。
您应该使用 fclose(stream)
而不是 close(fds[1])
,因为输出是缓冲的并且 fclose()
知道刷新缓冲区,但 close()
不知道。但是,通过在被误导的 close()
之前使用 fflush(stream)
,您确实可以避免问题。
这导致:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if (pid == (pid_t)0)
{
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[1]);
execlp("rev", "rev", 0);
}
else
{
FILE *stream;
close(fds[0]);
stream = fdopen(fds[1], "w");
fprintf(stream, ",ereh ot ereht morF\n");
fprintf(stream, ",ereht ot ereh dna\n");
fprintf(stream, ".erehwyreve era sgniht ynnuf\n");
fprintf(stream, "ssueS .rD - \n");
fclose(stream);
waitpid(pid, NULL, 0);
}
return 0;
}
产生输出:
From there to here,
and here to there,
funny things are everywhere.
- Dr. Seuss