跳转至

文件系统机制


POSIX 文件系统与目录机制总结


一、文件系统核心机制

  1. 树状目录结构
  2. 根目录:以 / 为起点,所有文件和目录形成层次化树状结构。
  3. 路径表示
    • 绝对路径:从根目录开始(如 /home/user/file.txt)。
    • 相对路径:从当前工作目录(CWD)开始(如 ../documents/)。
  4. 特殊目录

    • .:当前目录。
    • ..:父目录。
  5. 文件类型
    POSIX 定义多种文件类型,可通过 stat()st_mode 字段判断:

类型 标识宏 说明
普通文件 S_ISREG() 文本、二进制等常规数据文件。
目录 S_ISDIR() 包含其他文件或子目录的容器。
符号链接 S_ISLNK() 指向其他文件路径的快捷方式。
字符设备/块设备 S_ISCHR()/S_ISBLK() 硬件设备抽象(如终端、磁盘)。
FIFO(命名管道) S_ISFIFO() 进程间通信的先进先出队列。
套接字 S_ISSOCK() 网络或进程间通信的端点。
  1. Inode 元数据
    • 唯一标识:每个文件对应一个 inode,存储元信息(权限、大小、时间戳等)。
    • 获取方式:通过 stat()fstat()lstat() 获取 struct stat 结构体。
    • 关键字段
      struct stat {
          ino_t st_ino;     // Inode 编号
          mode_t st_mode;    // 文件类型和权限
          nlink_t st_nlink; // 硬链接数
          uid_t st_uid;     // 所有者用户 ID
          gid_t st_gid;     // 所有者组 ID
          off_t st_size;     // 文件大小(字节)
          time_t st_mtime;  // 最后修改时间
          // ...
      };
      

二、目录操作机制

  1. 目录遍历

    • 核心函数
      • DIR *opendir(const char *name):打开目录,返回目录流指针。
      • struct dirent *readdir(DIR *dirp):读取目录项,返回 dirent 结构体。
        struct dirent {
            ino_t d_ino;       // Inode 编号
            char d_name[256];  // 文件名
            // ...
        };
        
      • closedir(DIR *dirp):关闭目录流。
    • 示例:递归遍历目录树需自行实现(结合 S_ISDIR 判断子目录)。
  2. 目录创建与删除

    • int mkdir(const char *pathname, mode_t mode):创建目录,权限由 mode 指定(受 umask 影响)。
    • int rmdir(const char *pathname):删除空目录。
    • 注意:删除非空目录需递归删除其内容(POSIX 未提供直接支持,需手动实现)。

三、文件链接机制

  1. 硬链接(Hard Link)

    • 机制:通过 link(const char *oldpath, const char *newpath) 创建,多个文件名指向同一 inode。
    • 特性
      • 不能跨文件系统(同一设备)。
      • 删除原文件不影响硬链接(inode 引用计数减 1)。
  2. 符号链接(Symbolic Link)

    • 机制:通过 symlink(const char *target, const char *linkpath) 创建,存储目标文件路径。
    • 特性
      • 可跨文件系统。
      • 目标文件删除后,符号链接成为“悬空链接”(ENOENT 错误)。
    • 读取内容:使用 readlink() 获取链接指向的实际路径。

四、权限与所有权

  1. 权限控制

    • 权限位
      • 用户(Owner)、(Group)、其他(Others)的读(r)、写(w)、执行(x)权限。
      • 特殊权限位:
        • setuid:执行时以文件所有者权限运行。
        • setgid:目录中新文件继承组 ID。
        • 粘滞位(Sticky Bit):仅文件所有者可删除/重命名(如 /tmp 目录)。
    • 函数
      • chmod(const char *path, mode_t mode):修改权限。
      • umask(mode_t mask):设置进程的文件创建权限掩码(默认屏蔽位)。
  2. 所有权管理

    • 函数
      • chown(const char *path, uid_t owner, gid_t group):修改文件所有者和组。
      • lchown():修改符号链接自身所有权(而非目标文件)。

五、文件系统操作函数

  1. 路径解析

    • char *realpath(const char *path, char *resolved_path):解析绝对路径,消除符号链接。
    • int access(const char *path, int mode):检查路径访问权限(F_OKR_OKW_OKX_OK)。
  2. 工作目录管理

    • char *getcwd(char *buf, size_t size):获取当前工作目录。
    • int chdir(const char *path):切换当前工作目录。
  3. 文件删除

    • int unlink(const char *pathname):删除文件(减少 inode 引用计数,引用为 0 时释放)。
    • int remove(const char *pathname):等价于 unlink()(文件)或 rmdir()(目录)。

六、挂载与文件系统管理

  1. 挂载机制

    • 挂载点:通过 mount() 将设备或虚拟文件系统附加到目录树(具体实现依赖操作系统)。
    • 卸载umount()umount2() 解除挂载。
  2. 文件系统信息

    • int statvfs(const char *path, struct statvfs *buf):获取文件系统统计信息(如块大小、总空间、可用空间)。
      struct statvfs {
          unsigned long f_bsize;   // 文件系统块大小
          fsblkcnt_t f_blocks;     // 总块数
          fsblkcnt_t f_bfree;      // 空闲块数
          fsblkcnt_t f_bavail;     // 非特权用户可用块数
          // ...
      };
      

七、关键设计思想

  1. 统一抽象

    • 所有资源(文件、设备、管道等)均以文件形式呈现,简化操作接口。
  2. 权限分离

    • 通过用户/组权限和特殊位实现精细的访问控制。
  3. 软硬链接分离

    • 硬链接保证数据持久性,符号链接提供灵活性。
  4. 可扩展性

    • 支持多种文件系统类型(如 ext4、FAT、NFS)通过挂载机制无缝集成。

八、总结

机制 核心功能 关键函数/操作
目录结构 树状层次化管理文件 opendir/readdir/mkdir
文件类型 区分普通文件、目录、设备等 stat()/S_ISDIR()
链接机制 硬链接共享数据,符号链接跨文件系统 link()/symlink()/readlink()
权限控制 用户/组/其他权限 + 特殊位 chmod()/chown()
文件系统管理 挂载、空间查询、路径解析 mount()/statvfs()/realpath()
  • 应用场景
    • 文件搜索工具:结合目录遍历与权限检查。
    • 备份系统:利用硬链接减少存储冗余。
    • 多用户环境:通过权限位隔离数据访问。