首先,不要将标准库<stdio.h>
调用(如fprintf(3)
or fopen(3)
)与系统调用(如open(2)
orclose(2)
或sync(2)
)混为一谈,因为前者是库例程,它们使用进程内缓冲区来存储系统不知道的临时数据,而其他是操作系统接口,使系统从现在开始负责数据维护。您将很容易区分它们,因为前者使用FILE *
描述符进行操作,而最后使用int
整数描述符进行操作。
因此,如果您使用系统调用来确保您的数据正确同步到磁盘,则绝对有必要fflush(3)
sync(2)
在执行文件系统或fsync(2)
调用 之前首先处理进程的缓冲区数据。
不sync(2)
保证在时间fclose(3)
或什至close(2)
准时发生,或者在atexit()
您的进程之前执行的回调中发生exit()
。
出于性能原因,操作系统缓冲区被延迟写入,并且close(2)
不是使其触发此类事件的事件。试想一下,许多进程可以同时读取和写入同一个文件,并且每个close(2)
触发文件系统刷新都可能很难实现。操作系统会定期、umount(2)
系统调用、系统关闭以及对系统调用的特定调用sync(2)
触发此类fsync(2)
调用。
如果您需要保持FILE *fd
描述符打开,只需fflush(fd)
对该描述符执行 a 以确保操作系统首先拥有所有用于fwrite(3)
d 或fprintf(3)
ed 数据的缓冲区。
所以最后,如果您使用<stdio.h>
函数,首先对您写入fflush()
的所有描述符执行 a ,或者调用以告诉 stdio 在一次调用中同步所有描述符。然后执行or调用以确保您的所有数据物理上都在磁盘上。无需关闭任何东西。FILE *
fflush(NULL);
sync(2)
fsync(2)
FILE *fd;
...
fflush(fd);
fsync(fileno(fd));
/* here you know that up to the last write(2) or fwrite(3)...
* data is synced to disk */
顺便说一句,您/dev/fd/<number>
获取描述符的方法(您以前有过)是错误的,原因有两个:
一旦你关闭你的描述符,/dev/fd/<number>
就不再是你想要的描述符了。通常,它甚至不存在。试试这个:
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main()
{
int fd;
char fn[] = "/dev/fd/1";
close(1); /* close standard output */
fd = open(fn, O_RDONLY); /* try to reopen from /dev/fd */
if (fd < 0) {
fprintf(stderr,
"%s: %s(errno=%d)\n",
fn,
strerror(errno),
errno);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} /* main */
您无法仅使用文件描述符获取打开文件所属的目录。在多链接文件中,可能有数千个目录指向它。inode(或打开的文件结构)上没有任何内容可让您获取用于打开该文件的路径。使用临时文件的一种常见方法是创建它们并立即创建它们unlink(2)
,因此没有人可以再次打开它。只要您保持文件打开,您就可以访问它,但不再有指向它的路径。