文件系统
一、sync/fsync/fdatasync
-
大多数磁盘I/O都通过缓冲进行,
写入文件其实只是写入缓冲区,直到缓冲区满,
才将其排入写队列。 -
延迟写降低了写操作的次数,提高了写操作的效率,
但可能导致磁盘文件与缓冲区数据不同步。 -
sync/fsync/fdatasync用于强制磁盘文件与缓冲区同步。
-
sync将所有被修改过的缓冲区排入写队列即返回,
不等待写磁盘操作完成。 -
fsync只针对一个文件,且直到写磁盘操作完成才返回。
-
fdatasync只同步文件数据,不同步文件属性。
#include <unistd.h> void sync (void); int fsync ( int fd ); 成功返回0,失败返回-1。 int fdatasync ( int fd );
成功返回0,失败返回-1。
二、fcntl
#include <fcntl.h>
int fcntl (
int fd, // 文件描述符
int cmd, // 操作指令
… // 可变参数,因操作指令而异
);
对fd文件执行cmd操作,某些操作需要提供参数。
- 常用形式
#include <fcntl.h>
int fcntl (int fd, int cmd);
int fcntl (int fd, int cmd, long arg);
成功返回值因cmd而异,失败返回-1。
cmd取值:
F_DUPFD - 复制fd为不小于arg的文件描述符。
若arg文件描述符已用,
该函数会选择比arg大的最小未用值,
而非如dup2函数那样关闭之。
范例:dup.c
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
int main(void){
int fd1=open("fdup1.txt",O_WRONLY|O_CREAT|O_TRUNC,0664) ;
if(fd1==-1){
perror("fopen");
return -1;
}
printf("fd1=%d\n",fd1);
int fd2=open("fdup2.txt",O_WRONLY|O_CREAT|O_TRUNC,0664) ;
if(fd2==-1){
perror("fopen");
return -1;
}
printf("fd2=%d\n",fd2);
int fd3=fcntl(fd1,F_DUPFD,fd2);
if(fd3==-1){
perror("fcntl");
return -1;
}
printf("fd3=%d\n",fd3);
const char* text="123";
if(write(fd1,text,strlen(text)*sizeof(text[0]))==-1){
perror("write");
return -1;
}
text="456";
if(write(fd2,text,strlen(text)*sizeof(text[0]))==-1){
perror("write");
return -1;
}
text="789";
if(write(fd3,text,strlen(text)*sizeof(text[0]))==-1){
perror("write");
return -1;
}
close(fd1);
close(fd2);
close(fd3);
return 0;
}
~/uc/day05$ gcc fdup.c
~/uc/day05$ ./a.out
fd1=3
fd2=4
fd3=5
~/uc/day05$ cat fdup1.txt
123789~/uc/day05$ cat fdup2.txt
456~/uc/day05$
F_GETFD - 获取文件描述符标志。
F_SETFD - 设置文件描述符标志。
目前仅定义了一个文件描述符标志位FD_CLOEXEC:
0 - 在通过execve()函数所创建的进程中,
该文件描述符依然保持打开。
1 - 在通过execve()函数所创建的进程中,
该文件描述符将被关闭。
F_GETFL - 获取文件状态标志。
不能获取O_CREAT/O_EXCL/O_TRUNC。
F_SETFL - 追加文件状态标志。
只能追加O_APPEND/O_NONBLOCK。
范例:flags.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
void pflags (int flags) {
printf ("文件状态标志(%08X):", flags);
struct {
int flag;
const char* desc;
} flist[] = {
{O_RDONLY, "O_RDONLY"}, // 1000 0000 0000 0000 0
{O_WRONLY, "O_WRONLY"}, // 0100 0000 0000 0000 0
{O_RDWR, "O_RDWR"}, // 0010 0000 0000 0000 0
{O_APPEND, "O_APPEND"}, // 0001 0000 0000 0000 0
{O_CREAT, "O_CREAT"}, // 0000 1000 0000 0000 0
{O_EXCL, "O_EXCL"}, // 0000 0100 0000 0000 0
{O_TRUNC, "O_TRUNC"}, // 0000 0010 0000 0000 0
{O_NOCTTY, "O_NOCTTY"},
{O_NONBLOCK, "O_NONBLOCK"},
{O_SYNC, "O_SYNC"},
{O_DSYNC, "O_DSYNC"},
{O_RSYNC, "O_RSYNC"},
{O_ASYNC, "O_ASYNC"}
};
size_t i;
int first = 1; //标志是否为第一个 要不要打 ”|“
for (i = 0; i<sizeof(flist)/sizeof(flist[0]); ++i)
if (flags & flist[i].flag) {
printf ("%s%s", first ? "" : " | ",
flist[i].desc);
first = 0;
}
printf ("\n");
}
int main (void) {
int fd = open ("flags.txt",
O_WRONLY | O_CREAT | O_TRUNC | O_ASYNC, 0664);
if (fd == -1) {
perror ("open");
return -1;
}
int flags = fcntl (fd, F_GETFL);
if (flags == -1) {
perror ("fcntl");
return -1;
}
pflags (flags); // 不能获取O_CREATE/O_EXCL/O_TRUNC
if