以下代码 readTwice.c 从标准输入读取两次:
int main()
{
char s[8]={0};
read(0, (void *)s, (size_t) 3);
read(0, (void *)(s + 4), (size_t) 3);
for (int i = 0; i < 8; i++)
printf("%d: 0x%x\n", i, s[i]);
return 0;
}
我的目标是在调试相应的二进制文件时,为第一个read()提供第一个文件 a (例如,由echo a > a
创建),第二个read()并带有第二个文件 b (例如,由echo b > b
创建)。
在GDB外部,以下bash 5.0命令具有预期的效果:
$ ./readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x0
3: 0x0
4: 0x62
5: 0xa
6: 0x0
7: 0x0
但是,当在GDB 8.2.1中以相同的进程重定向运行二进制文件时,第一个read()调用也会读取第二个文件的开头:
$ gdb -q readTwice
Reading symbols from readTwice...(no debugging symbols found)...done.
(gdb) run < <(cat a;cat b)
Starting program: /home/av/root-me/ch77/readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x62
3: 0x0
4: 0xa
5: 0x0
6: 0x0
7: 0x0
[Inferior 1 (process 4710) exited normally]
(gdb)
您能帮助我理解此行为和/或告诉我有关具有预期效果的命令吗?
答案 0 :(得分:0)
程序输入包含4个字符:
'a' '\n' 'b' '\n'
在程序内部,您使用两个reads
:
read(0, (void *)s, (size_t) 3);
read(0, (void *)(s + 4), (size_t) 3);
read
不能完全读取 3
个字符。它最多读取3
个字符,并返回读取的字符数,请参阅man read(2)。我假设默认情况下STDIN_FILENO
在您的平台上处于阻止状态,因此它应读取至少1个字符。
可能的结果:
read
都读取1个字节。 s
将有{'a',0,0,0,'\n',0,0,0}
。输入中有2
个未读字节。read
读取1个字节,第二个读取3个字节。 s
将有{'a',0,0,0,'\n','b','\n',0}
read
读取3个字节,第二个读取1个字节。 s
将有{'a','\n','b',0,'\n',0,0,0}
。这是您在gdb
中观察到的输出。read
读取2个字节,第二个读取2个字节。 s
将有{'a','\n',0,0,'b','\n',0,0}
。这是您在shell中运行时观察到的输出。您的操作系统很可能在平台上以行缓冲方式在read
上实现了STDIN_FILENO
,因此,最有可能出现的两个结果就是您正在观察的结果。