本页详细介绍了在 Fuchsia 上开发软件时如何应对时间。
一般来说,您可以使用适用于您所用语言的任何时间库。大多数库都可以与 Fuchsia 的 libc 实现链接以获取时间。建议您使用与平台无关的库,除非 您需要 Fuchsia 特定时间操作。
您可以选择多种时间选项,例如:
语言 | Monotonic | 世界协调时间 (UTC) |
---|---|---|
C | clock_gettime |
time |
C++ | std::chrono::steady_clock |
std::chrono::system_clock |
Rust | std::time::Instant |
std::time::SystemTime |
紫红色特定时间操作
在某些情况下,您需要以 Fuchsia 特定方式处理时间。这个 在需要直接处理 Fuchsia 的时间表示形式时,此方法是必需的, 或者当您需要处理 特定于 Fuchsia 的 UTC 行为。
单调时间
Fuchsia 上的单调时间表示为一个 64 位有符号整数,其中包含系统开机以来经过的纳秒数。请参阅
如需了解详情,请访问 zx_clock_get_monotonic
。
中
单调时间可通过 libzircon 访问。
#include <stdio.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>
void monotonic_examples(void) {
// Read monotonic time.
zx_time_t mono_nsec = zx_clock_get_monotonic();
printf("The monotonic time is %ld ns.\n", mono_nsec);
}
C++
您可以通过 libzx 访问单调时间。
#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <stdio.h>
void monotonic_examples() {
// Read monotonic time.
zx::time monotonic_time = zx::clock::get_monotonic();
printf("The monotonic time is %ld ns.\n", monotonic_time.get());
}
Rust
您可以通过 zx crate 访问单调时间。此 crate 仅在树内可用。
pub fn monotonic_examples() {
// Read monotonic time.
let monotonic_time = zx::MonotonicInstant::get();
println!("The monotonic time is {:?}.", monotonic_time);
}
UTC 时间
在 Fuchsia 上,世界协调时间 (UTC) 表示为一个有符号的 64 位整数,其中包含 从 Unix 纪元(1970 年 1 月 1 日)开始所经过的纳秒数。
基于 UTC 时钟的操作需要获取 UTC 时钟句柄 提供给运行时。
直接处理 UTC 时钟会启用一些特定于 Fuchsia 的操作, 包括:
- 检查 UTC 时钟的属性。
等待 UTC 时钟开始运行(表示已同步)后再读取。
C
您可以使用 zx_utc_reference_get
获取对 UTC 时钟的句柄,并使用 libzircon 中公开的系统调用。
#include <stdio.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>
#include <zircon/utc.h>
void utc_examples(void) {
// This is a borrowed handle. Do not close it, and do not replace it using
// zx_utc_reference_swap while using it.
zx_handle_t utc_clock = zx_utc_reference_get();
if (utc_clock != ZX_HANDLE_INVALID) {
// Wait for the UTC clock to start. The clock may never start on a device
// that does not have a RTC or a network connection.
// A started clock may, but also may not have a valid UTC actual.
zx_status_t status = zx_object_wait_one(utc_clock, ZX_CLOCK_STARTED, ZX_TIME_INFINITE, NULL);
if (status == ZX_OK) {
printf("UTC clock is started.\n");
} else {
printf("zx_object_wait_one syscall failed (status = %d).\n", status);
}
// Wait for the UTC clock to be externally synchronized. Once that happens,
// the clock is known to correspond to UTC actual (with error bounds available through
// zx_clock_get_details).
status = zx_object_wait_one(utc_clock, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, NULL);
if (status == ZX_OK) {
printf("UTC clock is externally synchronized.\n");
} else {
printf("zx_object_wait_one syscall failed (status = %d).\n", status);
}
// Wait for the UTC clock to be of "logging quality". Logging quality UTC
// clock is started, but not necessarily corresponding to UTC actual. This
// clock is to be used only for logging timestamps.
status = zx_object_wait_one(utc_clock, ZX_USER_SIGNAL_1, ZX_TIME_INFINITE, NULL);
if (status == ZX_OK) {
printf("UTC clock is of logging quality.\n");
} else {
printf("zx_object_wait_one syscall failed (status = %d).\n", status);
}
// Read the UTC clock.
zx_time_t nsec;
status = zx_clock_read(utc_clock, &nsec);
if (status == ZX_OK) {
printf("It has been %ld ns since the epoch.\n", nsec);
} else {
printf("zx_clock_read syscall failed (status = %d).\n", status);
}
// Read UTC clock details.
zx_clock_details_v1_t details;
status = zx_clock_get_details(utc_clock, ZX_CLOCK_ARGS_VERSION(1), &details);
if (status == ZX_OK) {
printf("The UTC clock's backstop time is %ld ns since the epoch.\n", details.backstop_time);
} else {
printf("zx_clock_get_details failed (status = %d).\n", status);
}
} else {
printf("Error, our runtime has no clock assigned to it!\n");
}
}
C++
您可以使用 zx_utc_reference_get
获取对 UTC 时钟的句柄,并使用 libzx 中的系统调用封装容器。
#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <zircon/utc.h>
void utc_examples() {
// This is a borrowed handle. Do not close it, and do not replace it using
// zx_utc_reference_swap while using it.
zx_handle_t utc_clock_handle = zx_utc_reference_get();
zx::unowned_clock utc_clock(utc_clock_handle);
// Wait for the UTC clock to start. The clock may never start on a device
// that does not have a RTC or a network connection.
// A started clock may, but also may not have a valid UTC actual.
zx_status_t status = utc_clock->wait_one(ZX_CLOCK_STARTED, zx::time::infinite(), nullptr);
if (status == ZX_OK) {
printf("UTC clock is started.\n");
} else {
printf("Waiting for the UTC clock to start failed (status = %d).\n", status);
}
// Wait for the UTC clock to be externally synchronized. Once that happens,
// the clock is known to correspond to UTC actual (with error bounds available through
// `zx::Clock::get_details`).
status = utc_clock->wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr);
if (status == ZX_OK) {
printf("UTC clock is externally synchronized.\n");
} else {
printf("Waiting for the UTC clock to start failed (status = %d).\n", status);
}
// Wait for the UTC clock to be of "logging quality". Logging quality UTC
// clock is started, but not necessarily corresponding to UTC actual. This
// clock is to be used only for logging timestamps.
status = utc_clock->wait_one(ZX_USER_SIGNAL_1, zx::time::infinite(), nullptr);
if (status == ZX_OK) {
printf("UTC clock is of logging quality.");
} else {
printf("zx_object_wait_one syscall failed (status = %d).\n", status);
}
// Read the UTC clock.
zx_time_t utc_time;
status = utc_clock->read(&utc_time);
if (status == ZX_OK) {
printf("The UTC time is %ld ns since the epoch\n", utc_time);
} else {
printf("Reading the UTC clock failed (status = %d).\n", status);
}
// Read clock details.
zx_clock_details_v1_t details;
status = utc_clock->get_details(&details);
if (status == ZX_OK) {
printf("The UTC clock's backstop time is %ld ns since the epoch.\n", details.backstop_time);
} else {
printf("Reading the UTC clock details failed (status = %d).\n", status);
}
}
Rust
您可以使用 fuchsia_runtime crate 获取对 UTC 时钟的句柄,并使用 zx crate 中的系统调用封装容器。fuchsia_async crate 包含有助于等待时钟启动的实用程序。请注意,这些 crate 仅在树内可用。
use fuchsia_runtime::duplicate_utc_clock_handle;
use {fuchsia_async as fasync, zx};
pub async fn utc_examples() {
// Obtain a UTC handle.
let utc_clock = duplicate_utc_clock_handle(zx::Rights::SAME_RIGHTS)
.expect("Failed to duplicate UTC clock handle.");
// Wait for the UTC clock to start. The clock may never start on a device
// that does not have a RTC or a network connection.
// A started clock may, but also may not have a valid UTC actual.
fasync::OnSignals::new(&utc_clock, zx::Signals::CLOCK_STARTED)
.await
.expect("Failed to wait for ZX_CLOCK_STARTED.");
println!("UTC clock is started.");
// Wait for the UTC clock to be externally synchronized. Once that happens,
// the clock is known to correspond to UTC actual (with error bounds available through
// `zx::Clock::get_details`).
fasync::OnSignals::new(&utc_clock, zx::Signals::USER_0)
.await
.expect("Failed to wait for ZX_SIGNAL_USER_0.");
println!("UTC clock is externally synchronized.");
// Wait for the UTC clock to be of "logging quality". Logging quality UTC
// clock is started, but not necessarily corresponding to UTC actual. This
// clock is to be used only for logging timestamps.
fasync::OnSignals::new(&utc_clock, zx::Signals::USER_1)
.await
.expect("Failed to wait for ZX_SIGNAL_USER_1.");
println!("UTC clock is of logging quality.");
// Read the UTC clock.
let utc_time = utc_clock.read().expect("Failed to read UTC clock.");
println!("The UTC time is {:?}.", utc_time);
// Read UTC clock details.
let clock_details = utc_clock.get_details().expect("Failed to read UTC clock details.");
println!("The UTC clock's backstop time is {:?}.", clock_details.backstop);
}