免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6398 | 回复: 9
打印 上一主题 下一主题

linux用户空间有没有类似add_timer这种定时器函数? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-04-23 15:42 |只看该作者 |倒序浏览
本帖最后由 frank529 于 2012-04-23 16:08 编辑

网上找了下,都是调用setitimer函数用ITIMER_REAL定时器触发SIGALRM信号,貌似不适用于多个定时器的场景,而且使用信号也会导致某些系统调用返回负值。不知道有没有类似于内核定时器add_timer那种函数,可以注册定时触发函数,可以配置触发时间?

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
2 [报告]
发表于 2012-04-23 16:03 |只看该作者
回复 1# frank529
网上找了下,都是调用setitimer函数用ITIMER_REAL触发SIGALRM信号,貌似不适用于多个定时器的场景,而且使用信号也会导致某些系统调用返回负值。不知道有没有类似于内核定时器add_timer那种函数,可以注册定时触发函数,可以配置触发时间?

你可以用setitimer自己封装一个类似add_timer的库函数。这个库应该比较容易实现,比如在setitimer中根据注册的函数或者进程,执行不同的操作,从而实现类似add_timer的功能。当然这个库还可以有别的方法实现,但基本上离不开setitimer。

   

论坛徽章:
0
3 [报告]
发表于 2012-04-23 16:08 |只看该作者
瀚海书香 发表于 2012-04-23 16:03
回复 1# frank529

你可以用setitimer自己封装一个类似add_timer的库函数。这个库应该比较容易实现,比如 ...


如果我一个进程要用多个定时器,都是ALARM信号,怎么判断执行哪个函数?Linux怎么连定时器这么重要的接口都不提供啊,还要自己封装太不方便了

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
4 [报告]
发表于 2012-04-23 16:17 |只看该作者
回复 3# frank529
如果我一个进程要用多个定时器,都是ALARM信号,怎么判断执行哪个函数?

这个应该不难实现的。临时想了一下,提供一种方法(效率等方面没有考虑):
用一个链表timer_list存储所有的需要定时处理的函数,同时存储定时时间time_val = time_val_init。
设置setitimer的超时时间为所有定时器的最大公约数time_gcd,每当setitimer到期后,遍历timer_list链表,同时time_val -= time_gcd;如果time_val == 0,调用相应的函数,同时设置time_val = time_val_init.

   

论坛徽章:
0
5 [报告]
发表于 2012-04-23 16:51 |只看该作者
回复 4# 瀚海书香


    对,在信号处理函数里去判断哪个定时器到期,然后再去执行相应函数。只是这样对代码效率要求很高啊,不然就影响精度了。Linux应该提供一个定时器的系统调用接口,就用内核那套现成的定时器管理机制,应该不难实现。谢谢版主的回复。

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
6 [报告]
发表于 2012-04-24 08:50 |只看该作者
本帖最后由 linuxfellow 于 2012-04-24 09:16 编辑

回复 3# frank529
其他可能方法:
1。 把进程细化成多线程,一个线程只接收一个信号,干一件事.
2。 不同timer发送custom信号量SIGUSR1/SIGUSR2,进程decode这些信号量执行不同函授。
   

论坛徽章:
0
7 [报告]
发表于 2012-04-24 10:00 |只看该作者
应用层很多库都有timer事件支持的,libev  ,asio 等网络库都有,

论坛徽章:
0
8 [报告]
发表于 2012-04-24 16:27 |只看该作者
The Atheme projects
http://www.atheme.org/project/mowgli

libmowgli
A useful collection of routines for programming. Performance and usability-oriented extensions to C.


libmowgli Contains:
mowgli_alloc: A safe wrapper around malloc/free.
mowgli_argstack: Safe serialization of valists.
mowgli_assert: Various assertion routines that can be used.
mowgli_bitvector: Bitmasks with an unlimited level of precision.
mowgli_dictionary: A keyword-backed definition hashtable class.
mowgli_error_backtrace: Provide feedback to users on what caused the error they are recieving.
mowgli_exception: Assertions with user feedback.
mowgli_formatter: A simple token formatter which is sometimes useful.
mowgli_global_storage: A simple global storage library.
mowgli_hash: A portable implementation of the FNV-1 hash.
mowgli_heap: An optimistic heap-based memory allocator.
mowgli_hook: A simple hooks API you can use for your application, which allows for hooks to provide both application data and user data.
mowgli_ioevent: Portable I/O completion ports for many OSes.
mowgli_list: A high performance linked lists implementation with O(1) scalability for most common operations.
mowgli_logger: An internal class for handling logging of exceptions.
mowgli_memorypool: A class which allows for memory pooling.
mowgli_module: A wrapper around dlopen(3) and dlsym(3).
mowgli_object: A simple class which provides reference counted pointers and polymorphism of structs.
mowgli_object_class: Classing and subclassing for objects.
mowgli_object_metadata: Metadata for objects.
mowgli_object_messaging: Messaging and signalling for objects.
mowgli_queue: A simple class which implements double-ended queues.
mowgli_random: A high performance psuedo-random number generator.
mowgli_signal: A wrapper for sigaction(2).
mowgli_spinlock: Portable spinlocks.

小库,就20几个文件
你可以参考它的事件循环处理代码,看下它的封装。

libmowgli-2.0.0/src/libmowgli/eventloop# cat timer.c


