c/c++ 复习笔记 第六天 文件系统

本文详细介绍了C/C++中关于文件系统的操作,包括sync、fsync、fdatasync等函数用于同步缓冲区与磁盘数据,fcntl用于文件描述符管理,以及文件锁、stat/fstat/lstat获取文件属性,access测试访问权限,umask设置文件权限屏蔽字,chmod/fchmod修改文件权限,chown/fchown/lchown更改文件属主和属组,以及文件长度的修改、文件和目录的链接、删除、重命名等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件系统

一、sync/fsync/fdatasync

  1. 大多数磁盘I/O都通过缓冲进行,
    写入文件其实只是写入缓冲区,直到缓冲区满,
    才将其排入写队列。

  2. 延迟写降低了写操作的次数,提高了写操作的效率,
    但可能导致磁盘文件与缓冲区数据不同步。

  3. sync/fsync/fdatasync用于强制磁盘文件与缓冲区同步。

  4. sync将所有被修改过的缓冲区排入写队列即返回,
    不等待写磁盘操作完成。

  5. fsync只针对一个文件,且直到写磁盘操作完成才返回。

  6. 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操作,某些操作需要提供参数。

  1. 常用形式

#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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值