【问题标题】:Simulate Multiple Virtual Timers with one Physical Timer用一个物理定时器模拟多个虚拟定时器
【发布时间】:2016-10-19 12:20:10
【问题描述】:

我正在尝试使用 C 实现选择性重复协议以进行网络分配,但对于如何为每个单独的数据包模拟计时器感到困惑。我只能访问一个计时器,并且只能调用如下所述的函数。

/* start timer at A or B (int), increment in time*/
extern void starttimer(int, double);       

/* stop timer at A or B (int) */
extern void stoptimer(int);             

黑濑和罗斯在他们的网络教科书中提到

可以使用单个硬件定时器来模拟 多个逻辑计时器的操作 [Varghese 1997]。

我发现了类似assignment的以下提示

您可以使用单个物理计时器模拟多个虚拟计时器。基本思想是,您保持一系列虚拟计时器按其到期时间排序,并且物理计时器将在第一个虚拟计时器到期时关闭。

但是,我无法访问除 RTT 之外的任何时间变量,因为模拟器位于另一抽象层上。在这种情况下如何实现单个数据包的计时器?

【问题讨论】:

  • 随心所欲地保留一个计数器数组。并在每个物理计时器滴答声中更新它们。此外,您可能希望为它们中的每一个添加一个单独的开始/停止指示器。

标签: c timer network-programming network-protocols


【解决方案1】:

您可以按照在内核级别实现的相同方式执行此操作。您需要有一个“计时器”的链接列表,其中每个计时器都有一个相对于前一个计时器的超时。它会是这样的: Timer1:从 t0 开始 500 ms,Timer2:从 t0 开始 400 ms,Timer3 从 t0 开始 1000 ms。

然后你会得到一个链表,其中每个元素都有相对于前一个元素的超时时间,如下所示:

HEAD->Timer2(400ms)->Timer1(100ms)->Timer3(500ms)

每个元素都包含最小值:timerID、相对超时、绝对初始化时间(从纪元开始的时间戳)。您可以为每个计时器添加一个回调指针。

您使用唯一的计时器并将超时设置为列表中第一个元素的相对超时:400ms (Timer2)

超时后,您将删除第一个元素,可能会执行与 Timer2 相关的回调,理想情况下,此回调由另一个工作线程执行。然后将新的超时设置为下一个元素的相对超时 Timer1: 100ms。

现在,当您需要创建一个新计时器时,例如在 3,000 毫秒,从 t0 开始 300 毫秒后,您需要将其插入到导航计时器链接列表的适当位置。 Timer4 中的相对超时时间为 2,300。这是用 (Timer2.RelativeTimeout - (now - Timer2.AbsoluteTimeout)) 计算的,并通过链表找到相应的位置,添加每个先前元素的相对超时。您的链接列表将变为:

HEAD->Timer2(400ms)->Timer1(100ms)->Timer3(500ms)->Timer4(2,300)

通过这种方式,您可以使用一个物理计时器实现多个逻辑计时器。您的计时器创建和查找时间将为 O(n),但您可以为插入性能添加各种改进。最重要的是定时器超时处理和更新是 O(1)。查找计时器的删除复杂度为 O(n),删除的复杂度为 O(1)。

您必须注意控制计时器的线程与插入或删除计时器的线程之间可能存在的竞争条件。在用户空间中实现此计时器的一种方法是使用条件变量和等待超时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 2013-02-28
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    相关资源
    最近更新 更多