You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust中实现Linux CLOCK_MONOTONIC式的绝对时间等待

在Rust中实现基于单调时钟的异步等待功能

需求背景

需要在Linux平台的Rust程序中,等待系统单调时钟(统计系统启动后的流逝时间)达到指定值,对应C语言的实现代码如下:

void sleep_until_monotonic(int64_t ts)
{
  int fd = timerfd_create(CLOCK_MONOTONIC, 0);

  struct itimerspec its = { .it_value = { .tv_sec = ts }};
  timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL);

  struct pollfd pfd = { .fd = fd, .events = POLLIN };
  poll(&pfd, 1, -1);
  close(fd);
}

期望的Rust异步API形式:

some_lib::sleep_until_monotonic(1234).await?

实现方案

1. Linux专属异步实现

直接调用Linux系统的timerfd系列API,结合Tokio的异步IO封装,实现无阻塞的异步等待:

依赖配置

在Cargo.toml中添加:

[dependencies]
tokio = { version = "1.0", features = ["full"] }
libc = "0.2"

代码实现

use libc::{c_long, timerfd_create, timerfd_settime, CLOCK_MONOTONIC, TFD_TIMER_ABSTIME, itimerspec, timespec};
use tokio::io::AsyncFd;
use std::os::unix::io::FromRawFd;
use std::io;

pub async fn sleep_until_monotonic(ts_sec: i64) -> io::Result<()> {
    // 创建基于单调时钟的timerfd
    let fd = unsafe { timerfd_create(CLOCK_MONOTONIC, 0) };
    if fd == -1 {
        return Err(io::Error::last_os_error());
    }

    // 设置绝对时间触发的定时器
    let its = itimerspec {
        it_value: timespec {
            tv_sec: ts_sec as c_long,
            tv_nsec: 0,
        },
        it_interval: timespec {
            tv_sec: 0,
            tv_nsec: 0,
        },
    };

    let res = unsafe {
        timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, std::ptr::null_mut())
    };
    if res == -1 {
        let err = io::Error::last_os_error();
        unsafe { libc::close(fd) };
        return Err(err);
    }

    // 异步等待timerfd可读(定时器触发)
    let mut async_fd = unsafe { AsyncFd::from_raw_fd(fd) };
    let _guard = async_fd.readable().await?;

    // 读取timerfd的计数,避免资源泄漏
    let mut buf = [0u8; 8];
    let _ = async_fd.read(&mut buf)?;

    Ok(())
}

2. 跨平台异步实现

使用time crate获取跨平台的单调时钟时间,结合Tokio的sleep实现异步等待,支持Linux、Windows、macOS等主流平台:

依赖配置

在Cargo.toml中添加:

[dependencies]
tokio = { version = "1.0", features = ["full"] }
time = { version = "0.3", features = ["std", "clock"] }

代码实现

use time::{Clock, Duration};
use tokio::time::sleep;
use std::io;

pub async fn sleep_until_monotonic(ts_sec: i64) -> io::Result<()> {
    let target_duration = Duration::seconds(ts_sec);
    // 获取当前单调时钟从系统启动到现在的流逝时长
    let now_duration = Clock::Monotonic.instant()?.duration_since_epoch()?;

    // 如果目标时间已过,直接返回
    if target_duration <= now_duration {
        return Ok(());
    }

    // 计算需要等待的时长并异步睡眠
    let wait_duration = target_duration - now_duration;
    sleep(wait_duration).await;

    Ok(())
}

内容的提问来源于stack exchange,提问作者jforberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:15:42