【翻译】(19)Bionic Changes

本文详细阐述了Bionic在不同Android版本(2.1、2.0.1、2.0、1.6)之间的核心技术变化,包括但不限于CPU架构支持、函数实现与API更新,以及DNS、线程、内存操作等关键领域的调整。

-----------------

英文文档见android-ndk-r7的documentation.html

属于Android Native Development Kit (NDK)的一部分

http://developer.android.com/sdk/ndk/index.html

翻译仅个人见解

-----------------

 

Bionic ChangeLog:

-----------------

 

Bionic修改日志:

-----------------

 

Differences between current and Android 2.1:

 

当前版本与Android 2.1之间的差异:

 

- Add support for SH-4 CPU architecture !

 

- 添加对SH-4 CPU架构的支持!(注:SH是SuperH的缩写,以32位元存取的精简指令集架构,由日立开始开发)

 

- __atomic_swap(): use LDREX/STREX CPU instructions on ARMv6 and higher.

 

- __atomic_swap():ARMv6或更高的CPU上使用LDREX/STREX CPU指令。

 

- <arpa/telnet.h>: New header (declarations only, no implementation).

 

- <arpa/telnet.h>:新的头文件(只有声明,没有实现)。

 

- <err.h>: New header + implementation. GLibc compatibility.

 

- <err.h>:新的头文件+实现。兼容GLibc。

 

- <warn.h>: New header + implementation. GLibc compatibility.

 

- <warn.h>:新的头文件+实现。兼容GLibc。

 

- <fts.h>: New header + implementation.

 

- <fts.h>:新的头文件+实现。

 

- <mntent.h>: Add missing <stdio.h> include.

 

- <mntent.h>:添加缺少的<stdio.h>包含。

 

- <regex.h>: New header + implementation.

 

- <regex.h>:新的头文件+实现。

 

- <signal.h>: Added killpg()

 

- <signal.h>:添加killpg()(注:killpg在Linux上用于发送信号给进程组)

 

- <stdint.h>: Allow 64-bit type declarations on C99 builds.

 

- <stdint.h>:允许在C99构建上使用64位类型声明。

 

- <stdio.h>: Add fdprintf() and vfdprintf(). Note that GLibc provides the confusing 'dprintf' and 'vdprintf()' functions instead.

 

- <stdio.h>:添加fdprintf()和vfdprintf()(注:这两个函数在Linux上用于对文件描述符printf)。注意,与GLibc提供混淆的'dprintf'和'vdprintf()'函数不同。

 

- <stdlib.h>: Fix ptsname_r(): the return type is int instead of char*. The mistake comes from a GLibc man page bug (the man page listed a return type of char*, while the implementation used int. Fixed in late 2009 only). The Bionic implementation was incorrect. Technically, this is an ABI breakage, but code that used this function probably never worked or compiled properly anyway.

 

- <stdlib.h>:修正ptsname_r():返回类型是int而非char*。这个错误来自GLibc手册页面的缺陷(手册页面列出返回值为char*,但实现使用int。只在2009年底修正)。Bionic实现是不正确的。技术上,这是一个ABI破损,但使用这个函数的代码很可能无论如何都不能工作或正确地编译。

 

- <strings.h>: Add missing <sys/types.h> include.

 

- <strings.h>:添加缺少的<sys/types.h>包含。

 

- <sys/queue.h>: Added new header (no implementation - macro templates).

 

- <sys/queue.h>:添加新的头文件(没有实现——宏模板)。

 

- <sys/resource.h>: Add rlim_t proper definition.

 

- <sys/resource.h>:添加rlim_t的正确定义。(注:用于表示限制值的无符号整数类型)

 

- <time64.h>: Add missing C++ header inclusion guards.

 

- <time64.h>:添加缺少的C++头文件包含保护。

 

- <unistd.h>: Add getusershell(), setusershell() and endusershell(), though implementation are bogus. GLibc compatibility.

 

- <unistd.h>:添加getusershell(),setusershell()和endusershell(),虽然实现是假的。(注:这三个函数在Linux下用于获取合法的用户外壳命令,读取/etc/shells文件的下一行)。兼容GLibc。

 

- <wchar.h>: Add mbstowcs() and wcstombs()

 

- <wchar.h>:添加mbstowcs()和wcstombs()(注:在多字节和宽字节之间转换)

 

- add clone() implementation for ARM (x86 and SH-4 not working yet).

 

