c-FILE对象的只读缓冲日期



我想只读取FILE对象的缓冲区中已经存在的内容,这样之后缓冲区就会为空(我可以使用sendfile之类的对文件描述符进行操作的东西)。我想出了这个功能,它似乎适用于我的64位Linux安装:

int readbuf(FILE *stream, char buf[], size_t *size) {
    off_t pos = ftello(stream);
    if (pos < 0) return -1;
    off_t realpos = lseek(fileno(stream), 0, SEEK_CUR);
    if (realpos < 0) return -1;
    if (pos > realpos) {
        errno = EIO;
        return -1;
    }
    size_t bufsize = realpos - pos;
    if (bufsize > *size) {
        *size = bufsize;
        errno = ERANGE;
        return -1;
    }
    *size = bufsize;
    if (fread(buf, bufsize, 1, stream) < 1) {
        return -1;
    }
    return 0;
}

现在我想知道,我能假设这在其他符合POSIX的操作系统上工作吗?(在提供所有相关功能的系统上。)

如果底层文件描述符是可查找的(要么是常规文件,要么是块设备,除非你的系统上有其他奇怪的可查找对象…),那么你尝试做什么就没有意义了。只需使用ftello来获取FILE中的逻辑位置,然后丢弃FILE并使用sendfile。无论如何,在用户空间中使用已经缓冲的数据实际上比sendfile慢。

如果底层文件描述符不可查找,则整个方法不起作用,因为lseek将始终返回-1,而ftello将返回EOF。这种情况下的潜在解决方案:

  • 使用dup创建一个新的文件描述符,引用相同的打开文件描述
  • 仅打开/dev/null写入,dup2位于FILE使用的旧文件描述符编号之上
  • FILE读取将成功,直到缓冲区耗尽,然后给出读取错误,因为文件描述符现在指的是不可读的文件
  • 在这一点上,您可以直接从第一步中复制的fd中进行读取。您还可以自由使用fcloseFILE

对于Unix平台上的可查找文件,您应该能够使用fflush()来协调基于fd的使用和基于FILE*的使用,包括读取。详细信息见http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01和http://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html.

这是对标准C的扩展(不足为奇)。

我不相信stdio API能保证这在任何系统上都能工作。例如,如果注意到缓冲区为空,它可能会执行预读。

你的"解决方案"至多是一个特定的实现破解。

相关内容

  • 没有找到相关文章

最新更新