struct sigevent与定时器

介绍

最强大的定时器接口来自POSIX时钟系列,其创建、初始化以及删除一个定时器的行动被分为三个不同的函数:timer_create()、timer_settime()、timer_delete()

创建定时器

**int timer_create(clockid_t clock_id, struct sigevent evp, timer_t timerid)

  1. clock_id说明定时器属于的时钟序号,*timerid装载的是被创建的定时器ID。函数创建一个定时器并指向timerid。

  2. 参数evp指定定时器到期产生的异步通知,evp为NULL则产生默认信号。若要产生非默认信号,则设置

    evp->sigev_signo为期望新号码,evp->sigev_notify为通知行动。通常sigev_notifySIGEV_SIGNAL,说明到期时产生一个新号。程序可以将其设置为SIGEV_NONE来防止定时器到时产生信号;

  3. 如果几个定时器产生了同一信号,处理程序可以用evp->sigev_value来区分。要实现这种功能,程序必须在为信号安装处理程序时,使用struct sigaction的成员sa_flags中的标志SA_SIGINFO

  4. clock_id取值CLOCK_REALTIME时为系统真实时间;

  5. sigenv结构体

    struct sigevent
    {
     int sigev_notify;   // notifiction type
        int sigev_signo; // signal number
        union sigval sigev_value;    // signal value
        void (*sigev_notify_function)(union sigval); // sigev_notify=SIGEV_THREAD
        pthread_attr_t *sigev_notifiction_attributes;
    }
    
    union sigval
    {
        int sigval_int;      //  integer value
        void *sigval_ptr;    //  pointer value
    }
    

    sigev_notify = SIGEV_NONE时只提供通过timer_gettimetimer_getoverrun查询超时信息;

    sigev_notify = SIGEV_SIGNAL当定时器超时内核将sigev_signo所指定的新号传送给进程。在信号处理程序中,si_val会被设置成sigev_value

    sigev_notify = SIGEV_THREAD当定时器到期内核会在此进程内以sigev_notifiction_attributes为线程参数创建一个线程,并且执行sigev_notify_function,传入sigev_value作为一个参数。

启动一个定时器

int timer_settime(timer_t timerid, int flags, const struct itimerspec * value, struct itimerspec ovalue)
timer_create()创建的定时器并未启动,将它关联到一个到期时间以及启动始终周期,可以使用
timer_settime()*

  1. itimespec结构体

    struct itimespec
    {
        struct timespec it_interval;
        struct timespec it_value;
    }
    

    it_value用于指定当前定时器到期时间。当定时器到期,则it_value会被更新为it_interval的值。若it_interval为0则定时器不是一个时间间隔定时器,一旦it_value到期就回到未启动的状态。

  2. timespec结构体提供了纳秒级别分辨率:

    struct timespec
    {
        timet_t tv_sec;
        long tv_nsec;
    }
    

    ovalue不是NULL,则之前的定时器到期时间会被存入ovalue。如果定时器之前处于未启动的状态,则此结构成员都为0。

获得一个活动定时器的剩余时间

*int timer_gettime(timer_t timerid, struct itimierspec value)

取得定时器的超限运行次数

int timer_getoverrun(timer_t timerid)

  1. 有可能一个定时器到期了,而这个定时器上一次产生的新号还处于挂起状态。这种情况下,其中的一个新号可能会丢失。这就是定时器超限。
  2. 通过调用timer_getoverrun()函数来确定定时器超限次数。超限只出现在同一定时器上,多个定时器产生信号会排队而不会丢失。

删除定时器

int timer_delete(timer_t timerid)

执行成功返回0,失败返回-1并将errno设为EINVAL,这个唯一的错误情况代表timerid不是一个有效定时器。

示例

int create_suicide_timeout(int sec_to_suicide)
{
        timer_t timerid;
        struct sigevent sev;
        sigset_t mask;
        struct itimerspec its;
        struct sigaction sa;

        sa.sa_sigaction = suicide_timeout_handler;
        sigemptyset(&sa.sa_mask);
        if (sigaction(SIGRTMIN, &sa, NULL) == -1) {
                perror("sigaction");
                return -1;
        }

        sigemptyset(&mask);
        sigaddset(&mask, SIGRTMIN);
        if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
                perror("sigprocmask(SIG_SETMASK)");
                return -1;
        }

        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_signo = SIGRTMIN;
        sev.sigev_value.sival_ptr = &timerid;
        if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
                perror("timer_create");
                return -1;
        }

        its.it_value.tv_sec = sec_to_suicide;
        its.it_value.tv_nsec = 0;
        its.it_interval.tv_sec = its.it_value.tv_sec;
        its.it_interval.tv_nsec = its.it_value.tv_nsec;
        if (timer_settime(timerid, 0, &its, NULL) == -1) {
                perror("timer_settime");
                return -1;
        }

        if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) {
                perror("sigprocmask(SIG_UNBLOCK)");
                return -1;
        }
        return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351