Linux 文件操作总结(2)
fcntl 函数
作用
操作文件描述符。
接口原型
#include<unistd.h>
#include<fcntl.h>
int fcntl(intfd, int cmd, ... /* arg */ );
功能
f c n t l函数有五种功能:
• 复制一个现存的描述符(c m d=F _ D U P F D)。
• 获得/设置文件描述符标记(c m d = F _ G E T F D或F _ S E T F D)。
• 获得/设置文件状态标志(c m d = F _ G E T F L或F _ S E T F L)。
• 获得/设置异步I / O有权(c m d = F _ G E TO W N或F _ S E TO W N)。
• 获得/设置记录锁(c m d = F _ G E T L K , F _ S E T L K或F _ S E T L K W)。
修改文件描述符
在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现在的标志值,然后按照希望修改它,最后设置新标志值。
O_RDONLY
O_WRONLY
O_RDWR
-----------------------------------------------------------
O_APPEND
O_NONBLOCK
O_SYNC
O_ASYNC
其中,O_RDONLY、O_WRONLY、O_RDWR 。这三种值互斥,一个文件只能有这三种值之一。并且他们这三种标志的值各是 0、1和2。
O_APPEND 、O_NONBLOCK 、O_SYNC 、O_ASYNC 可以按位设置启用关闭状态。
include "apue.h"
#include <fcntl.h>
void set_fl(int fd, int flags,int state) /*flags are file status flags to turn on */
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
err_sys("fcntl F_GETFLerror");
if(state == 0){
val &= ~flags /*turn off flags*/
}else if(state== 1){
val |= flags; /* turn on flags */
}
if (fcntl(fd, F_SETFL, val) < 0)
err_sys("fcntl F_SETFLerror");
}
往文件写数据时相关的缓存问题
LINUX在内核中设有缓冲存储器,大多数磁盘 I / O 都通 过 缓 存 进 行 。
当 将 数 据 写 到文件上时,通常该数据先由内核复制到缓存中,如果该缓存尚未写满,则并不将其排入输出队列,而是等待其写满或者当内核需要重用该缓存以便存放其他磁盘块数据时,再将该缓存排入输出队列,然后待其到达队首时,才进行实际的 I / O 操作 。 这 种 输 出 方 式 被 称 之 为 延 迟 写 ( d e l a y e d w ri t e )。
延 迟 写 减 少 了 磁 盘 读 写 次 数 , 但 是却降低了文件内容的更新速度 。
了保证磁盘上实际文件系统与缓 存中内容的一致性, LINUX系统提供了 s y n c和f s y n c 两个 系 统 调 用 函 数 和O_SYNC 标志位。
s y n c 只是将所有修改过的块的缓存排入写队列,然后就返回,它并不等待实际 I / O 操作结束。
函数 f s y n c 只引用单个文件 ( 由文件描述符 f i l e d e s指定 ),它等待 I / O 结束,然后返回。
O _ S Y N C ,则每次对文件调用 w r i t e 函数时就更新文件的内容。
测试代码:
#include "apue.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFSIZE 4096
int main(void)
{
int n;
int fd = open("./message",O_RDWR);
int fd2 = open("./test",O_WRONLY/*|O_SYNC*/);// 方法一
char buf[BUFFSIZE];
while ((n = read(fd, buf, BUFFSIZE)) > 0)
if (write(fd2, buf, n) != n)
err_sys("writeerror");
if (n < 0)
err_sys("readerror");
//fsync(fd2); //方法二
//sync(); //方法三
close(fd);
close(fd2);
exit(0);
}
运行时间排序:
time( O_SYNC) > time (fsync) >time(sync)
大家可以自己动手测试。