Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 读取(fd,buf,N>;0)=0,但fd不在EOF?_C_Posix_Aix_Rlwrap - Fatal编程技术网

C 读取(fd,buf,N>;0)=0,但fd不在EOF?

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声明“在成功时,读取的字节数为 返回(零表示文件结束)”(斜体是我的)此 问题是 没有提到这个场景 这就引出了一个问题:如何便携式地确定 从属端已关闭?(在这种情况下,我可能只能等待 然后关闭商

下面的小C程序(我们称之为无意义的):

显然,在除AIX之外的所有系统上,
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
实际上是一个流设备,而且不是管道或FIFO
ioctl(STDOUT\u FILENO,I\u SWROPT,0)
似乎可以使pty与Unix世界的其他部分保持一致。悲哀的是,这必须从从从机端调用,因此在
rlwrap
的影响范围之外(即使我们可以在
fork()
exec()
之间调用
ioctl()
,这不能保证执行的命令不会将其更改回来)

<

如果count为零且fd引用常规文件,则write() 如果出现以下错误之一,则可能返回故障状态 检测。如果未检测到错误,或未检测到错误 执行后,将返回0,而不会造成任何其他影响。 如果计数为零且fd引用的文件不是常规文件 文件中,未指定结果

因此,由于它是未指定的,因此它可以在您的情况下执行任何它喜欢的操作。

:

尝试从空管道或FIFO读取时:

  • 如果没有进程打开管道进行写入,read()将返回0以表示文件结束。“
因此,“读取零字节意味着EOF”符合POSIX

关于(加粗我的):

在执行下面描述的任何操作之前,如果
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?  */