加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux读取sys调用不会得到EOF

发布时间:2020-12-13 22:58:35 所属栏目:Linux 来源:网络整理
导读:首先抱歉,如果我的英语不流利和清晰. 我正在努力理解流程之间的管道和通信.我试图实现两个c程序,一个从他从标准输入读取的内容写入某个管道,另一个等待直到管道打开并从中读取并打印到标准输出直到EOF. 以下是编写器管道的代码: fd = open(filename,O_RDWR)
首先抱歉,如果我的英语不流利和清晰.

我正在努力理解流程之间的管道和通信.我试图实现两个c程序,一个从他从标准输入读取的内容写入某个管道,另一个等待直到管道打开并从中读取并打印到标准输出直到EOF.

以下是编写器管道的代码:

fd = open(filename,O_RDWR);
  if(fd == -1) print_error();

  while(fgets(buffer,BUFFER_SIZE,stdin) != NULL) {
    if(write(fd,buffer,BUFFER_SIZE) == -1) print_error();
  }

这是读者管道的代码:

while(1) {
    if((fd = open(filename,O_RDWR)) == -1) {
      if(errno == ENOENT) sleep(1);
      else print_error();
    }
    else {
      while(read(fd,BUFFER_SIZE) != 0) {
        fprintf(stdout,"%s",buffer);
      }
    }
  }

问题在于,当我同时运行这两个程序时,基本概念有效,我在编写器程序中向标准输入写了一些东西,我在另一个终端中看到读取器程序将它打印到标准输出.问题是,当我通过按CTRL D为编写器程序发送EOF时,读取器程序仍然等待输入,我确定它不是因为while(1),我在调试器中看到了读取系统调用只是等待输入并且不明白我们得到了EOF,行:read(fd,BUFFER_SIZE)即使没有输入也没有评估.

我希望我提供解决问题所需的所有数据,任何人都有任何想法出了什么问题?

解决方法

如果fgets()检测到EOF,它将返回其读缓冲区中已有的内容或仅返回NULL.

在后一种情况下,您希望通过例如关闭管道来通知读取端传输已结束.

int fd = open(filename,O_RDWR);
  if (fd == -1) 
  {
    perror("open() failed");
  }
  else
  {    
    while (fgets(buffer,stdin) != NULL) 
    {
      if (write(fd,BUFFER_SIZE) == -1) 
      {
        perror("write() failed");
        break;
      }
    }
    if (ferror(stdin))
    {
       perror("fgets() failed");
    }

    close(fd); /* The other end's blocking call to read() would return 0. */
  }

在任何情况下都不会读取类似EOF的内容. EOF不是一个角色,而是一个国家.

man 3 read开始:

If some process has the pipe open for writing […] read() shall block the calling thread until some data is written or the pipe is closed by all processes that had the pipe
open for writing.

此代码也不包括read()失败:

while(read(fd,BUFFER_SIZE) != 0) {
    fprintf(stdout,buffer);
  }

它应该看起来像这样的例子:

ssize_t result;
  while (0 != (result = read(fd,BUFFER_SIZE))) 
  {
    if (0 > result)
    {
      if ((EINTR == errno) || (EAGAIN == errno)) 
      {
        continue;
      }

      perror("read() failed");
      break;
    }

    fprintf(stdout,buffer);
  }

更多这个循环……

while(1) {
  if((fd = open(filename,O_RDWR)) == -1) {
    if(errno == ENOENT) sleep(1);
    else print_error();
  }
  ...
}

…错过关闭()fd,然后(重新)打开它.

如果读者不写,则通过指定O_RDONLY而不是RDWR来打开管道.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读