> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-yi-bu-fen-gai-lan/3.5.-ji-shi.md).

# 3.5 计时

内核为进程提供几种不同的计时服务，包括按真实时间运行的计时器和只在进程执行期间运行的计时器。

**真实时间**

系统调用 `gettimeofday` 返回系统当前协调世界时（UTC）和当前时区。今天的多数处理器（包括所有 VAX 处理器）都有一个带电池后备的当日时刻寄存器；处理器断电后这个时钟也继续走。系统引导时，查询处理器的当日时刻寄存器得知当前时刻。此后系统时间由 hardclock 中断维护：每次中断，系统把全局时间变量增加每节拍的微秒数。VAX 以每秒 100 次节拍运行，每个节拍代表 10,000 微秒。系统若丢失 hardclock 中断，内部时钟就会变慢。要避免这种情况，时钟中断必须以高优先级进行，而且必须尽快完成。

**调整时间**

人们常常希望网络上所有机器保持同一时间，也可能希望得到比处理器基本时钟更准的时间。例如，收听 WWV（在美国广播 UTC 同步信号的一组电台）的设备很容易得到。一组经网络通信的进程可以约定一个共同时间，然后希望把主机处理器的时钟调得与全网时基一致。一种办法是用 `settimeofday` 系统调用把系统时间设为网络时间。对于时钟偏快的机器，这会导致时间倒退，让期待时间只增不减的用户程序（如 **make**）晕头转向。为避免这个问题，系统提供了 `adjtime` 系统调用来调整时间 \[Gusella et al., 1986]。这个系统调用接受一个可正可负的时间差，把时间推进的速率相应加快或放慢 10%，直到调整完成。加快时每个 hardclock 节拍给全局时间加 11,000 微秒；放慢时加 9,000 微秒。两种情况下时间都单调递增，依赖文件修改时间顺序的用户进程不受影响。耗时几十秒的调整会影响那些靠反复调用 `gettimeofday` 度量时间间隔的程序。

**外部表示**

内核内部以自 1970 年 1 月 1 日 UTC 以来的微秒数维护时间。时间从系统导出时总是用微秒数而不用时钟节拍，以提供与分辨率无关的格式。内核内部可以随意选择节拍率，在时钟开销与计时器分辨率之间权衡。每秒节拍率越高，接应 hardclock 中断所花的时间越多；但节拍率越高，系统计时器的分辨率越细。随着处理器变快，节拍率可以提高，计时分辨率更细，又不会妨害现有的用户应用。

系统有一个编译时内置的值指明机器所在的时区，还有一个魔数指明是否使用夏令时算法及用哪一种。内核内部所有时间戳都以 UTC 维护，到本地时间的转换在内核之外由 C 库处理。有一个库例程向内核询问时区和夏令时算法编号，由它按本地约定转换内核时间戳。

传统 UNIX 的时区处理（包括 4.3BSD 的）有问题：规则编译在 C 库里，二进制发行版无法更改，源码发行版也难改。内置的规则集对许多使用 UNIX 系统的地方并不完整或不准确。4.3BSD 里用户也不能按进程设置想要的时区。

CSRG 在 4.3BSD Tahoe 发行版中首次发布的 Olson 时区处理方法（见 1.2 节）避开了这些问题：把规则放进数据库文件，允许单个进程通过指定规则集来选择一套规则。这个方法极其灵活，能应对同一年内多次改规则（例如提议中的美国总统选举时间——西海岸只在那一天提前 3 小时）、大于 1 小时的偏移（第二次世界大战用过的双重夏令时）或小于 1 小时的偏移（如纽芬兰），甚至太阳时（如沙特阿拉伯）。不过偏移仍以秒计，因为连太阳时也不需要更高精度。缺的规则可以在目的地补上，时区规则后来的真实世界变动（时有发生、几无预告）也可如法炮制。

**间隔时间**

系统为每个进程提供三个间隔计时器。实时（real）计时器按真实时间递减，可供库例程用来维护一个唤醒服务队列；它到期时投递 SIGALRM 信号。如 3.1 节所述，实时计时器由 `softclock()` 例程维护的超时队列驱动。

**剖析**

剖析（profiling）计时器在进程虚拟时间（用户态运行）和系统为进程运行时都递减，为进程对自己的执行做统计剖析而设计；它到期时投递 SIGPROF 信号。剖析计时器由 `hardclock()` 例程实现：每次运行都检查当前进程是否请求了剖析计时器；若有，`hardclock()` 递增该计时器，达到间隔就给进程发信号。

虚拟（virtual）计时器按进程虚拟时间递减，只在进程以用户态执行时走动；它到期时投递 SIGVTALRM 信号。虚拟计时器在 `hardclock()` 里的实现与剖析计时器如出一辙，只是仅当当前进程在用户态执行（而不是在内核中运行）时才递增计时器。

正常情况下，系统中所有与时间相关的事件都走同一个时钟，于是统计采集与重调度同时发生。这可能造成异常的统计结果，对那些由系统计时事件驱动的进程尤甚。为能采集更准的统计，内核支持第二个剖析时钟。有第二个时钟可用时，它被设为与主系统时钟节拍率互素的速率（VAX 上每秒 109 次）。统计采集改由这个备用时钟完成，计时和调度仍由原来的时钟承担。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-yi-bu-fen-gai-lan/3.5.-ji-shi.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
