游乐游手机版
首页/系统平台/文章详情

Unix文件系统pwd命令底层实现原理解析

时间:2026-06-19 07:50
Unix系统中的文件组织方式,本质上是一棵层次化的目录树。每个目录都可以包含文件和其他子目录。从理论上讲,这棵树的深度几乎可以无限延伸——然而,如果实际尝试挑战其极限,系统会提示“超出范围”并终止执行。使用以下脚本即可验证这一特性: while true do mkdir deep_well cd

Unix系统中的文件组织方式,本质上是一棵层次化的目录树。每个目录都可以包含文件和其他子目录。从理论上讲,这棵树的深度几乎可以无限延伸——然而,如果实际尝试挑战其极限,系统会提示“超出范围”并终止执行。使用以下脚本即可验证这一特性:

while true
do
mkdir deep_well
cd deep_well
done

运行几秒后,系统就会提示超过目录树范围并中断执行。

2. 一个磁盘可以划分为大量扇区,每个扇区存储512字节

扇区是磁盘上最小的物理存储单元,我们可以对每个扇区进行编号,从而使磁盘成为一系列已编号块的集合。

3. 磁盘块上存储文件时遵循固定规则

每个文件系统通常由三部分组成:超级块、i-节点表以及数据区。

  • 超级块:存储文件系统自身的元信息,例如各区域的大小以及未使用的磁盘块信息(不同版本的实现略有差异)。
  • i-节点表:每个文件都有其属性(如大小、最近修改时间等),这些属性被保存在ino_t结构体中。所有i-节点的大小相同,i-节点表就是这些节点的线性列表。表中的每个i-节点通过其在表中的位置索引来标识,例如索引为2的i-节点位于文件系统i-节点表中的第3个位置。
  • 数据块:用于存放文件的具体内容。由于块的大小固定,一个文件通常会被分散存储到多个磁盘块上。

4. 创建一个文件的4个步骤

  1. 存储属性:内核首先找到一个空闲的i-节点,将文件的属性信息填入其中;
  2. 存储数据:从磁盘上分配空闲块,将文件数据复制进去;
  3. 记录分配情况:内核在i-节点的磁盘分布区中记录刚才分配的磁盘块编号;
  4. 添加文件名到目录:将(i-节点号,文件名)的映射关系添加到对应目录中。

5. cat、more等命令的实现原理

执行 cat name 时,系统会在目录中查找文件名,定位到该文件名对应的i-节点号;然后根据i-节点号获取文件属性并检查权限——若权限不足,open()函数返回-1,打开失败并停止执行;接着根据i-节点中的磁盘位置访问文件的数据块,反复调用read读取数据(可将其存放到缓冲区)。

6. 大文件的存储方式

如果一个文件需要14个编号的磁盘块来存储,而i-节点只包含13个项的分配链表,此时可以将前10个直接块地址存放于i-节点中,剩余的4个块地址存入一个数据块,并在i-节点的第11个位置写入指向该数据块的指针。这样实际使用了10+4+1个数据块,多出来的那个块称为间接块

同理,当间接块也被填满时,还可以设置二级间接块,以此类推,从而支持更大的文件。

7. 文件在目录中的本质含义

目录包含(i-节点号,文件名)的条目——也就是说,目录存储的是对文件的引用,每个引用被称为链接

8. 目录包含子目录的含义

目录包含指向子目录i-节点的链接。

9. 目录包含父目录的含义

目录包含 .. 的链接,即指向其父目录。

10. 文件只有i-节点号而没有名称,链接则可以有名字

一个文件可以拥有多个链接(名字可以各不相同),但它们都指向同一个文件,对这些链接的任何操作实质上都是对源文件的操作。

11. Unix系统可以挂载多个文件系统

每个文件系统都是一棵独立的树,都有各自的根目录。但系统可以通过 mount 操作将它们整合为一棵大树——即将一个文件系统的根挂载到另一个文件系统的某个目录节点上。

12. 符号链接与硬链接的区别

符号链接通过文件名引用目标文件,可以跨越不同文件系统,也可以指向目录,类似于Windows中的快捷方式。

硬链接是将目录直接链接到树的指针,同时也是将文件名与文件自身链接起来的指针,通过i-节点号来引用文件。

13. 与目录树相关的命令和系统调用

  • 命令 mkdir
    实现:头文件 #include #include
    函数原型:int res = mkdir(char *path, mode_t mode);

  • 命令 rmdir:删除一个目录,该目录必须为空。
    实现:#include
    函数原型:int res = rmdir(const char* path);

  • 命令 rm:减少相应i-节点的链接计数,若链接数减为0,则释放数据块和i-节点。该命令不能用于删除目录。
    实现:#include
    函数原型:int res = unlink(const char *path);

  • 命令 ln:不能用于创建目录的硬链接。
    实现:#include
    函数原型:int res = link(const char *old, const char *new);

  • 命令 mv:先删除原目录链接,再复制到新位置。
    实现:#include
    函数原型:int res = rename(const char* from, const char *to);
    原理:将链接复制到新名称/位置,然后删除原链接——if(link("x","z")!=-1) unlink("x");

  • 命令 cd:仅影响当前进程的工作目录,对目录本身无影响。
    实现:#include
    函数原型:int res = chdir(const char *path);

