土法炼钢兴趣小组的算法知识备份

【操作系统百科】路径名解析

文章导航

分类入口
os
标签入口
#namei#lookup-rcu#openat2#symlink#pathname

目录

用户传一个字符串 /usr/bin/ls,内核要一级一级查 dcache / 磁盘,穿越 mount 点、symlink,最终拿到目标 inode。这个过程叫 namei(name-to-inode),是 VFS 最频繁的操作。

一、先看图

flowchart LR
    PATH["/usr/bin/ls"] --> SLASH[/ → root dentry]
    SLASH --> USR[lookup "usr"]
    USR --> BIN[lookup "bin"]
    BIN -->|mount 穿越| BINMNT[/usr/bin 挂载点]
    BINMNT --> LS[lookup "ls"]
    LS --> INODE[inode 返回]
    classDef step fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef mount fill:#a371f722,stroke:#a371f7,color:#adbac7;
    class SLASH,USR,BIN,LS,INODE step
    class BINMNT mount

二、三阶段查找

2.1 LOOKUP_RCU(快速路径)

不加任何锁,RCU 保护:

  1. 从根 dentry 开始
  2. 每个组件用 d_hash 查 dcache
  3. 验证 d_seq(dentry 序列号)保证数据一致
  4. mount 穿越用 mnt_seq 验证

成功率 >99%(热路径命中 dcache)。

2.2 LOOKUP_LOCK(降级)

RCU 验证失败 → 降级拿 inode->i_rwsem + dentry 引用。

2.3 LOOKUP_SLOW(磁盘)

dcache miss → 调用 inode->i_op->lookup() → 读磁盘目录。

三、mount 穿越

路径走到 mount 点时:

/        → root sb
/usr     → root sb
/usr/bin → 如果 /usr 是独立挂载,穿越到新 sb 的 root dentry

follow_managed() 处理 automount + mount 穿越。

遇到 symlink → 递归解析目标。

保护:

五、openat2 与 RESOLVE_*

openat2(2) 引入安全控制:

struct open_how how = {
    .flags = O_RDONLY,
    .resolve = RESOLVE_NO_SYMLINKS | RESOLVE_BENEATH,
};
int fd = openat2(dirfd, "path", &how, sizeof(how));

容器安全的基石。

六、AT_EMPTY_PATH 与 fstat 优化

openat(dirfd, "", AT_EMPTY_PATH)
// 等价于对 dirfd 本身操作

配合 /proc/self/fd/N → 可以用路径操作已打开的 fd。

七、case-insensitive

ext4 5.2+ 支持 casefold 特性(UTF-8 case folding):

mkfs.ext4 -O casefold /dev/sda1
chattr +F /mnt/mydir    # 该目录及子目录大小写不敏感

内核在 lookup 时用 UTF-8 NFC 正规化 + case fold 比较。

限制:不同 locale 的 case mapping 不同;不支持 Turkic “i” 问题。

八、RENAME_EXCHANGE

renameat2(olddirfd, "a", newdirfd, "b", RENAME_EXCHANGE);
// 原子交换 a 和 b

比 rename+rename 安全——不会出现中间状态。

RENAME_NOREPLACE:不覆盖目标(原子 create-or-fail)。

九、dcache 调优

# 当前 dcache 状态
cat /proc/sys/fs/dentry-state

# negative dentry 限制(6.1+)
sysctl fs.negative-dentry-limit=0    # 不限(默认)

大量 negative dentry 场景:编译器频繁探测不存在的头文件 → dcache 膨胀。

十、路径查找性能

# 衡量 lookup 速度
perf stat -e 'syscalls:sys_enter_openat' -- find /usr -name '*.so' > /dev/null

# dcache 命中率
perf stat -e dentry-cache-misses,dentry-cache-accesses 2>/dev/null
# 或看 /proc/slabinfo dentry 变化

十一、小结


参考文献

工具


上一篇VFS 四层抽象 下一篇fd 表与 struct file

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-29 · linux / os

EEVDF 调度器:Linux 6.6 为什么换掉了 CFS

Linux 6.6 用 EEVDF 取代了 CFS 的 SCHED_NORMAL 选取逻辑。从 1995 年原始论文的 lag、eligibility、virtual deadline,到 commit 147f3ef 只重写 placement/pick/preempt,再到本机内核 6.6 上读 sched/debug 把每个任务的 vruntime、eligible 标志、deadline 一一对上 vd=ve+r/w,外加 nice 带宽与 base_slice 抢占两组实测,讲清换的是哪一块、延迟敏感任务凭什么先跑。

2026-07-05 · os

【操作系统百科】实时 OS 巡礼

硬实时与软实时的可调度性边界、VxWorks/QNX/Zephyr 机制对照、Linux PREEMPT_RT 与主线合入、DO-178C/ISO 26262 认证语境,以及选型决策树。

2026-07-06 · os

【操作系统百科】Unikernel

Unikernel 在云上为什么没成主流?MirageOS、IncludeOS、Unikraft、OSv 的设计取舍——库操作系统、启动时间、工具链、调试困难、POSIX 兼容。


By .