Linux定时器接口

Linux定时器接口主要分为三类:

一. sleep(), unsleep, alarm(),引用了SIGALARM信号,在多线程中使用信号又是相当麻烦的。

二. nanosleep(), clock_nanosleep(),让线程挂起,程序失去响应,多线程网络编程中应该避免。

三. timerfd_create(),也是用信号来deliver超时,将时间转变成一个文件描述符,可以像其他I/O事件一样操作定时器,所以程序中在写I/O框架用到定时器首选timerfd_create()。

1. timerfd的创建

int timerfd_create(int clockid, int flags);//成功返回0

第一个参数为CLOCK_REALTIME:表示相对时间,表示从1970.1.1到现在的时间。或者CLOCK_MONOTONIC:表示绝对时间,表示系统重启到现在的时间。

第二个参数为TFD_NONBLOCK(非阻塞)或TFD_CLOEXEC(同O_CLOEXEC)。

2. 定时器的设置(启动和停止定时器)

int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspce *old_value);//成功返回0

第一个参数fd是timerfd_create创建的定时器文件描述符。

第二个参数如果是0表示相对定时器,为TFD_TIMER_ABSTIME表示绝对定时器。

第三个参数new_value设置超时时间,为0表示停止定时器。

第四个参数为原来的超时时间,一般设为NULL。

3. 代码实例:

//代码逻辑:创建timer等待时间,创建timer定时器文件描述符,创建epoll_event事件绑定timer,另起一线程等待事件。时间到,事件触发,操作map之前用mutex锁住,找到GroupID

#include <syso/timerfd.h>

#include <syso/epoll.h>

itimerspec timerValue;
memset(&timerValue, 0, sizeof(timerValue));
timerValue.it_value.tv_sec = tagCollection->GetSampleRate() / 1000;
timerValue.it_value.tv_nsec = (tagCollection->GetSampleRate() % 1000) * 1000 * 1000; // GetPublishInterval is in milliseconds
timerValue.it_interval.tv_sec = timerValue.it_value.tv_sec;
timerValue.it_interval.tv_nsec = timerValue.it_value.tv_nsec;

timerFd = timerfd_create(CLOCK_MONOTONIC, 0);
if (timerFd < 0)
{
  SYSO_CRIT("timer_create failed with error: %s", strerror(errno));
  return;
}
// set events
epoll_event epollEvent;
memset(&epollEvent, 0, sizeof(epoll_event));
epollEvent.events = EPOLLIN;
epollEvent.data.fd = timerFd;
epoll_ctl(epollFd, EPOLL_CTL_ADD, timerFd, &epollEvent); // this is thread safe
// start timer
if (timerfd_settime(timerFd, 0, &timerValue, nullptr) < 0)
{
  SYSO_NOTICE("timerfd_settime failed with error", strerror(errno));
}
else
{
  SYSO_INFO("PlcAdapterProxy Create Get Sample timer: ", timerFd, ", interval: ", timerValue.it_value.tv_sec, " seconds");
}

另起一线程等待epollfd

for(;;) // wait for events
{
  int eventCount = epoll_wait(epollFd, newEvents, MAX_TIMER_EVENTS, -1);
  if (eventCount > 0)
  {
    for (int i = 0; i < eventCount; ++i)
    {
      uint64_t clearEventDummy = 0;
      static_cast<void>(read(newEvents[i].data.fd, &clearEventDummy, sizeof(uint64_t))); // clears the event

      std::unique_lock<std::mutex> lock(epollToTimerIdMapMutex);
      auto iter = epollToTimerIdMap.find(newEvents[i].data.fd);
      if(iter != epollToTimerIdMap.end())
      {
        CollectionTimerElapsed(iter->second);
      }
    }
  }
  else
  {
    SYSO_CRIT("epoll_wait for timers failed, errno:%s", strerror(errno));
  }
}

原文地址:https://www.cnblogs.com/embeddedking/p/9689494.html

时间: 2024-10-09 11:28:45

Linux定时器接口的相关文章

【转】Linux 定时器setitimer()

