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.
下面的示例代码执行,但是来自分叉进程的输出不可读:在我按enter之前,控制台上没有显示任何内容,然后显示“Read failed!”
The question is: why is that, and how can I interact with stdin
and stdout
from the fork()
'ed process?
问题是:为什么会这样,以及如何从fork()的ed过程与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;
}
Update:
更新:
Another example of strange behavior of IO streams:
另一个关于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
script:
的回声。sh脚本:
#!/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:
更新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...
解决方案是用vfork替换fork。我只是不知道为什么这个工作…
3 个解决方案
#1
2
I think you want wait(2)
. As in
我想你需要等一下。就像在
/* example1.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
int status;
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);
}
}
else
{
while (wait(&status) != pid);
}
return 0;
}
#2
1
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).
这是因为您的子进程现在处于孤立的进程组中,其中没有进程是shell的直接子进程(应该由该进程执行作业控制)。
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).
孤立的进程组:进程组,该进程组至少没有一个成员,该成员的父成员不在进程组中,而是在同一个会话中(~是shell的直接子节点)。
While the parent and child are both running, the situation is like this:
当父母和孩子都在跑步时,情况是这样的:
$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd
27177 27177 27177 32170 pts/6 Ss 00:00:00 | \_ /bin/bash
4706 4706 27177 27177 pts/6 S+ 00:00:00 | \_ ./ex1
4707 4706 27177 4706 pts/6 S+ 00:00:00 | \_ ./ex1
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.
过程组4706有两个过程,4706和4707。4706是27177的孩子,在同一个会议(27177),但是不同的进程组(27177):进程组4706的工作控制是shell处理的。
When the parent dies, the situation is like this:
当父母去世时,情况是这样的:
$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd
27177 27177 27177 32170 pts/6 Ss+ 00:00:00 | \_ /bin/bash
4664 4663 27177 1 pts/6 S 00:00:00 ./ex1
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()
and write()
get EIO
.
进程组4663中只有一个进程4664,它的父进程(init)不在同一个会话中。shell不能处理这个进程组的作业控制,因此,read()和write() get EIO。
#3
0
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:
如果您在UNIX/Linux上,当stdout进入控制台时,它是行缓冲的。也就是说,在你这样做之前,你不会看到任何输出:
fflush(stdout)
- 。fflush(stdout)
prinf("\n")
- prinf(“\ n”)
- stdout buffer overflows.
- stdout缓冲区溢出。
When stdout goes somewhere else (like pipe of file) it is fully-buffered, that is, printf("\n")
does not flush the buffer.
当stdout到达其他地方(比如文件管道)时,它是完全缓冲的,也就是说,printf(“\n”)不会刷新缓冲区。
#1
2
I think you want wait(2)
. As in
我想你需要等一下。就像在
/* example1.c */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
int status;
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);
}
}
else
{
while (wait(&status) != pid);
}
return 0;
}
#2
1
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).
这是因为您的子进程现在处于孤立的进程组中,其中没有进程是shell的直接子进程(应该由该进程执行作业控制)。
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).
孤立的进程组:进程组,该进程组至少没有一个成员,该成员的父成员不在进程组中,而是在同一个会话中(~是shell的直接子节点)。
While the parent and child are both running, the situation is like this:
当父母和孩子都在跑步时,情况是这样的:
$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd
27177 27177 27177 32170 pts/6 Ss 00:00:00 | \_ /bin/bash
4706 4706 27177 27177 pts/6 S+ 00:00:00 | \_ ./ex1
4707 4706 27177 4706 pts/6 S+ 00:00:00 | \_ ./ex1
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.
过程组4706有两个过程,4706和4707。4706是27177的孩子,在同一个会议(27177),但是不同的进程组(27177):进程组4706的工作控制是shell处理的。
When the parent dies, the situation is like this:
当父母去世时,情况是这样的:
$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd
27177 27177 27177 32170 pts/6 Ss+ 00:00:00 | \_ /bin/bash
4664 4663 27177 1 pts/6 S 00:00:00 ./ex1
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()
and write()
get EIO
.
进程组4663中只有一个进程4664,它的父进程(init)不在同一个会话中。shell不能处理这个进程组的作业控制,因此,read()和write() get EIO。
#3
0
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:
如果您在UNIX/Linux上,当stdout进入控制台时,它是行缓冲的。也就是说,在你这样做之前,你不会看到任何输出:
fflush(stdout)
- 。fflush(stdout)
prinf("\n")
- prinf(“\ n”)
- stdout buffer overflows.
- stdout缓冲区溢出。
When stdout goes somewhere else (like pipe of file) it is fully-buffered, that is, printf("\n")
does not flush the buffer.
当stdout到达其他地方(比如文件管道)时,它是完全缓冲的,也就是说,printf(“\n”)不会刷新缓冲区。