我正在玩系统功能和文件重写,发现了一个我不太懂的奇怪行为。
我有一个第一个进程,它读取stdin,然后在另一个也读取stdin的进程上调用fork(调用系统函数)。
在第一种情况下,我不会将任何内容重定向到第一个流程' stdin,一切都按预期工作,两个进程都从我的提示中读取。
但在第二种情况下,我将文件管道或重定向到第一个进程,分叉进程开始读取"随机"数据
以下是我的模拟示例:
fork.c
#include <stdlib.h>
#include <stdio.h>
int main() {
char buf[10];
fgets(buf,10,stdin);
printf("Buff: %s\n", buf);
system("./print");
fgets(buf,10,stdin);
printf("Buff: %s\n", buf);
return 0;
}
print.c
#include <stdlib.h>
#include <stdio.h>
int main() {
char buf[10];
fgets(buf,10,stdin);
printf("Buff: %s\n", buf);
}
如果我跑
echo "just another awesome input" | ./fork
我得到了
Buff: just anot
Buff: Ðhuÿ
Buff: her aweso
对于孩子来说,输入总是不同的(我猜它是在内存中读取一些随机位置......)。
任何人都可以解释这种行为吗?我知道孩子在fork处继承了文件描述符,但我不明白为什么它只能读取与父级相同的输入,或者至少是确定性的。
我想知道在调用我的fork程序时是否有诀窍说我想要&#34; fork&#34;有这个输入,它的孩子是另一个输入。
答案 0 :(得分:1)
您应该查看子进程中fgets()
返回的错误状态,并在fgets()
报告时报告EOF。
父进程从管道中读取了一个充满信息的缓冲区,并以9个字符+空字节为增量进行处理。由于信息已经从管道消失,孩子无法读取任何内容并报告EOF。父级继续使用缓冲输入中的材料。
始终检查I / O调用(尤其是输入调用)是否成功。
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char buf[10];
if (fgets(buf,10,stdin) != 0)
printf("Buff-1: %s\n", buf);
else
printf("Buff-1: EOF detected\n");
system("./print");
if (fgets(buf,10,stdin) != 0)
printf("Buff-2: %s\n", buf);
else
printf("Buff-2: EOF detected\n");
return 0;
}
#include <stdio.h>
int main(void)
{
char buf[10];
if (fgets(buf,10,stdin) != 0)
printf("Buff-C: %s\n", buf);
else
printf("Buff-C: <<EOF>>\n");
return 0;
}
在第一次运行中,我在键盘上输入了输入。打印'similitud'后,系统似乎挂起,所以我输入'杂项',并且子进程报告'miscellan'(并且可能已经报告'eous'继续阅读)。与此同时,父流程继续报告来自'ude'行的数据。
在第二个示例中,正如预测的那样,子进程报告了EOF,因为父进程已在其第一个输入操作中读取了管道中的所有数据。
$ ./fork
similitude and gratitude and attitude and longitude, dude!
Buff-1: similitud
miscellaneous
Buff-C: miscellan
Buff-2: e and gra
$ echo "just another awesome input" | ./fork
Buff-1: just anot
Buff-C: <<EOF>>
Buff-2: her aweso
$
答案 1 :(得分:0)
完成乔纳森的回答。
孩子确实收到了EOF。原因是父母正在阅读的不只是fgets请求。 Strace显示父级读取4096字节的块。 因此,如果您想将一些数据直接传递给子进程,您只需要在4096个第一个字节之后写入。
E.g。
$ python -c 'print "0*4096"+"123"' | ./fork
Buff: 0000000000
Buff: 123
Buff: 0000000000
另一个有趣的方法是使用cat从提示中读取。
$ (echo "once upon a time";cat) | ./fork
Buff: once upon
test <-- I am prompted here
Buff: test
Buff: a time