如何在Linux下用C实现timer的回调函数

时间:2011-01-19 14:07:54

标签: c linux timer

我已经在很多论坛上搜索了可能的解决方案好几天但没有运气; (我在这里发布我的问题,非常感谢你的回复。

IDEA: 使用脚本来控制灯光(在Linux下的C语言中)

应用场景 我有三个灯:红色,蓝色和绿色。该脚本具有控制它们的计划。例如, 从现在起10秒钟,打开红灯2秒钟; 从现在开始15秒,打开蓝灯10秒钟; 从现在开始21秒,打开红灯5秒钟; 从现在起5秒钟,打开绿灯7秒钟; 从现在起103秒,打开绿灯11秒; ... .. 打开灯的时间和时间完全是任意的。而且这个程序应该能够扩展到百灯和数千个时间表。

如何编码 我的想法是有两个进程和一个邮箱: 第一个进程读取脚本文件并将计划解析为许多计时器。计时器到期后,它会向邮箱发送一条消息(包括灯光ID和操作 - 开启或关闭 - )。 第二个过程是根据来自邮箱的消息打开或关闭指定的灯光。

每个计划将被解析为两个计时器: 时间表:从现在起10秒钟,打开红灯2秒钟; 解析: 定时器1:定时器将在10秒后到期;一旦过期,它将光ID(红灯)和动作(ON)作为消息传递给邮箱; 定时器2:定时器将在(10 + 2)秒内到期;一旦过期,它会将灯ID(红灯)和动作(OFF)作为消息传递给邮箱;

第二个过程会不断检查邮箱,并根据收到的消息对正确的灯光采取适当的操作。

我的问题 Linux()中的计时器仅在过期时发出相同的SIGALRM信号。我无法将灯ID和操作传递给邮箱。我还有其他办法吗?非常感谢。

2 个答案:

答案 0 :(得分:3)

SIGALRM不是非常可靠的方法来实现这样的任何事情,你不能同时拥有多个警报请求。这两个流程设计是否类似于at(1) / atd(8)?不幸的是,“at”在这里使用起来并不是那么精确,我不确定它在你安排某些事情时甚至会花费几秒钟。

然而,只用一个程序解决问题非常简单。只需将任务拆分为诸如“打开/关闭灯光X”之类的事件,将它们放入有序队列并有一个循环读取队列并休眠,直到需要采取行动。

答案 1 :(得分:3)

Tonttu的解决方案非常好。

使用通过链表实现的队列:

struct node {
    struct node *next;
    time_t t;        // time to start
    int action;   // on / off
    int lamp_id;
};

struct queue {
    struct node *head;
    struct node *tail;
};

解析文件并填充队列(保持按t排序)。 接下来,您的主循环应如下所示:

time_t start = time(NULL);
while(!queue_empty()) {
    time_t now = time(NULL) - start;
    struct node *n = queue.head;        

    if(n->t <= now) {
        lamp(n->lamp_id, n->action); // set the status of a lamp
        queue_next();
    } else {
        sleep(n->t - now);
    }
}

像往常一样,阅读精细手册。你需要time(2)。 如果您需要亚秒级时间,请使用gettimeodday(2)