C 读取(fd,buf,N>;0)=0,但fd不在EOF?
下面的小C程序(我们称之为无意义的): 显然,在除AIX之外的所有系统上,C 读取(fd,buf,N>;0)=0,但fd不在EOF?,c,posix,aix,rlwrap,C,Posix,Aix,Rlwrap,下面的小C程序(我们称之为无意义的): 显然,在除AIX之外的所有系统上,writeing 0字节 pty的从端是no-op,而在AIX上它会唤醒 在主机端选择()。写入0字节似乎毫无意义,但只有一个字节 我的一个测试程序写随机长度的文本块,这可能 实际上正好长度为0 在linux上,man 2 read声明“在成功时,读取的字节数为 返回(零表示文件结束)”(斜体是我的)此 问题是 没有提到这个场景 这就引出了一个问题:如何便携式地确定 从属端已关闭?(在这种情况下,我可能只能等待 然后关闭商
write
ing 0字节
pty的从端是no-op,而在AIX上它会唤醒
在主机端选择()。写入0字节似乎毫无意义,但只有一个字节
我的一个测试程序写随机长度的文本块,这可能
实际上正好长度为0
在linux上,man 2 read
声明“在成功时,读取的字节数为
返回(零表示文件结束)”(斜体是我的)此
问题是
没有提到这个场景
这就引出了一个问题:如何便携式地确定
从属端已关闭?(在这种情况下,我可能只能等待
然后关闭商店,但这可能会打开另一罐啤酒
(我宁愿避免虫子)
编辑:国家: 将零长度缓冲区(nbyte为0)写入STREAMS设备将发送0字节,返回0。但是,将零长度缓冲区写入基于流的管道或FIFO不会发送任何消息,返回0。该进程可能会发出I_SWROPT ioctl(),以允许通过管道或FIFO发送零长度消息 在AIX上,
pty
实际上是一个流设备,而且不是管道或FIFOioctl(STDOUT\u FILENO,I\u SWROPT,0)
似乎可以使pty与Unix世界的其他部分保持一致。悲哀的是,这必须从从从机端调用,因此在rlwrap
的影响范围之外(即使我们可以在fork()
和exec()
之间调用ioctl()
,这不能保证执行的命令不会将其更改回来)<
如果count为零且fd引用常规文件,则write()
如果出现以下错误之一,则可能返回故障状态
检测。如果未检测到错误,或未检测到错误
执行后,将返回0,而不会造成任何其他影响。
如果计数为零且fd引用的文件不是常规文件
文件中,未指定结果
因此,由于它是未指定的,因此它可以在您的情况下执行任何它喜欢的操作。:
尝试从空管道或FIFO读取时:
- 如果没有进程打开管道进行写入,read()将返回0以表示文件结束。“
nbyte
为零且文件为常规文件,则write()
函数可能会检测并返回如下所述的错误。如果没有错误,或者未执行错误检测,则write()函数
函数应返回零且无其他结果。如果nbyte
为零且文件不是常规文件,则结果未指定。
不幸的是,这意味着您不能以可移植的方式依赖于零字节的write()
,因为AIX符合POSIX标准中的write()
您可能必须依赖于
SIGCHLD
:“当尝试从空管道或FIFO读取时:如果没有进程打开管道进行写入,read()将返回0以指示文件结束。”因此“读取零字节意味着EOF是的,我也看到了。我的问题是:它声明如果在EOF,那么返回0。但它并没有说如果返回0,您可以假设EOF。然而,表示文件结尾的短语似乎暗示反蕴涵确实可以双向读取。出于好奇,您能否尝试在AIX上的无意义.c
的开头使用ioctl(STDOUT\u FILENO,I\u SWROPT,0)
,看看会发生什么?()@Sergey_Kalinichenko:好的。我有时间再试试…@Sergey_Kalinichenko:ioctl(STDOUT_FILENO,I_SWROPT,0)
成功了!当我在pointless的开头插入它时,c
rlwrap
不会从pselect()返回当pointless
执行0位写入时。我想我会在pty的从机端的fork()
和execute()
之间使用它。谢谢你的提示!理论上,客户端程序可以撤销ioctl()
,但是这个bug已经20多年没有被注意到了,所以解决方案不一定是完美的……您的IBM链接是针对z/OS的。是的。但在POSIX中,它的未定义行为是您所依赖的。因此,正如您所经历的,它可以在一种情况下工作,但在另一种情况下不能工作。z/OS链接声明“如果N为零,write()只返回0,而不尝试任何其他操作。”这不是AIX上发生的情况。未定义就是未定义。我删除了与IBM的链接,因为这只是为了表明您根据操作系统有不同的行为,因为它是未定义的”这是关键。不要使用nbytes==0
调用write
,除非您想处理这样做的未指定的、可能是特定于实现的后果。问题是,作为rlwrap
维护者,我遇到了使用nbytes=0
调用write
之类的程序。当然,我可以说这些程序做得不对,但它们存在,所以我必须处理它们……@HansLub可能会证明是有用的。
/* pointless.c */
#include <stdio.h>
#include <unistd.h>
void main(){
write(STDOUT_FILENO, "", 0); /* pointless write() of 0 bytes */
sleep(1);
write(STDOUT_FILENO, "still there!\n", 13);
}
/* master is the file descriptor of the master end of a pty, while the slave is 'pointless's stdout */
/* master was opened with O_NDELAY */
while(pselect(nfds, &readfds, .....)) {
if (FD_ISSET(master, &readfds)) { /* master is "ready" for reading */
nread = read(master, buf, BUFFSIZE - 1); /* so try to read a buffer's worth */
if (nread == 0) /* 0 bytes read... */
cleanup_and_exit(); /* ... usually means EOF, doens't it? */