其中,sync函数家族、fcntl,ioctl函数的原型如下:
#include
#include //for fcntl
#include //For ioctl
void sync(void);
int fsync(int fd);
int fdatasync(int fd);
int fcntl(int fd, int cmd, ... /* arg */ );
int ioctl(int fd,int request);
在Linux系统中,其内核都设有高速缓冲区来缓存硬盘IO内容以减轻物理硬盘的负担。但是,有时候我们需要信息即时写入硬盘,以防止突然断电造成的数据丢失。
所以,我们可以用以下函数刷新缓冲区:
sync();
注意,这个函数只是把所有修改过的块缓冲区排入写队列,排入之后立即返回,并不等待写操作完成。
fsync函数只对特定的文件描述符fd起作用,且等待写操作完成后才返回。
fdatasync函数类似于fsync,它与fsync的不同之处在于fdatasync只影响文件的数据部分,对于文件属性做出的更改,fdatasync不会保存,而fsync会保存。
fsync和fdatasync函数在执行成功时返回0,出错时返回-1.
fcntl函数常用来取得或者改变文件的属性。
fcntl的原型如下:
#include
int fcntl(int fd, int cmd, ... /* arg */ );
其中,参数cmd用于指定要对文件描述符执行的操作:
cmd参数 | 解释 |
---|---|
F_DUPFD | 复制一个已有的文件描述符 |
F_GETFD/F_SETFD | 取得或者设置文件描述符标志 |
F_GETFL/F_SETFL | 取得或者设置文件属性 |
F_GETOWN/F_SETOWN | 取得或者设置异步IO所有权 |
F_GETLK/F_SETLK | 取得或者设置记录锁 |
F_DUPFD 用于复制一个已有的文件描述符,新的文件描述符作为函数返回值返回,这个值是未打开文件的各文件描述符大于等于第三个参数值的最小值。新的文件描述符与旧的文件描述符共享同一套文件表项,但是,文件描述符标志是独立的。实际上,在上篇笔记介绍的dup函数实际上等效于fcntl函数调用:
dup(fd)
等效于
fcntl(fd,F_DUPFD,0)
F_GETFD、F_SETFD 用于获取或者设置文件描述符标志。目前只能只有一个文件描述符标志:FD_CLOEXEC.第三个参数在设置文件描述符时指定为要设置的文件描述符标志,
F_GETFL/F_SETFL 用于获取或者设置文件状态标志。
其中,F_GETFL 可用于获取以下文件状态标志:
O_RDONLY O_WRONLY O_RDWR
O_APPEND O_NONBLOCK
O_SYNC //等待写操作完成 (数据和属性)
O_DSYNC //等待写操作完成 (数据)
O_RSYNC //同步读和写
但是,当你需要获取3个访问标志(O_RDONLY O_WRONLY O_RDWR) 时你需要将函数返回值和掩码O_ACCMODE相与再与上述值比较。
F_SETFL:将参数设置为第三个参数的值(可以取为整型值)。可以更改的几个标志是:
O_ADDEND O_NONBLOCK O_SYNC O_DSYNC O_DSYNC O_RSYNC
下面给出了一个简单的使用fcntl的例子:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,int **argv){
int value;
if(argc!=2)
{
printf("Usage: %s \n" ,argv[0]);
exit(-1);
}
if((value=fcntl(atoi(argv[1]),F_GETFL,0))<0)
{
printf("FCNTL ERROR:%s\n",strerror(errno));
exit(-1);
}
switch(value & O_ACCMODE)
{
case O_RDONLY:
printf("ReadOnly");
break;
case O_WRONLY:
printf("WriteOnly");
break;
case O_RDWR:
printf("WriteAndRead");
break;
}
if( value & O_APPEND )
printf(" , append");
if( value & O_NONBLOCK )
printf(" , nonblocking");
if( value & O_SYNC )
printf(" ,SYNC ");
}