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

【操作系统百科】vDSO

文章导航

分类入口
os
标签入口
#vdso#vvar#vsyscall#getrandom#zero-syscall

目录

gettimeofday() 是调用频率最高的系统调用之一。如果每次都进内核 → 200ns 开销。vDSO 让它在用户态完成 → 20ns。

一、先看图

flowchart LR
    APP[用户程序] -->|调用| VDSO[vDSO<br/>linux-vdso.so.1]
    VDSO -->|读| VVAR[vvar 页<br/>内核维护的只读数据]
    VVAR --> TSC[读 TSC<br/>计算时间]

    APP2[传统方式] -->|syscall| KERNEL[内核<br/>sys_clock_gettime]

    classDef fast fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    classDef slow fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    class APP,VDSO,VVAR,TSC fast
    class APP2,KERNEL slow

二、什么是 vDSO

Virtual Dynamic Shared Object:内核编译的一小段共享库 → mmap 到每个进程地址空间。

cat /proc/self/maps | grep vdso
# 7fff...  r-xp  [vdso]

cat /proc/self/maps | grep vvar
# 7fff...  r--p  [vvar]

三、支持的函数

函数 x86_64 arm64
clock_gettime
gettimeofday
clock_getres
time
getcpu
getrandom(6.11+)

四、工作原理

4.1 时间读取

// vDSO 内部(简化)
int __vdso_clock_gettime(clockid_t clk, struct timespec *ts)
{
    struct vdso_data *vd = __arch_get_vdso_data();
    // seqcount 重试循环
    do {
        seq = vdso_read_begin(vd);
        ns = vd->clock_mode == VDSO_CLOCKMODE_TSC
             ? rdtsc() * vd->mult >> vd->shift + vd->base_ns
             : fallback_to_syscall();
    } while (vdso_read_retry(vd, seq));
    ts->tv_sec = ns / NSEC_PER_SEC;
    ts->tv_nsec = ns % NSEC_PER_SEC;
}

内核每 tick 更新 vvar 中的时间基准 → vDSO 读 TSC 计算偏移。

4.2 Fallback

如果 clocksource 不适合 vDSO(如 HPET)→ vDSO 退回 syscall。

五、vsyscall(已退役)

vsyscall 是 vDSO 的前身——固定地址(0xffffffffff600000)→ 安全风险(ASLR 无效)。

现代内核:vsyscall=emulate(陷入内核模拟)或 vsyscall=none(禁用)。

六、getrandom vDSO(6.11+)

getrandom(buf, 32, 0);  // 传统:syscall
// vDSO 版本:用户态生成随机数

内核维护 ChaCha20 状态在 vvar → vDSO 在用户态生成随机数 → 性能大幅提升。

七、time namespace

unshare(CLONE_NEWTIME);
// 写 /proc/self/timens_offsets

每个 time namespace 有独立的 vvar → vDSO 读到的时间带偏移 → 容器迁移时保持时间连续性。

八、性能对比

方式 clock_gettime 延迟
syscall ~200ns
vDSO (TSC) ~15-25ns

高频调用场景(数据库、交易系统、日志时间戳)→ 10 倍差距。

九、观察

# 查看 vDSO
ldd /bin/ls | grep vdso
# linux-vdso.so.1

# 导出 vDSO
dd if=/proc/self/mem of=vdso.so skip=$(cat /proc/self/maps | grep vdso | cut -d- -f1) bs=1 count=4096

# 验证是否走 vDSO
strace -e clock_gettime ./my_app  # 应该看不到 syscall(vDSO 不经过 syscall)
ltrace -e clock_gettime ./my_app  # ltrace 可以看到

十、小结


参考文献

工具


上一篇ELF 加载 下一篇内核模块生态

同主题继续阅读

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

2026-06-08 · os

【操作系统百科】时钟源

TSC 真的稳吗?本文讲 clocksource/clockevents 分离、TSC invariant/unstable 判定、HPET/ACPI PM/arch_timer、watchdog 校准、vDSO gettimeofday、PTP/PHC 硬件时间戳。

2026-04-17 · os

【操作系统百科】系统调用 ABI:x86_64 / arm64 / riscv / Windows NT 对照

系统调用是 OS 最稳定的接口。本文拆解 Linux syscall 的参数寄存器约定、返回值规范(负 errno 与 2-value ABI)、x86_64 SYSCALL、arm64 SVC、RISC-V ECALL、Windows NT 的 int 2e/syscall/SYSENTER 历史;说明为什么 Linux 承诺 \"don't break userspace\"、什么东西算 syscall ABI、vDSO 如何用共享内存加速、Go/musl/glibc 各自怎么实现 syscall stub。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。


By .