调一个单片机通信的模拟程序,协议里要求两次读之间隔 500 微秒。我一开始写 sleep(1),结果一次睡了一整秒,程序慢得没法看。后来换成 usleep(500) 才对上。

usleep 的单位是微秒

usleep 的参数是微秒,1 微秒等于百万分之一秒。想要 500 微秒就传 500,想要 0.5 秒就传 500000。别和 sleep 搞混,sleep 的单位是整秒。它声明在 unistd.h 里,是 POSIX 提供的接口,Windows 上默认没有。

一个最容易忽略的限制

usleep 的参数类型是 useconds_t,实际能接受的延时有个上限。在老一点的实现里,参数必须小于 1000000,也就是不能超过一秒,超过会返回 -1 并设置 EINVAL。想睡更久就循环调用,或者改用 nanosleep。返回值也要看,成功返回 0,失败返回 -1,中断时 errno 会是 EINTR。

和几个兄弟函数的区别

  • sleep:单位秒,精度粗
  • nanosleep:单位纳秒,参数用 struct timespec,能睡任意时长
  • Windows 的 Sleep:单位是毫秒,注意首字母大写
  • 忙等待:精度最高但吃满 CPU,只在极短延时时用

实际精度没想象中高

usleep 只是让出 CPU,具体睡多久取决于系统调度粒度。Linux 默认时钟中断大约 1 毫秒一次,所以传 500 微秒,实际可能睡了 1 毫秒甚至更久。要测真实延时,用 clock_gettime 配 CLOCK_MONOTONIC 记时间差,别用 gettimeofday,它会受系统时间调整影响。

#include <unistd.h>
int ret = usleep(500);
if (ret == -1) perror('usleep');

结论:需要亚毫秒延时且对精度没苛刻要求,usleep 够轻便;真要稳定到微秒级,就得考虑忙等或者直接用硬件定时器。