我已经在很多论坛上搜索了可能的解决方案好几天但没有运气; (我在这里发布我的问题,非常感谢你的回复。
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和操作传递给邮箱。我还有其他办法吗?非常感谢。
答案 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)。