【问题标题】:Timer library in C [closed]C中的定时器库[关闭]
【发布时间】:2012-09-17 16:35:00
【问题描述】:

我正在寻找一个用C编写的开源定时器库,该库应该有定时器回调函数等。

在搜索时,我看到 POSIX 计时器setitimer(),它们使用基于信号的方法,可能会导致多线程代码出现问题。

假设我在线程代码中使用 POSIX 计时器,信号将无法到达正确的位置。如果我在一个进程中使用多个计时器,那么每个计时器都应该使用不同的信号。还有其他选择吗?

【问题讨论】:

  • 解释为什么这会被否决/关闭通常会有所帮助。
  • 这获得了接近投票,因为它可能会引发辩论、争论、投票或扩展讨论。做一些研究,尝试使用一个或多个候选人,询问他们是否有问题。或者问,例如,我可以在多线程代码中使用 POSIX setitimer ...这是个好问题
  • 我回答了关于在线程代码中使用 POSIX 计时器的问题。是可以的,我把文档的相关部分给展示了。
  • 一个程序可以使用 timer_create() 创建多个间隔定时器。看我的回答。
  • 我最终使用了 macOS 上可用的 libdispatch,它也已移植到多个其他系统。

标签: c linux multithreading


【解决方案1】:

由于您运行的是 Linux,我建议您使用内置的 POSIX 计时器 API。

int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);

这里是一些documentation 的链接,展示了如何使用支持回调函数的 POSIX 计时器。

关于一个进程中的多个计时器,文档是这样说的:

   A program may create multiple interval timers using timer_create().

   Timers are not inherited by the child of a fork(2), and are disarmed and
   deleted during an execve(2).

   The kernel preallocates a "queued real-time signal" for each timer created
   using timer_create().  Consequently, the number of timers is limited by the
   RLIMIT_SIGPENDING resource limit (see setrlimit(2)).

请注意,通过使用 SIGEV_THREAD_ID 设置通知,可以在线程应用程序中使用 POSIX 计时器,如下所示:

The sevp.sigev_notify field can have the following values:

       SIGEV_NONE
              Don't asynchronously notify when the timer expires.  Progress of the
              timer can be monitored using timer_gettime(2).

       SIGEV_SIGNAL
              Upon timer expiration, generate the signal sigev_signo for the process.
              See sigevent(7) for general details.  The si_code field of the
              siginfo_t structure will be set to SI_TIMER.  At any point in time, at
              most one signal is queued to the process for a given timer; see
              timer_getoverrun(2) for more details.

       SIGEV_THREAD
              Upon timer expiration, invoke sigev_notify_function as if it were the
              start function of a new thread.  See sigevent(7) for details.

       SIGEV_THREAD_ID (Linux-specific)
              As for SIGEV_SIGNAL, but the signal is targeted at the thread whose ID
              is given in sigev_notify_thread_id, which must be a thread in the same
              process as the caller.  The sigev_notify_thread_id field specifies a
              kernel thread ID, that is, the value returned by clone(2) or gettid(2).
              This flag is only intended for use by threading libraries.

【讨论】:

  • 如果我在线程代码中使用 POSIX 定时器,信号将无法到达正确的位置。如果我在一个进程中使用多个定时器,那么每个定时器都应该使用不同的信号。还有其他选择吗?跨度>
  • 您可以使用 SIGEV_THREAD_ID 将通知设置为线程感知。所以计时器信号将转到您希望它转到的线程 ID。
  • "Here is a link to some documentation showing how to use POSIX timers which provide support for callback functions" - 在哪里?我看不到回调函数的任何提及
  • @Mawg 通过 sevp 结构的 sevp.sigev_notify 成员。
  • 你能详细说明一下吗?
【解决方案2】:

Linux 的做法是通过timerfd_create 与基于 epoll 的事件循环很好地集成(从而避免信号处理程序的限制)

【讨论】:

  • 想知道timefd的解析精度。
  • 和 timer_create 完全一样,因为底层基础设施是一样的——只是通知接口不同而已。
  • 谢谢!这正是我需要与 epoll_wait() 一起使用的,但我想我花了一个小时研究计时器和 epoll,而没有注意到其他人提到的这一点。非常感谢。
【解决方案3】:

要为其创建库非常简单。

示例:

#include <time.h>
int main()
{
    time_t start,end;
    double dif;
    double duration=40f; //duration of timer
    bool loop=true;
    while(loop==true)
    {
        time(&start);
        if(dif==duration)
        {
            /*callback*/
            dif=0;
        }
        //do stuff
        time(&end);
        dif+=difftime(end,start);
    }
{

【讨论】:

  • 简单的解决方案,但它并没有真正提供适当的回调机制。
  • 做到这一点并不难。我只是把这个想法扔在那里。
  • 使用定时器回调的重点是避免在每次迭代时检查时间! -1
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 2010-09-23
  • 2010-12-10
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多