我有一个简短的C程序,输出3行,然后从标准输入读取。我想使用以下shell脚本与其交互:
使用添加了
- 逐行读取c输出:
while read line; do ...; done <$out_
- 保存第二行:
if [ "$count" == 2 ]; then input=$line; fi
- 将保存的行发送回程序:
echo $input >$in_
./iotest >$out_ <$in_ &
但是我没有得到预期的结果。
问题
使用mkfifo
创建管道out_
和in_
后,我使用while read
循环,但似乎导致死锁。读取不到任何内容,shell脚本在读取命令上陷入了困境。
我尝试在启动iotest
之前添加cat >$in_ &
,如此处所述,打开写入in_
而不实际写入任何内容。这解除了阻塞,但我无法将输入写入in_
(我的C程序好像已经将\x00写入stdin,echo $input >$in_
命令挂起了)。
我尝试过的方法
在这里我读到如果没有写入者,读取会被阻塞,而没有cat >$in_ &
时,iotest
会写入out_
,而read
从中读取,我试图将in_
重定向到iotest
,并从一开始就不写任何内容。
但是为什么添加cat命令会使C程序在读取时失败,我不知道。如果我用while true; do :; done >$in_&
或exec 3>$in_ &
(如此处所述)交换cat >$in_ &
,也会出现相同的情况。
代码
这是我的C代码:
$ cat iotest.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main (int argc, char* argv[])
{
char A[9] = "";
printf("hello. please send me the following line:\n");
printf("input me\n");
printf("now send me the line:\n");
int ret = read(0,A,8);
fprintf(stderr,"read returned %i\n",ret);
if(ret != -1) {
printf("You sent: %s\n", A);
if (strcmp(A,"input me") == 0) {
printf("correct!\n");
} else {
printf("wrong line.\n");
}
} else {
printf("read failed.\n");
}
return 0;
}
这是我测试过的shell脚本:
$ cat runiotest.sh
#!/bin/bash
in_=/tmp/testpipein
out_=/tmp/testpipeout
mkfifo $in_
mkfifo $out_
count=0
input=""
./iotest >$out_ <$in_ &
while read line
do
count=$((count+1))
echo "line number $count:"
echo $line
if [ "$count" == 2 ]
then
input=$line
fi
if [ "$count" == 3 ]
then
echo "$input" >$in_
fi
done < $out_
rm -f $in_
rm -f $out_
我已在32位Debian和64位Ubuntu上使用gcc进行编译,并使用bash执行shell脚本进行了测试。
结果
没有添加cat命令的情况下:
$ /bin/bash/ ./runiotest.sh
(hangs)
使用添加了
cat >$in_ &
的命令:$ /bin/bash ./runiotest.sh
read returned 0
line number 1:
hello. please send me the following line:
line number 2:
input me
line number 3:
now send me the line:
line number 4:
You sent:
line number 5:
wrong line.
摘要
我的问题是:我的shell脚本有什么问题,我该如何修改它以读取并写入我的c程序?我不能更改c代码本身,但可以调整shell脚本。
非常感谢您的帮助!
strace -f
下运行脚本(请参阅手册以获取输出选项等)。看到哪个进程在哪个文件描述符上阻塞真的很有帮助。 - Uselesscat > $in_ &
,但使用runiotest.sh <&-
执行脚本,则cat
将立即终止,并且iotest
中的读取将返回0。(由于这里存在很多竞争条件取决于进程执行的顺序,因此将“将”改为“可能”) - William Pursell