- 为ARM添加clone()实现(x86和SH-4还不能工作)。

 

- <sys/epoll.h>: <sys/system_properties.h>: Add missing C++ inclusion guards

 

- <sys/epoll.h>:<sys/system_properties.h>:添加缺少的C++包含保护。

 

- fix getpwnam() and getpwgrp() to accept "app_0" as a valid user name.

 

- 修正getpwnam()(注:通过用户名获取用户属性)和getpwgrp()(注:获取调用进程的进程组ID)以接受"app_0"作为合法用户名。

 

- fix sem_trywait() to return -1 and set errno to EAGAIN, instead of returning EAGAIN directly.

 

- 修正sem_trywait()以返回-1并设置errno为EAGAIN,而非直接返回EAGAIN。

 

- fix sem_post() to wake up multiple threads when called rapidly in succession.

 

- 修正sem_post()以在成功地快速调用时唤醒多个线程。

 

- DNS: partial implementation of RFC3484 (rule 1, 2, 5, 6, 8, 10 and modified rule 9), for better address selection/sorting. In the process, removed code that was previously used for "sortlist" in /etc/resolv.conf. (resolv.conf is already ignored, so the latter is a no-op for actual functionality.)

 

- DNS:部分实现RFC3484(规则1,2,5,6,8,10和修改过的规则9),更好的地址选择/排序。在进程中,移除以前在/etc/resolv.conf中用于sortlist的代码。(resolv.conf已经被忽略,所以以后对于实际功能是无操作的。)

 

- fix pthread_sigmask() to properly return an error code without touching errno. Previous implementation returned -1 on error, setting errno, which is not Posix compliant.

 

- 修正pthread_sigmask()以正确地返回错误码而不影响errno。以前的实现在出错时返回-1,设置errno,这是不兼容Posix的(注:Posix是Unix可移植操作系统接口的缩写)。

 

- add sigaltstack() implementation for ARM.

 

- 添加ARM的sigaltstack()实现。(注:设置或获取信号备用堆栈上下文)

 

- <time.h>: Properly implement the 'timezone' and 'daylight' global variables (they were not defined previously, though declared in the header).

 

- <time.h>:正确实现timezone和daylight全局变量(它们之前没有定义,虽然在头文件中声明了)

 

- <time.h>: Fix timezone management implementation to properly update 'tm_gmtoff' field in 'struct tm' structure.

 

- <time.h>:修正时区管理实现以正确地更新struct tm结构体中的tm_gmtoff域。

 

- DNS: get rid of spurious random DNS queries when trying to resolve an unknown domain name. Due to an initialization bug, a random DNS search list was generated for each thread if net.dns.search is not defined.

 

- DNS:避免当尝试解析一个未知域名时的伪随机DNS查询。因为一个初始化的缺陷,如果net.dns.search未定义,每个线程将生成一个随机DNS搜索列表。

 

- <pthread.h>: Add pthread_condattr_init/destroy/setpshared/getpshared functions to enable proper shared conditional variable initialization.

 

- <pthread.h>:添加pthread_condattr_init/destroy/setpshared/getpshared函数,使正确的共享条件变量初始化生效。

 

  Modify the pthread_mutex_t and pthread_cond_t implementation to use private futexes for performance reasons. Mutexes and Condvars are no longer shareable between processes by default anymore, unless you use PTHREAD_PROCESS_SHARED with pthread_mutexattr_setpshared() and/or pthread_condattr_setpshared().

 

  修改pthread_mutex_t和pthread_cond_t实现以使用私有futex,出于性能原因。默认下mutex和condvar不再在进程间共享,除非你上用pthread_mutexattr_setpshared()和/或pthread_condattr_setpshared()指定PTHREAD_PROCESS_SHARED。

 

-------------------------------------------------------------------------------

Differences between Android 2.1 and 2.0.1:

 

Android 2.1和2.0.1之间的差异:

 

- zoneinfo: updated data tables to version 2009s

 

- zoneinfo:更新数据表格至版本2009。

 

-------------------------------------------------------------------------------

Differences between Android 2.0.1 and 2.0:

 

Android 2.0.1和2.0之间的差异:

 

- abort(): ARM-specific hack to preserve the 'lr' register when abort() is called (GCC does not preserve it by default since it thinks that abort() never returns). This improves stack traces considerably.

 

- abort():特定ARM的修改,以在abort()调用时保留lr寄存器(GCC默认不保留它,因为它认为abort()从不返回)。这很大程度上改进了堆栈追溯。

 

