1,延迟写
传统的UNIX系统实现在内核都设有缓冲区【高速缓存、页高速缓存】,大多数磁盘IO都是通过缓冲区进行。当我们向文件写入数据时,内核通常先将数据复制到缓冲区中,然后排入队列,晚些时候在写入磁盘。这种方式称为延迟写。
为保证磁盘实际内容,与缓冲区的内容一致性,unix系统提供了sync、fsync、fdatasync函数
2,函数
#include <unistd.h>
void sync();
int fsync(int fd);
int fdatasync(int fd);
return:
0:success
-1: ERROR
sync() :只是将修改过的块缓冲区排入队列,然后返回,不等待实际的write磁盘操作结束,排入队列后,update守护进程每隔30s进行flush缓冲区,写磁盘。
fsync():只对由文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束后返回。
fdatasync():类似于fsync函数,但是只影响文件的数据部分,而除数据外,fsync还会同时更新文件的属性。
3、fcntl()函数
int fcntl(int fd, int cmd, /*int arg*/);
功能:改变打开文件的属性
复制一个已有的描述符 cmd = F_DUPFD / F_DUPFD_CLOEXEC
获取、设置 文件描述符标志 cmd = F_GETFD / F_SETFD
获取、设置文件状态标志 cmd = F_GETFL / F_SETFL
获取异步I/O所有权 cmd = F_GETOWN / F_SETOWN
获取、设置记录锁 cmd = F_GETLK / F_SETLK
解释各选项:
F_DUPFD:
赋值文件描述符,新文件描述符作为函数返回值(最小且未打开的文件描述符值),他们共享同一个文件表项,但 新描述符有一套自己的文件描述符标志,其FD_CLOEXEC标志被清除
F_GETFD:
获取fd文件描述符标志
F_GETFL :
获取fd的文件状态标志(O_RDONLY、O_RWONLY、O_RDWR、O_APPREN、O_SYNC、O_NONBLOCK等)
F_GETOWN:
获取但却接收SIGIO和SIGURG信号的进程ID
fcntl 返回值跟cmd有关:
如果出错,返回:-1
F_DUPFD:换回一个新的文件描述符
FD_GETFD、FD_GETFL:返回相应的fd标志
FD_GETOWN :返回一个进程ID
实例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//测试文件描述符状态标志
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("./a,out fd");
return -1;
}
int val = fcntl( atoi(argv[1]), F_GETFL, 0 );
if(val < 0)
{
perror("fcntl:");
return -1;
}
switch(val & O_ACCMODE)
{
case O_RDONLY:
printf("Read\n");
break;
case O_WRONLY:
printf("Write\n");
break;
case O_RDWR:
printf("Read_Write\n");
break;
default:
printf("GET FL is error\n");
break;
}
if(val & O_APPEND)
printf("Apprend.");
if(val & O_NONBLOCK)
printf("NonbLock.");
if(val & O_SYNC)
printf("SYNC");
printf("\n");
return 0;
}
注:
当使用F_SETFL时,不能去修改一个文件的打开方式(O_RDONLY/O_WRONLY/O_RDWR),如下部分代码:
//只读打开
int fd = open("./1.txt",O_RDONLY);
if(fd < 0)
{
printf("open is error\n");
return -1;
}
//get fd stat
int val= fcntl( fd, F_GETFL, 0);
if(val > 0)
{
val |= O_RDWR;
fcntl(fd, F_SETFL, val);
perror("fcntl_1:");
}
//尝试写文件
if( 0 > write(fd ,"AAAAAAA", 7))
{
perror("write :");
return -1;
}
结果:
fcntl_1:: Success
write:: Bad file descriptor
(前面以为是自己SET状态时出错,后面尝试将文件打开方式改为O_RDWR,write函数成功写入)