14. pwd命令的实现原理

下面是一个pwd命令的简单实现示例,通过递归向上查找父目录来拼接出完整路径:

#include 
#include 
#include 
#include 
#include 
#include 

ino_t get_inode(char *);
void printpathto(ino_t);
void inum_to_name(ino_t, char *, int);

int main()
{
    printpathto(get_inode("."));
    putchar('\n');
    return 0;
}

void printpathto(ino_t this_inode)
{
    ino_t my_inode;
    char its_name[BUFSIZ];
    if (get_inode("..") != this_inode)
    {
        chdir(".."); // up one dir
        inum_to_name(this_inode, its_name, BUFSIZ); // get its name
        my_inode = get_inode(".");
        printpathto(my_inode); // iterate
        printf("/%s", its_name);
    }
}

void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen)
{
    DIR *dir_ptr;           // the directory
    struct dirent *direntp; // each entry
    dir_ptr = opendir(".");
    if (dir_ptr == NULL)
    {
        perror(".");
        return;
    }
    while ((direntp = readdir(dir_ptr)) != NULL)
    {
        if (direntp->d_ino == inode_to_find)
        {
            strncpy(namebuf, direntp->d_name, buflen);
            namebuf[buflen-1] = '\0';
            closedir(dir_ptr);
            return;
        }
    }
    fprintf(stderr, "error looking for inum %d\n", (int)inode_to_find);
    return;
}

ino_t get_inode(char *fname)
{
    struct stat info;
    if (stat(fname, &info) == -1)
    {
        fprintf(stderr, "Can not stat");
        perror(fname);
        return 1;
    }
    return info.st_ino;
}

运行结果:

caoli@caoli-laptop:~/workspace/test$ ./pwd1
/home/caoli/workspace/test
caoli@caoli-laptop:~/workspace/test$
来源:https://www.jb51.net/os/Unix/545900.html
上一篇FreeBSD时间设置方法详解 下一篇FreeBSD添加硬盘的方法与步骤
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
微软详解Win11时间点还原 默认每24小时创建恢复点
系统平台 · 2026-06-30

微软详解Win11时间点还原 默认每24小时创建恢复点

微软今日推送了最新的 6 月可选更新,并发布博客详细解读了 Win11 全新的“时间点还原”(Point-in-time restore)功能——这一功能本质上是对系统恢复体验的一次全面升级,旨在让用户更轻松地应对电脑故障。 微软表示,面向 Windows 11 客户端用户的“时间点还原”功能现已正

Win11 26H1六月可选更新KB5095091 优化放大镜改善装机体验
系统平台 · 2026-06-30

Win11 26H1六月可选更新KB5095091 优化放大镜改善装机体验

微软今天推送了Windows 11 26H1设备的6月可选更新KB5095091,安装完成后系统版本号会升级到Build 28000 2340。值得一提的是,这次更新并非面向所有设备,而是专门为搭载高通骁龙X2系列芯片的机型准备的——包括骁龙X2 Plus、X2 Elite和X2 Elite Ext

Win11六月可选更新KB5095093修复回收站弹窗异常
系统平台 · 2026-06-30

Win11六月可选更新KB5095093修复回收站弹窗异常

微软已悄然推送Windows 11六月可选更新,编号KB5095093。本次更新覆盖两个版本:24H2用户安装后版本号升级至Build 26100 8737,而25H2用户则更新至Build 26200 8737。 本次更新并非仅是小修小补,而是带来了多项实质性新功能。下面我们就来详细解析这些更新内

苹果macOS 27 Beta2封堵Siri AI跳过候补名单漏洞
系统平台 · 2026-06-30

苹果macOS 27 Beta2封堵Siri AI跳过候补名单漏洞

科技媒体 Cult of Mac 昨日(6月23日)发布博文指出,苹果在 macOS 27 Beta 2 更新中悄然封堵了一个此前可用的后门——用户曾能通过一条终端命令绕过候补名单,直接启用新版 Siri AI,如今这一方法已失效。 简要回顾一下:在 macOS 27 Beta 1 阶段,只需在 M

微软加速Win11 25H2推送 覆盖所有符合条件家用PC
系统平台 · 2026-06-30

微软加速Win11 25H2推送 覆盖所有符合条件家用PC

近日(6月23日),科技媒体 Windows Latest 发布了一则值得关注的动态:微软已进一步扩大 Windows 11 25H2 的推送范围,所有满足硬件要求、且不受 IT 部门管理的家庭版和专业版设备,现在均可顺利接收本次更新。 此次升级有一个显著特点——采用“启用包”(eKB)方式进行推送