http://blog.sina.com.cn/s/blog_590be5290100izdf.html 用法: #include <sys/time.h> int getitimer(int which, struct itimerval *value); int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); 功能描述: 获取或设定间歇计时器的值.系统为进程提供三种类型的计时器,每

Linux 定时器

也许,一本书你从头到尾都看完了,但也只是看完了. 也许,你似懂非懂的理解了. 但,当你准备用学来的这些东西做东西时,才发现:原来你根本没懂! 看书重要的不是看了多少,重要的是理解了多少,理解的多深多广! 一个傅里叶变换,一个小波,我怎么越看越晕? "学以致用"这四个字越来越被教育所忽视了. 如果不是图像处理我真不知道线性代数原来可以这么牛逼! ......................................... #include <stdio.h> #incl

Linux程序接口实验:取进程标志及用户信息

0.环境平台 操作系统平台: Linux leaf 4.4.0-75-generic #96-Ubuntu SMP Thu Apr 20 09:56:33 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 相关工具语言:vim,gcc,C语言 1.程序源代码 [email protected]:~/operation/1$ cat pflag.c  #include <unistd.h> #include <pwd.h> #include <sy

Linux定时器 使用

1.alarm alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数. #include <stdio.h>#include <unistd.h>#include <signal.h>void sigalrm_fn(int sig){    printf("alarm!\n");    alarm(2);    return;}int main(void){    s

Smart210学习记录-----linux定时器

1.内核定时器: Linux 内核所提供的用于操作定时器的数据结构和函数如下: (1) timer_list 在 Linux 内核中,timer_list 结构体的一个实例对应一个定时器 1 struct timer_list { 2    struct list_head entry; /* 定时器列表 */ 3    unsigned long expires; /*定时器到期时间*/ 4    void (*function)(unsigned long); /* 定时器处理函数 */ 5

[Linux] Linux smaps接口文件结构

在Linux内核 2.6.16中引入了一个系统内存接口特性,这个接口位于/proc/$pid/目录下的smaps文件中 ,一看内容发现是进程内存映像信息,比同一目录下的maps文件更详细些. 400df000-4048c000 r--s 00000000 1f:05 286 /data/dalvik-cache/[email protected]@[email protected] Size: 3764 kB Rss: 1804 kB Pss: 1804 kB Shared_Clean: 0 k

Linux定时器工具-crontab 各參数具体解释及怎样查看日志记录

要使用crontab定时器工具,必需要启动cron服务: service cron start crontab的语法,以备日后救急.先上张超给力的图: crontab各參数说明: -e : 运行文字编辑器来编辑crontab,内定的文字编辑器是VI -r : 删除眼下的crontab -l : 列出眼下的crontab(查看专用) -i : 会和-r 配合使用,在删除当前的crontab时询问,输入y 则删除 注意crontab是分用户的,以谁登录就会编辑到谁的crontab crontab特殊

linux定时器

我们常常有设置系统在某一时间执行相应动作的需求,比如设置电脑什么时候自动锁屏,什么时候自动关机,设置应用程序什么时候自动运行,什么时候自动退出.这些与时间相关的功能,都需要依靠操作系统中的定时器来实现. linux中定时器的使用原理很简单,你只需设置一个超时时间和相应的执行函数,系统就会在超时的时候执行一开始设置的函数.超时的概念有点模糊,它指的是你设定一个时间,如果当前的时间超过了你设定的时间,那就超时了.比如说,你设置五分钟后系统自动关机,系统会记住五分钟后的具体时间,也就是当前时间再加上五

linux定时器(crontab)实例

linux实验示例----实现每2分钟将“/etc”下面的文件打包存储到“/usr/lobal”目录下 ·Step1:编辑当前用户的crontab并保存终端输入:>crontab -u root -l #查看root用户设置的定时器>crontab -u root -e #进入vi编译模式 00-59/2 * * * * /bin/bash /usr/local/crontab_test.sh #Esc退出编辑模式,在文件尾部输入“:wq”进行保存 ·Step2:/usr/local目录下,编