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

【操作系统百科】时钟源

文章导航

分类入口
os
标签入口
#clocksource#tsc#hpet#vdso#ptp

目录

gettimeofday() 每次调用返回当前时间——底层读的是什么硬件?TSC 够稳吗?为什么 vDSO 能不进内核就读时间?

一、先看图

flowchart TD
    APP[gettimeofday / clock_gettime] --> VDSO[vDSO<br/>用户态读取]
    VDSO --> SEQCOUNT[seqcount_latch<br/>读 timekeeper]
    SEQCOUNT --> CSRC[clocksource<br/>read 硬件计数器]

    subgraph 硬件时钟
        TSC[TSC<br/>rating: 300]
        HPET[HPET<br/>rating: 250]
        ACPI[ACPI PM<br/>rating: 200]
        ARM_GT[ARM Generic Timer<br/>rating: 400]
    end

    CSRC --> TSC
    CSRC --> HPET
    CSRC --> ACPI
    CSRC --> ARM_GT

    classDef user fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    classDef hw fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    class APP,VDSO,SEQCOUNT user
    class TSC,HPET,ACPI,ARM_GT,CSRC hw

二、clocksource 框架

struct clocksource {
    u64 (*read)(struct clocksource *cs);
    u32 rating;       // 越高越好
    const char *name;
    // ...
};

内核选择 rating 最高的可用 clocksource。

2.1 常见 clocksource

名称 rating 精度 平台
TSC 300 ns x86
HPET 250 ns x86(慢)
ACPI PM 200 μs x86(最慢)
arch_timer 400 ns ARM
KVM clock 400 ns KVM guest
cat /sys/devices/system/clocksource/clocksource0/available_clocksource
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

三、TSC 的稳定性

3.1 Invariant TSC

现代 CPU(Sandy Bridge+)标记 constant_tsc + nonstop_tsc

3.2 Unstable TSC

旧 CPU 或某些虚拟化环境 → TSC 不稳定 → 内核 watchdog 检测到后降级到 HPET/ACPI PM。

clocksource: Marking clocksource 'tsc' as unstable because the skew is too large

3.3 TSC 同步

多 socket 系统 → 各 socket TSC 可能不同步 → 内核检查 TSC 偏差。

四、clockevents

clocksource 是时间;clockevents 是编程定时器。

struct clock_event_device {
    void (*event_handler)(struct clock_event_device *);
    int (*set_next_event)(unsigned long, struct clock_event_device *);
    enum clock_event_state state_use_accessors;
    // ...
};

hrtimer 用 clockevents 编程下一个到期中断。

五、vDSO

Virtual Dynamic Shared Object:内核把一小段代码和数据映射到每个进程地址空间。

clock_gettime(CLOCK_MONOTONIC) → 不进内核 → vDSO 读 seqcount + TSC → 返回。

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

5.1 性能

方式 延迟
syscall clock_gettime ~200ns
vDSO clock_gettime ~20ns

10 倍差距。

六、PTP/PHC

精确时间协议(Precision Time Protocol):

# 硬件时间戳
ethtool -T eth0 | grep -i ptp
# 配置 ptp4l
ptp4l -i eth0 -m

PHC(PTP Hardware Clock)提供独立的硬件时钟 → 纳秒级网络时间同步。

七、time namespace(5.6+)

容器可以有独立的时间偏移:

unshare(CLONE_NEWTIME);
// 修改 /proc/self/timens_offsets

用途:容器迁移时保持时间连续性。

八、Watchdog

内核定期用次优 clocksource 校验主 clocksource:

clocksource: timekeeping watchdog on CPU0

偏差过大 → 标记为 unstable → 切换。

九、观察

# 当前时钟源
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

# TSC 特性
grep -E "constant_tsc|nonstop_tsc" /proc/cpuinfo

# clockevents
cat /sys/devices/system/clockevents/clockevent0/current_device

# vDSO 性能
perf stat -e 'syscalls:sys_enter_clock_gettime' -- ./benchmark

十、小结


参考文献

工具


上一篇无滴答内核 下一篇CPU 热插拔

同主题继续阅读

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

2026-06-14 · os

【操作系统百科】vDSO

vDSO 把 gettimeofday/clock_gettime 搬到用户态——零 syscall 读时间。本文讲 vDSO 原理、vvar 共享页、getrandom vDSO、x86/arm64 差异、vsyscall 退役、time namespace 支持。

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 .