/*
* Copyright (c) 2011 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2005-2007 Atheme Project (http://www.atheme.org)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "mowgli.h"

static mowgli_heap_t *timer_heap = NULL;

static mowgli_eventloop_timer_t *mowgli_timer_add_real(mowgli_eventloop_t *eventloop,
        const char *name, mowgli_event_dispatch_func_t *func, void *arg, time_t when, time_t frequency)
{
        mowgli_eventloop_timer_t *timer;

        return_val_if_fail(eventloop != NULL, NULL);
        return_val_if_fail(func != NULL, NULL);

        if (timer_heap == NULL)
                timer_heap = mowgli_heap_create(sizeof(mowgli_eventloop_timer_t), 16, BH_NOW);

        timer = mowgli_heap_alloc(timer_heap);

        timer->func = func;
        timer->name = name;
        timer->arg = arg;
        timer->when = mowgli_eventloop_get_time(eventloop) + when;
        timer->frequency = frequency;
        timer->active = true;

        if (eventloop->deadline <= mowgli_eventloop_get_time(eventloop) || timer->when <= eventloop->deadline)
                eventloop->deadline = timer->when;

        mowgli_node_add(timer, &timer->node, &eventloop->timer_list);

#ifdef DEBUG
        mowgli_log("[timer(%p) add when:%d active:%d] [eventloop deadline:%d]", timer, timer->when, timer->active, eventloop->deadline);
#endif

        return timer;
}

/* add an event to the table to be continually ran */
mowgli_eventloop_timer_t *mowgli_timer_add(mowgli_eventloop_t *eventloop, const char *name, mowgli_event_dispatch_func_t *func, void *arg, time_t when)
{
        return mowgli_timer_add_real(eventloop, name, func, arg, when, when);
}

/* adds an event to the table to be ran only once */
mowgli_eventloop_timer_t *mowgli_timer_add_once(mowgli_eventloop_t *eventloop, const char *name, mowgli_event_dispatch_func_t *func, void *arg, time_t when)
{
        return mowgli_timer_add_real(eventloop, name, func, arg, when, 0);
}

/* delete an event from the table */
void mowgli_timer_destroy(mowgli_eventloop_t *eventloop, mowgli_eventloop_timer_t *timer)
{
        return_if_fail(eventloop != NULL);
        return_if_fail(timer != NULL);

        if (eventloop->last_ran == timer->name)
                eventloop->last_ran = "<removed>";

        mowgli_node_delete(&timer->node, &eventloop->timer_list);
        mowgli_heap_free(timer_heap, timer);
}

/* checks all pending events */
void mowgli_eventloop_run_timers(mowgli_eventloop_t *eventloop)
{
        mowgli_node_t *n, *tn;
        time_t currtime;

        return_if_fail(eventloop != NULL);

        currtime = mowgli_eventloop_get_time(eventloop);

        MOWGLI_ITER_FOREACH_SAFE(n, tn, eventloop->timer_list.head)
        {
                mowgli_eventloop_timer_t *timer = n->data;

                if (timer->active && timer->when <= currtime)
                {
                        /* now we call it */
                        eventloop->last_ran = timer->name;
                        timer->func(timer->arg);

                        /* invalidate eventloop sleep-until time */
                        eventloop->deadline = -1;

                        /* event is scheduled more than once */
                        if (timer->frequency)
                                timer->when = currtime + timer->frequency;
                        else
                        {
                                /* XXX: yuck.  find a better way to handle this. */
                                eventloop->last_ran = "<onceonly>";

                                mowgli_timer_destroy(eventloop, timer);
                        }
                }
        }
}

/* returns the time the next mowgli_timer_run() should happen */
time_t mowgli_eventloop_next_timer(mowgli_eventloop_t *eventloop)
{
        mowgli_node_t *n;

        return_val_if_fail(eventloop != NULL, 0);

        if (eventloop->deadline == -1)
        {
                MOWGLI_ITER_FOREACH(n, eventloop->timer_list.head)
                {
                        mowgli_eventloop_timer_t *timer = n->data;

                        if (timer->active && (timer->when < eventloop->deadline || eventloop->deadline == -1))
                                eventloop->deadline = timer->when;

#ifdef DEBUG
                        mowgli_log("timer %p active:%d when:%ld deadline:%ld", timer, timer->active, timer->when, eventloop->deadline);
#endif
                }
        }

#ifdef DEBUG
        mowgli_log("eventloop deadline:%ld", eventloop->deadline);
#endif

        return eventloop->deadline;
}

/* finds an event in the table */
mowgli_eventloop_timer_t *mowgli_timer_find(mowgli_eventloop_t *eventloop, mowgli_event_dispatch_func_t *func, void *arg)
{
        mowgli_node_t *n;

        return_val_if_fail(eventloop != NULL, NULL);
        return_val_if_fail(func != NULL, NULL);

        MOWGLI_ITER_FOREACH(n, eventloop->timer_list.head)
        {
                mowgli_eventloop_timer_t *timer = n->data;

                if (timer->func == func && timer->arg == arg)
                        return timer;
        }

        return NULL;
}

/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
* vim:ts=8
* vim:sw=8
* vim:noexpandtab
*/

论坛徽章:
0
9 [报告]
发表于 2012-04-25 10:01 |只看该作者
回复 8# 251316192


    挺有用的库,谢谢LS分享

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:17
10 [报告]
发表于 2012-04-25 13:32 |只看该作者
man timer_create

Google:  Posix real time singals
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP