非实时系统精确定时器的实现

我们通常使用的系统,不管是linux还是windows,都是非实时系统。非实时系统可以获得很精确的当前时间,甚至可以通过读取cpu的某些寄存器得到以cpu周期计数的时钟,估计除了GPS系统之外足以应付我们日常能够碰到的应用,但是,非实时系统并没有提供精确的定时器实现。如果在linux或者windows系统中使用系统定时器,尽管我们可以创建精度为1ms甚至更小的定时器,但是实际执行的时候可以发现,定时器总是需要几ms甚至十几ms才会被调度一次,而不能达到期望的精度。

通常情况下10ms量级的定时器可以满足应用的需求,但一些特殊场景下10ms就显得太长了,比如我碰到过一个场景,在一个单向网络上将数据推动到一台设备上,推送速率大约100Mbps量级。如果每10ms推送一次,那么每次推送的数据量大约是1Mb,可是那个接收设备比较老,没有这么大的接收buffer,很容易造成丢包,而单向网络上是没有办法进行数据重传的,如果我们降低一次推送的数据量,那么总体的传输效率就会相应下降。因此,唯一可行的方法是我们根据接收设备的IO大小,尽可能“平滑”的进行数据的推送,我们需要更精细的时钟对推送行为进行控制。

对于linux系统,理论上我们可以重新编译内核,减少系统时钟的调用间隔,但这样做动静太大,可能影响许多系统模块的运行,存在风险,我们还是期望能够在应用层解决问题。经过尝试,最终我们找到了问题的解决方案:

感谢cpu厂商为我们提供的多核系统,我们牺牲一个内核,在这个核上跑一个忙等待的检查线程,它的作用就是用死循环的方式不断的读取系统时间,并通知推送线程(可以是多个)是否可以启动推送。推送线程平时等待在一个信号量上,当时间到期之后,检查线程置位信号量,推送线程被激活并进行推送。按照这个方式,我们可以实现几乎任意精度的定时器。

这个方案的缺点是有一个cpu内核被浪费了,好在服务器一般都有4、8甚至16个内核,浪费一个核的代价还是可以接受的。

注:我们为该方案申请了专利并已经获得授权,专利名称:一种在非实时系统上精确网络限速的方法,授权号CN102368729B。

时间: 2024-11-05 13:36:23

非实时系统精确定时器的实现的相关文章

select实现精确定时器

select实现精确定时器 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); struct timeval { long tv_sec; long tv_usec; } /* seconds and microseconds */ 秒级定时器 void sec_sleep(unsigned sec) {     int err;     stru

iOS 精确定时器

Do I need a high precision timer? Don't use a high precision timer unless you really need it. They consume compute cycles and battery. There can only be a limited number of high precsion timers active at once. A high precision timer is "first in line

精确获取时间(QueryPerformanceCounter)

LARGE_INTEGER tima,timb; QueryPerformanceCounter(&tima); 在 Windows Server 2003 和 WindowsXP 中使用 QueryPerformanceCounter 函数的程序可能执行不当 QueryPerformanceCounter 來精確計算執行時間QueryPerformanceCounter 來精確計算執行時間// 這個程式展示了如何使用QueryPerformanceCounter 來精確計算執行時間//代码 1

定时器的使用

定时器(Timer)在 Windows 的程序设计中很多地方都能用到,他的主要用途是按程序的设定间隔时间,间歇性的产生 WM_TIMER 消息,发送到指定窗口 之后,在窗口中对 WM_TIMER 消息进行处理,完成指定的任务! ①.定时器函数的讲解: ◆ 定时器启动函数:SetTimer UINT SetTimer( UINT nIDEvent, //定时器标识 UINT nElapse, //定时器间隔 void (CALLBACK EXPORT* lpfnTimer)(HWND, //定时器

使用定时器SetTimer

//创建定时器函数的声明:SetTimer( hWnd: HWND; {与定时器相关联的窗口句柄} nIDEvent: UINT; {指定一个非 0 的定时器标识符} uElapse: UINT; {指定间隔时间, 单位是毫秒} lpTimerFunc: TFNTimerProc {每到时间后, 要调用的函数的指针}): UINT; {返回定时器标识符; 失败返回 0} //移除定时器函数的声明:KillTimer( hWnd: HWND; {与定时器相关联的窗口句柄} uIDEvent: UI

TCP/IP具体解释学习笔记--TCP的坚持和保活定时器

TCP的坚持定时器 1.基本概念 TCP的接收方指名希望从发送方接收的数据字节(窗体大小)来进行流量控制,假设窗体大小为0.那么放送方就会阻止发送数据,直到接收方发来一个已跟新窗体大小的ACK为止,那么假设接收方发送的这个ACK中途丢失了呢(这样的可能性是有的)?此时发送方收不到信息,就默认窗体大小还为0,那它就继续堵塞在那,这样就造成了死锁. 那么怎样解决此类问题呢,解决方式就是我此片博文的题目.TCP的坚持定时器.为了防止上述死锁的发生.TCP的发送方使用了一个坚持定时器.来周期性的向接收方

MFC的定时器OnTimer

本文总结来源出自鸡啄米,感谢鸡啄米.来源:http://www.jizhuomi.com/software/232.html 定时器简介 定时器,可以帮助开发者或者用户定时完成某项任务.在使用定时器时,我们可以给系统传入一个时间间隔数据,然后系统就会在每个此时间间隔后触发定时处理程序,实现周期性的自动操作.例如,我们可以在数据采集系统中,为定时器设置定时采集时间间隔为1个小时,那么每隔1个小时系统就会采集一次数据,这样就可以在无人操作的情况下准确的进行操作.  MFC定时器 VS2010编程中,

TCP/IP详解学习笔记--TCP的坚持和保活定时器

TCP的坚持定时器 1.基本概念 TCP的接收方指名希望从发送方接收的数据字节(窗口大小)来进行流量控制,如果窗口大小为0,那么放送方就会阻止发送数据,直到接收方发来一个已跟新窗口大小的ACK为止,那么如果接收方发送的这个ACK中途丢失了呢(这种可能性是有的)?此时发送方收不到信息,就默认窗口大小还为0,那它就继续阻塞在那,这样就造成了死锁.那么如何解决此类问题呢,解决方案就是我此片博文的题目,TCP的坚持定时器.为了防止上述死锁的发生,TCP的发送方使用了一个坚持定时器,来周期性的向接收方查询

Windows中7种定时器(VC定时器种类及占用资源对比)

VC中提供了很多关于时间操作的函数,利用它们控制程序能够精确地完成定时和计时操作.本文详细介绍了VC中基于Windows的精确定时的七种方式,如下图所示: 图一 图像描述 方式一:VC中的WM_TIMER消息映射能进行简单的时间控制.首先调用函数SetTimer()设置定时间隔,如SetTimer(0,200,NULL)即为设置200ms的时间间隔.然后在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成到达定时时间的操作.这种定时方法非常简单,可以实现一定的