交替使用 FILE 指针和文件描述符

interchangeably using FILE pointer and file descriptor

当我在 fileno() 给出的文件描述符上调用较低级别的函数 API 时,如 read/write,我如何确保 FILE* 文件描述符状态保持同步函数而不是调用 fread/fwrite。 我想到的场景是:

fp = fopen(...)
fd = fileno(fp)
read(...,fd)

在上述 read(...,fd) 之后,我希望 fp (FILE*) 在读取字节后正确定位。 ftellfeof 应该仍然指向正确的信息。

这个问题比你想象的要复杂:

基于 FILE* 的 API(例如 fread())使用内部缓冲区,并且根据您使用的 C 库(版本),您必须考虑...

  • ...fopen()可能已经将字节读入缓冲区,所以fp的文件指针是0,但是fd的文件指针是不是 0.

    这意味着在使用fd之前,您必须确保fdfp同步。

  • ...C 库可能假定 fd 的文件指针仅由基于 FILE 的调用修改。

    这意味着你必须在使用read()和调用任何基于FILE的函数之间恢复fd的文件指针。

因此以下代码可能有效:

fp = fopen(...)
fd = fileno(fp)
/* Remember file position of fd */
oldpos = lseek(fd, 0, SEEK_CUR);
/* Ensure file position of fd is in sync with fp */
lseek(fd, ftell(fp), SEEK_SET);
read(...,fd)
/* Get new file position of fd */
newpos = lseek(fd, 0, SEEK_CUR);
/* Restore old file position of fd */
lseek(fd, oldpos, SEEK_SET);
/* Keep fp in sync with fd */
fseek(fp, newpos, SEEK_SET);

(但是,不能保证此代码适用于每个存在的 C 库。)