fork() 进程中的 IO 流
执行以下示例代码,但分叉进程的输出不可读:控制台上不会显示任何内容,直到我按 Enter 键,然后“读取失败!”显示。
问题是:为什么会这样,以及如何与 fork()
进程中的 stdin
和 stdout
进行交互?
/* example1.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = fork();
if (!pid) {
// child
char s[64];
printf("Enter something: ");
char *res = fgets(s, 64, stdin);
if (!res) {
printf("Read failed!\n");
} else {
printf("You entered: %s", s);
}
}
return 0;
}
更新:
IO 流奇怪行为的另一个示例:
/* example2.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = fork();
if (!pid) {
// child
char *argv[] = {
"-c",
"/home/user/echo.sh",
NULL
};
execv("/bin/sh", argv);
}
return 0;
}
echo.sh
脚本:
#!/bin/sh
read -p "Enter something: " INPUT
echo "You entered $INPUT"
此脚本返回
Enter something: /home/user/echo.sh: line 3: read: read error: 0: Input/output error
You entered
更新 2:
看起来这段代码的作用正是如此需要:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = vfork();
if (!pid) {
// child
system("/home/user/echo.sh");
}
return 0;
}
解决方案是用 vfork
替换 fork
。我只是不知道为什么这个会起作用......
The following example code executes, but output from the forked process is not readable: nothing is shown on console until I press enter, and then "Read failed!" shows.
The question is: why is that, and how can I interact with stdin
and stdout
from the fork()
'ed process?
/* example1.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = fork();
if (!pid) {
// child
char s[64];
printf("Enter something: ");
char *res = fgets(s, 64, stdin);
if (!res) {
printf("Read failed!\n");
} else {
printf("You entered: %s", s);
}
}
return 0;
}
Update:
Another example of strange behavior of IO streams:
/* example2.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = fork();
if (!pid) {
// child
char *argv[] = {
"-c",
"/home/user/echo.sh",
NULL
};
execv("/bin/sh", argv);
}
return 0;
}
echo.sh
script:
#!/bin/sh
read -p "Enter something: " INPUT
echo "You entered $INPUT"
This one returns
Enter something: /home/user/echo.sh: line 3: read: read error: 0: Input/output error
You entered
Update 2:
Looks like this code does exactly what's needed:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
pid_t pid = vfork();
if (!pid) {
// child
system("/home/user/echo.sh");
}
return 0;
}
The solution was to replace fork
with vfork
. I just don't know why is this one working...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为您需要
wait(2)
。如在I think you want
wait(2)
. As in这是因为您的子进程现在位于孤立进程组中,其中没有进程是 shell(应该执行作业控制)的直接子进程。
孤立进程组:至少没有一个成员的进程组其父进程不在该进程组中但位于同一会话中(~是外壳)。
当父进程和子进程都在运行时,情况是这样的:
进程组4706上有两个进程,4706和4707。4706是27177的子进程,它在同一个会话(27177)中,但是不同的进程组( 27177):它是处理进程组4706的作业控制的shell。
当父进程死亡时,情况是这样的:
只有一个进程组 4663 中的进程 4664 及其父进程 (init) 不在同一会话中。 shell 无法处理此进程组的作业控制,因此
read()
和write()
获取EIO
。This is because your child process is now in an orphaned process group, where no process is a direct child of the shell (who is supposed to do job-control).
Orphaned process group: Process group which doesn't have at least a member who has a parent not in the process group but within the same session (~ is a direct child of the shell).
While the parent and child are both running, the situation is like this:
There are two processes, 4706 and 4707 on process group 4706. 4706 is a child of 27177, which is in the same session (27177), but different process group (27177): it's the shell that deals with job control for process group 4706.
When the parent dies, the situation is like this:
There is only one process, 4664, in process group 4663, and its parent (init) isn't on the same session. The shell cannot deal with job control for this process group, therefore,
read()
andwrite()
getEIO
.如果您使用的是 UNIX/Linux,当 stdout 进入控制台时,它是行缓冲的。也就是说,除非执行以下任一操作,否则您看不到任何输出:
fflush(stdout)
prinf("\n")
当 stdout 到达其他地方(例如文件管道)时,它是完全缓冲的,即 printf("\n") 不会刷新缓冲区。
If you are on UNIX/Linux, when stdout goes into console it is line-buffered. That is, you don't see any output until you do either:
fflush(stdout)
prinf("\n")
When stdout goes somewhere else (like pipe of file) it is fully-buffered, that is,
printf("\n")
does not flush the buffer.