-------------------------------------------------------------------------------

Differences between Android 2.0 and 1.6:

 

Android 2.0和1.6之间的差异:

 

- memcmp(), memcpy(): ARMv7 optimized versions.

 

- memcmp(),memcpy():ARMv7优化版本。(注:memcmp用于比较内存区,memcpy用于复制内存)

 

- pthread_mutexattr_setpshared(): implementation will not return ENOTSUP if PTHREAD_PROCESS_SHARED is used, because our Mutex implementation can work across multiple processes.

 

- pthread_mutexattr_setpshared:如果使用了PTHREAD_PROCESS_SHARED,实现将不会返回ENOTSUP,因为我们的互斥锁实现可以跨多个进程工作。(注:pthread_mutexattr_setpshared用于设置特定互斥属性值的进程共享状态属性,PTHREAD_PROCESS_SHARED表示创建的互斥量可以在系统内的所有进程中同步线程,而不局限于当前进程)

 

  *HOWEVER* it does not use "robust futexes" which means that held mutexes *are not* automatically released by the kernel when the owner process crashes or exits. This is only done to simplify communication between two always-live system processes, DO NOT USE THIS IN APPLICATIONS !

 

  然而它不使用robust futex(注:健壮的快速用户互斥锁,见http://lxr.linux.no/linux/Documentation/robust-futexes.txt),它的意思是内核持有拥有者进程崩溃或退出时不被自动释放的mutex。这个函数只用来简化两个已存在系统进程间的通信,不要在应用程序中使用它!

 

- pthread_mutex_lock_timeout_np(): New Android-specific function to perform a timed lock(). In case of timeout, it returns EBUSY.

 

- pthread_mutex_lock_timeout_np():新的特定Android的函数以执行超时lock()。在超时的情况下,它返回EBUSY。

 

- pthread_cond_timedwait_monotonic_np(): Same as pthread_cond_timedwait() but uses the monotonic clock(). Android-specific.

 

- pthread_cond_timedwait_monotonic_np():同pthread_cond_timedwait(),但使用单调的clock()。特定于Android。

 

- pthread_cond_timedwait_relative_np(): Same as pthread_cond_timedwait() but uses a relative timeout instead. Android-specific.

 

- pthread_cond_timedwait_relative_np():同pthread_cond_timedwait(),但改为使用相对超时时间。特定于Android。

 

- <netinet/in.h>: Now includes <netinet/in6.h>.

 

- <netinet/in.h>:现在包含<netinet/in6.h>。

 

- <netinet/in6.h>: Added IPV6_JOIN_GROUP, IPV6_LEAVE_GROUP, IN6ADDR_ANY_INIT and ipv6mr_interface definitions.

 

- <netinet/in6.h>:添加IPV6_JOIN_GROUP,IPV6_LEAVE_GROUP,IN6ADDR_ANY_INIT和ipv6mr_interface定义。

 

- <time.h>:

    * Add missing tzset() declaration.

    * Add Android-specific strftime_tz().

 

- <time.h>:

* 添加缺少的tzset()定义。(注:设置时间环境变量)

* 添加特定Android的strftime_tz()。

 

- getaddrinfo():

    Only perform IPv6 lookup for AF_UNSPEC if we have IPv6 connectivity. This saves one DNS query per lookup on non-IPv6 systems.

 

- getaddrinfo():

如果我们有IPv6连接,对于AF_UNSPEC参数只执行IPv6查找。它在非IPv6系统上每查找一次,保存一个DNS查询。

 

- mktime(): Fix an infinite loop problem that appeared when switching to GCC 4.4.0.

 

- mktime():修正在切换到GCC 4.4.0时出现的一个无限循环问题。

 

- strftime(): fix incorrect handling of dates > 2038 due to 64-bit issue in original code.

 

- strftime():修正由于原始代码中64位问题造成的大于2038的不正确日期处理。

 

-------------------------------------------------------------------------------

Differences between Android 1.6 and 1.5:

 

Android 1.6和1.5之间的差异:

 

- C runtime: Fix runtime initialization to be called before any static C++ constructors. This allows these to use pthread functions properly.

 

- C运行时:修正运行时的初始化在任意静态C++构造函数(注:这里指静态变量的构造?)调用前被调用。它允许这些构造函数正确地使用pthread函数。

 

- __aeabi_atexit(): Fix implementation to properly call C++ static destructors when the program exits (or when a shared library is unloaded).

 

- __aeabi_atexit():修正实现,使程序退出时(或当一个共享库卸载时)能正确调用C++静态析构函数。

 

- <sys/stat.h>: added GLibc compatibility macros definitions:

 

- <sys/stat.h>:添加兼容GLibc的宏定义:

 

        #define  st_atimensec  st_atime_nsec

        #define  st_mtimensec  st_mtime_nsec

        #define  st_ctimensec  st_ctime_nsec

 

- getaddrinfo(): implementation will now allow numeric ports if ai_socktype is set to ANY. This is to match the GLibc behaviour.

 

- getaddrinfo():实现现在将允许,如果ai_socktype被设置为ANY,则允许数字型的端口。(注:这个函数把DNS主机名转换为IP地址)。这匹配GLibc的行为。

 

- getservent(): and getservent_r() incorrectly returned the port in host-endian order in the s_port field. It now returns it in big-endian order.

 

- getservent():和getservent_r()在s_port域中以不正确的主机字节序返回端口。它现在以大端顺序返回。(注:大端序又被称为网络字节序,用于网络传输)

 

- DNS: Allow underscore in the middle of DNS labels. While not really standard, this extension is needed for some VPN configurations and is supported by other operating systems.

 

- DNS:允许在DNS标签中间带下划线。然而不是太标准,这个扩展是一些VPN(注:虚拟专用网络的缩写)配置所需的,并被其它操作系统支持。

 

- DNS: Support for DNS domain search lists through the new net.dns.search system property. The corresponding value must be a space-separated list of domain suffixes.

 

- DNS:支持通过新的net.dns.search系统属性指定DNS域名搜索列表。相应的值必须是空格分隔的域名后缀列表。


<think>我们正在讨论Monotonic Time(单调时间)的概念及其在操作系统中的实现原理。根据用户的问题,需要明确Monotonic Time的定义,并解释其实现原理。同时,用户提供了一些引用,但其中部分引用可能不直接相关(如引用[1]描述的是时间原点,引用[2]是关于过时的函数,引用[3][4]是定时器设置和更新,引用[5]是人工智能历史),我们需要聚焦于单调时间的核心内容。 ### Monotonic Time 的定义 Monotonic Time(单调时间)是指一个**单向递增**的时间计数器,它不受系统时间调整(如NTP同步、手动修改系统时间)的影响。其关键特性包括: 1. **单调性**:时间值只增不减,确保时间差值的计算总是非负。 2. **连续性**:理想情况下,时间值应连续递增,但实际可能受硬件限制而离散递增。 3. **系统范围**:通常在整个系统范围内有效(不同进程看到的单调时间是一致的)。 4. **与挂钟时间无关**:单调时间通常不表示真实时间(如年月日),而是从某个未指定的起点开始计数(可能是系统启动时刻)。 在Linux中,单调时间通常以纳秒为单位,通过`CLOCK_MONOTONIC`时钟ID表示(用户空间通过`clock_gettime()`获取)。其起点(epoch)通常是系统启动时刻,但具体起点未公开(以避免依赖)。 ### 实现原理 操作系统中单调时间的实现依赖于硬件和软件协同工作,主要分为以下层次: #### 1. 硬件层:时钟源(Clocksource) 操作系统通过硬件时钟源获取原始时间计数。常见的时钟源包括: - **TSC(Time Stamp Counter)**:现代x86 CPU内置的64位寄存器,以CPU主频递增计数。具有纳秒级精度和极低访问开销(通过`rdtsc`指令读取)。内核通过`constant_tsc`和`nonstop_tsc`标志验证其在多核间的一致性和稳定性[^1]。 - **HPET(High Precision Event Timer)**:独立于CPU的硬件定时器,提供全局统一的计时,精度约100纳秒。 - **ACPI PM Timer**:旧系统使用,精度较低(约300纳秒)。 内核启动时通过`clocksource_select()`自动选择最佳时钟源(优先TSC)[^1]。时钟源需满足: - **稳定性**:频率稳定(不受CPU频率调整影响)。 - **一致性**:多核CPU间计数同步(TSC需满足`constant_tsc`特性)。 #### 2. 内核抽象层:时间维护(Timekeeping) Linux内核通过`struct timekeeper`全局维护单调时间: ```c struct timekeeper { struct clocksource *clock; // 当前时钟源 u64 cycle_interval; // 每个滴答的时钟周期数 u64 nsec_scale; // 周期数到纳秒的转换因子 u64 xtime_nsec; // 当前单调时间(纳秒) ... }; ``` **更新机制**: - 时钟中断(如`tick_handle_periodic()`)或高精度定时器(hrtimer)触发时间更新。 - 每次中断时,读取时钟源的当前周期值,计算自上次更新以来的增量周期数$\Delta C$。 - 将$\Delta C$转换为纳秒:$\Delta T = \Delta C \times \text{nsec\_scale}$。 - 累加到`xtime_nsec`:`xtime_nsec += \Delta T`。 #### 3. 高精度与低开销:动态滴答(Tickless)和 hrtimer - **动态滴答(Tickless Kernel)**: 当CPU空闲时,内核暂停周期性的时钟中断(tick),通过设置下一个到期事件(如hrtimer)唤醒CPU。这减少了功耗,同时确保单调时间在唤醒后通过计算空闲期间的增量时间正确更新[^4]。 - **高精度定时器(hrtimer)**: 提供微秒级精度的定时器,用于替代传统低精度定时器。其核心机制: - 使用红黑树管理定时器,按到期时间排序。 - 当设置新定时器时,仅对最早到期的定时器调用`timerfd_settime()`(系统调用),避免频繁系统调用[^3]。 #### 4. 用户空间接口 用户程序通过系统调用获取单调时间: - `clock_gettime(CLOCK_MONOTONIC, &ts)`:获取秒和纳秒格式的单调时间。 - `clock_gettime(CLOCK_MONOTONIC_RAW)`:获取未经NTP调整的原始单调时间(避免NTP微调引入的非单调性)。 ### 关键保障机制 - **单调性保证**: 时间更新仅做加法操作(`xtime_nsec += delta`)。若检测到时钟源回退(如CPU降频导致TSC计数减少),则丢弃异常值并重新校准。 - **多核同步**: 通过`clocksource_mask`标记跨核一致的时钟源(如TSC),并配合读写锁(`timekeeper.lock`)保护全局时间状态。 - **与挂钟时间隔离**: 系统时间同步(如NTP/PTP)仅修改`CLOCK_REALTIME`,不影响`CLOCK_MONOTONIC`[^1]。 ### 工作流程示例 ```mermaid graph TD A[硬件时钟源 TSC/HPET] -->|读取周期计数| B(计算增量周期 ΔC) B -->|乘以缩放因子| C[转换为纳秒 ΔT] C --> D[累加到 xtime_nsec] D -->|用户空间查询| E[clock_gettime CLOCK_MONOTONIC] F[hrtimer 到期] -->|触发中断| G[更新时间] G --> D ``` ### 总结 Monotonic Time 的实现核心是: 1. **硬件时钟源**提供原始计数。 2. **内核时间子系统**将计数转换为纳秒并维护单调递增。 3. **动态滴答和hrtimer**确保高精度与低开销。 4. **隔离机制**避免系统时间调整影响单调性。 此机制是实时系统、性能分析和分布式协调的基础。 --- §§相关问题§§ 1. TSC 时钟源在多核 CPU 上如何保证计数一致性? 2. 动态滴答(Tickless)模式如何影响系统响应延迟? 3. 用户空间程序如何利用 `CLOCK_MONOTONIC` 实现高精度计时? 4. 时钟源漂移(Clock Drift)时内核如何进行补偿? [^1]: 硬件时钟源选择与校准机制 [^3]: 高精度定时器初始化与启动流程 [^4]: hrtimer 到期时间管理与红黑树操作</think>### Monotonic Time 的定义与实现原理 #### 一、Monotonic Time 核心定义 1. **基本概念** Monotonic Time(单调时间)是**严格单向递增**的时间计数器,其核心特性包括: - **单调性**:时间值只增不减($T_{n+1} \geq T_n$),不受系统时间调整影响 - **连续性**:理想情况下连续递增(实际实现可能为离散递增) - **系统范围**:整个操作系统范围内有效 - **与挂钟时间无关**:不表示真实时间(如年月日),仅表示时间流逝量 2. **关键特性对比** | 时间类型 | 是否单调 | 是否受NTP影响 | 典型用途 | |-------------------|----------|---------------|------------------------| | `CLOCK_REALTIME` | ❌ | ✅ | 文件时间戳、日志记录 | | `CLOCK_MONOTONIC` | ✅ | ❌ | 性能分析、超时控制 | | `CLOCK_BOOTTIME` | ✅ | ❌ | 包含系统休眠的时间统计 | 3. **时间原点(Epoch)** Linux 单调时间以**系统启动时刻**为原点($T_0$),而非真实时间(如1970-01-01 UTC)[^1]。用户空间获取的是从 $T_0$ 开始的纳秒计数: ```c struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); // ts.tv_sec 秒级计数 // ts.tv_nsec 纳秒级计数 ``` #### 二、实现原理分层解析 ##### 1. 硬件层:时钟源抽象 内核通过 `clocksource` 框架抽象硬件计时器: ```c struct clocksource { u64 (*read)(void); // 读取硬件计数函数指针 u64 mask; // 计数器位宽掩码 u32 mult; // 周期转纳秒的乘数 u32 shift; // 位移优化计算 const char *name; // 时钟源名称(如"tsc") }; ``` - **典型时钟源**: - **TSC**(Time Stamp Counter):CPU内置寄存器,`rdtsc` 指令读取 - **HPET**:高精度事件定时器(精度 ~100ns) - **KVM clock**:虚拟化环境专用时钟 时钟源选择策略: ```mermaid graph LR A[检测硬件] --> B{TSC可用?} B -->|是| C[验证constant_tsc/nonstop_tsc] C -->|通过| D[选择TSC为默认时钟源] B -->|否| E[选择HPET或ACPI PM] ``` ##### 2. 内核层:时间维护机制 **核心数据结构**: ```c struct timekeeper { struct clocksource *clock; // 当前时钟源 u64 cycle_interval; // 每个tick的周期数 u64 xtime_nsec; // 当前单调时间(纳秒) u32 mult; // 周期转纳秒系数 ... }; ``` **时间更新流程**: 1. 时钟中断触发 `tick_handle_periodic()` 2. 调用 `update_wall_time()` 3. 计算增量时间: $$ \Delta T = \frac{(C_{\text{current}} - C_{\text{last}}) \times \text{mult}}{2^{\text{shift}}} $$ 4. 更新单调时间:`xtime_nsec += \Delta T`[^4] ##### 3. 高精度实现:hrtimer与动态滴答 - **hrtimer 机制**: - 使用红黑树管理定时器 - 仅对**最早到期**的定时器设置硬件中断[^3] ```c // 示例:设置单调时间定时器 hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_start(&timer, expires, HRTIMER_MODE_ABS); ``` - **动态滴答(Tickless)**: ```mermaid graph TB A[CPU空闲] --> B[取消周期tick中断] B --> C[计算下一个定时器到期时间] C --> D[设置硬件定时器唤醒] D --> E[唤醒后补偿空闲时间 ΔT] E --> F[更新xtime_nsec += ΔT] ``` #### 三、关键保障机制 1. **单调性保证**: - 禁用减法操作:时间更新仅允许加法 - 时钟源异常处理: ```c if (current_cycles < last_cycles) { // 检测回退 discard_cycles(); // 丢弃异常值 recalibrate(); // 重新校准 } ``` 2. **多核一致性**: - 通过 `clocksource_mask` 标记跨核一致的时钟源 - 读写锁保护全局状态:`seqlock_t timekeeper_lock` 3. **精度保障**: - TSC频率校准:`calibrate_tsc()` - 动态调整mult/shift:适应CPU频率变化 #### 四、用户空间应用 高精度计时示例: ```c #include <time.h> struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); // 起始时间 // 执行待测代码... clock_gettime(CLOCK_MONOTONIC, &end); // 结束时间 // 计算纳秒级耗时 long elapsed = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec); ``` #### 五、与相关技术的关系 1. **NTP/PTP 时间同步**: - 仅影响 `CLOCK_REALTIME` - 单调时间独立更新[^1] 2. **虚拟化支持**: - KVM 提供 `kvm-clock` 时钟源 - 保证虚拟机暂停期间单调时间连续 ### 总结 Monotonic Time 的实现本质是: 1. **硬件抽象**:通过 `clocksource` 统一访问计时硬件 2. **数学转换**:$$ T_{\text{ns}} = \frac{C_{\text{cycles}} \times \text{mult}}{2^{\text{shift}}} $$ 3. **增量更新**:严格通过加法维护单调性 4. **动态优化**:Tickless 模式降低开销 该机制为高性能计算、实时系统提供可靠时间基准,精度可达纳秒级。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值