共计 1659 个字符,预计需要花费 5 分钟才能阅读完成。
3.13 函数 sync、fsync 和 fdatasync
传统的 UNIX 零碎实现在内核中设有缓冲区高速缓存或页高速缓存,大多数磁盘 I / O 都通过缓冲区进行。当向文件写入数据时,内核通常先将数据复制到缓冲区,而后排入队列,晚些时候再写入磁盘。这种形式被成为提早写。
通常,当内核须要重用缓冲区来寄存其余磁盘块数据时,它会把所有提早写数据块写入磁盘。为了保障磁盘上理论文件系统与缓冲区中内容的一致性,UNIX 零碎提供了 sync、fsync 和 fdatasync 三个函数。
#include <unistd.h>
int fsync(int fd);
int fdatasync(int fd); // 返回值:若胜利,返回 0;若出错,返回 -1
void sync(void);
sync 只是将所有批改过的块缓冲区排入写队列,而后就返回,它并不期待理论写磁盘操作完结。
通常,称为 update 的零碎守护过程周期性地调用(个别每隔 30 秒)sync 函数。这就保障了定期 flush 内核的块缓冲区。命令 sync 也调用 sync 函数。
fsync 函数只对有文件描述符 fd 指定的一个文件起作用,并且期待写磁盘操作完结才返回。fsync 可用于数据库这样的应用程序,这种应用程序须要确保批改过的块立刻写到磁盘上。
fdatasync 函数相似于 fsync,但它只影响文件的数据局部。而除数据外,fsync 还会同步更新文件的属性。
3.14 函数 fcntl
fcntl 函数能够扭转曾经关上文件的属性。
#include <fcntl.h>
int fcntl(int fd, int cmd, .../* int arg */); // 返回值:若胜利,则依赖于 cmd;若出错,返回 -1
在本节的各实例中,第 3 个参数总是一个整数,与下面所示的函数原型中的正文局部对应。然而在 14.3 节阐明记录锁时,第 3 个参数是指向一个构造的指针。
fcntl 函数有以下 5 种性能:
- 复制一个已有的描述符(cmd=F_DUPFD 或 FDUPFD_CLOEXEC)
- 获取 / 设置文件描述符标记(cmd=F_GETFD 或 F_SETFD)
- 获取 / 设置文件状态标记(cmd=F_GETFL 或 F_SETFL)
- 获取 / 设置异步 I / O 所有权(cmd=F_GETOWN 或 F_SETOWN)
- 获取 / 设置记录锁(cmd=F_GETLK、F_SETLK 或 F_SETLKW)
- F_DUPFD:复制文件描述符 fd/ 新文件描述符作为函数值返回。他是尚未关上的各描述符中大于或等于第 3 个参数值(取为整型值)中各值的最小值。新描述符与 fd 共享同一文件表项。然而,新描述符有它本人的一套文件描述符标记,其 FD_CLOEXEC 文件描述符标记被革除,这示意该描述符在 exec 时仍放弃无效。
- F_DUPFD_CLOEXEC:复制文件描述符,设置与新描述符关联的 FD_CLOEXEC 文件描述符标记的值,返回新文件描述符。
- F_GETFD:对应于 fd 的文件描述符标记作为函数值返回。以后只定义了一个文件描述符编制 FD_CLOEXEC。
- F_SETFD:对于 fd 设置文件描述符标记。新标记按第 3 个参数(取为整型值)设置。
- F_GETFL:对应于 fd 的文件状态标记作为函数值返回。
- F_SETFL:将文件状态标记设置为第 3 个参数的值(取为整型值)。能够更改的几个标记是 O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC 和 O_ASYNC。
- F_GETOWN:获取以后接管 SIGNO 和 SIGURG 信号的过程 ID 或过程组 ID。
- F_SETOWN:设置接管 SIGNO 和 SIGURG 信号的过程 ID 或过程组 ID。正的 arg 指定一个过程 ID,负的 arg 示意等于 arg 绝对值的一个过程组 ID。
fcntl 的返回值与命令无关。如果出错,所有的命令都返回 -1,如果胜利则返回某个其余值。下列 4 个命令有特定的返回值:F_DUPFD、F_GETFD、F_GETFL、和 F_GETOWN。第 1 个命令返回新的文件描述符,第 2 个和第 3 个命令返回响应的标记,最初一个命令返回一个整的过程 ID 或负的过程组 ID。