在程序中延迟或者等待一段时间一般可以使用Sleep函数实现,但是因为操作系统线程调度的消耗,往往只能做到十几或者数十毫秒的精度,很难达到微秒级,Golang的time.Sleep也是如此。

Sleep函数一般都会将当前线程从CPU让出,然后等待操作系统的重新调度,这样可以有效利用CPU资源,但也是Sleep时间精度不高的“罪魁祸首”。因为操作系统线程调度并不是实时的,它会先对线程排队,然后在合适的时机才进行真正的CPU切换,我们可以想象还会有队列优先级以及插队的情况存在。

那么如何才能降低到微秒级呢?本着有现成的就不造轮子的原则,我找遍了各个技术角落也没有找到,当然很可能有遗漏的地方。不过虽然没有Golang的实现,但是找到了一些C语言版本的延迟函数。参考它们,我实现了Golang的版本,代码如下:

func DelayMicroseconds(us int64) {
var tv syscall.Timeval
_ = syscall.Gettimeofday(&tv) stratTick := int64(tv.Sec)*int64(1000000) + int64(tv.Usec) + us
endTick := int64(0)
for endTick < stratTick {
_ = syscall.Gettimeofday(&tv)
endTick = int64(tv.Sec)*int64(1000000) + int64(tv.Usec)
}
}

  

你可能会说,这不就是一个死循环吗?!是的,这就是一个死循环,也因此它的名字是Delay,而不是Sleep。

这是目前找到的最好的实现方式了,虽然会导致CPU繁忙,但是也只是在短暂的微秒级别,有时候还是能接受的。

天空飘来五个字,那都不是事,是事也就烦一会,一会就没事。

这里边通过系统调用获取了精确到微秒级别的当前时间,然后通过循环不断获取当前时间,与deadline进行比较,在达到或超出deadline时跳出循环,最终实现了指定微秒的时间延迟。

经过实测这个函数在Linux上可以实现微秒级别的延迟,不过虽然Windows上也有Gettimeofday的系统调用,但是最低只能做到大概500us左右的延迟,通过看源码内部实现机制差别很大。

如果你有更好的方法,欢迎指正。


这段代码用在我编写的一个树莓派硬件驱动库中,如有兴趣欢迎拍砖:https://github.com/bosima/go-pidriver

Golang在Linux系统中实现微秒级延迟的更多相关文章

  1. 用户管理 之 Linux 系统中的超级权限的控制

    在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户 ...

  2. 【OS_Linux】Linux系统中目录及文件管理

    1.Linux系统中目录的树状结构 目录 /bin 存放二进制可执行文件(ls,cat,mkdir等),常用命令一般都在这里. /etc 存放系统管理和配置文件 /home 存放所有用户文件的根目录, ...

  3. Linux系统中的硬件问题如何排查?(1)

    在Linux系统中,对于硬件故障问题的排查可能是计算机管理领域最棘手的工作,即使是经验相当丰富的用户有时也会遇上自己搞不定的状况,本文分享一些实用的技巧与处理方法,希望有助于读者朋友理解.查明并最终搞 ...

  4. Linux系统中的Page cache和Buffer cache

    Linux系统中的Page cache和Buffer cache Linux中有两个很容易混淆的概念,pagecache和buffercache,首先简单将一些Linux系统下内存的分布,使用free ...

  5. Linux系统中安装软件方法总结

    Linux系统中安装软件方法总结 [1]Linux系统中安装软件的几种方式 [2] Linux配置yum源(本地源和网络源) [3] SuSE下zypper源配置 [4] SUSE zypper 本地 ...

  6. 『学了就忘』Linux服务管理 — 75、Linux系统中的服务

    目录 1.服务的介绍 2.Windows系统中的服务 3.Linux系统中服务的分类 4.独立的服务和基于xinetd服务的区别 5.如何查看一个服务是独立的服务还是基于xinetd的服务 (1)查看 ...

  7. Linux系统中的Device Mapper学习

    在linux系统中你使用一些命令时(例如nmon.iostat 如下截图所示),有可能会看到一些名字为dm-xx的设备,那么这些设备到底是什么设备呢,跟磁盘有什么关系呢?以前不了解的时候,我也很纳闷. ...

  8. 在linux系统中安装VSCode(Visual Studio Code)

    在linux系统中安装VSCode(Visual Studio Code) 1.从官网下载压缩包(话说下载下来解压就直接可以运行了咧,都不需要make) 访问Visual Studio Code官网  ...

  9. Linux 系统中的MySQL数据库默认区分大小写

    今天在开发中遇到这么个问题,将连接的数据库改为服务器上的时候(服务器是Linux系统的),程序跑起来后一直出错,总提示数据库的表找不到, 而打开数据库看该表明明是存在的,在我的印象中MySQL数据是不 ...

随机推荐

  1. Spring学习总结(一)---谈谈对Spring IOC的理解(一:理论知识理解)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  2. FTP传输

    FTP传输                    一.FTP服务–用来传输文件的协议                    二.设置匿名用户访问的FTP服务(最大权限)                 ...

  3. Token验证详解

    为什么使用Token验证: 在Web领域基于Token的身份验证随处可见.在大多数使用Web API的互联网公司中,tokens 是多用户下处理认证的最佳方式. 以下几点特性会让你在程序中使用基于To ...

  4. 单细胞分析实录(17): 非负矩阵分解(NMF)代码演示

    本次演示使用的数据来自2017年发表于Cell的头颈鳞癌单细胞文章:Single-Cell Transcriptomic Analysis of Primary and Metastatic Tumo ...

  5. Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第九集-补充-热部署项目到tomcat中,但是数据库配置文件错误,中途停止部署,导致执行shutdow.sh报错异常: Could not contact localhost:8005. Tomcat may not be running error while shutting down】

    1,经过千辛万苦的尝试和百度,终于一个博客:http://stackmirror.caup.cn/page/skxugjqj0ldc关于catalina.sh文件的执行引起了我的注意: 2,我执行ca ...

  6. war项目依赖war项目

    还没有看,立个flag:https://my.oschina.net/u/588379/blog/1817077

  7. DNS Bind日志详述

    简介 在默认情况下,BIND9 把日志消息写到 /var/log/messages 文件中,而这些日志消息是非常少的,主要就是启动,关闭的日志记录和一些严重错误的消息:而将调试日志信息写入 BIND ...

  8. div填满页面剩余空间的方法

    想让div填满页面剩余空间,最简易的方式还是靠提前的布局. 这里提供两种方法: (1)利用 height 样式的%比例设置布局 <!DOCTYPE html> <html lang= ...

  9. 构建前端第2篇之--ESLint 配置

    张艳涛 写于2021-1-19 报错: http://eslint.org/docs/rules/space-before-function-paren Missing space before fu ...

  10. 漫谈CUDA优化

    ​ 作者:Lawliet 翻译:仿佛若有光 前言: 几个月前,我根据 Simoncelli 2016 年的论文编写了自己的自动编码器,用于研究目的.一开始,我想使用一些流行的深度学习框架(例如 Ten ...