Linux提供了计时器机制,使您可以指定在未来的某个时刻发生某些事件。 计时器的结构为:struct timer_list,如下所示
{
struct list_head list;
unsigned long expires;
无符号长数据;
void(*function ) )无符号长整型;
(;
实现list时使用的与计时器功能无关
expires是计时器计时的滴答数(当前滴答数为jiffies )
函数直到那时为止由内核调用的函数
由于data有多个计时器调用一个函数的可能性,为了使该函数能够区分不同的计时器,
在结构中的data中标识并调用此计时器
是函数(数据)
允许函数区分它们,即data作为ID。
怎么用
将计时器添加到计时器队列
void add _ timer (struct timer _ list * timer ) )。
更改计时器的有效期限
intmod _ timer (struct timer _ list * timer,unsigned long expires ) )。
删除计时器(以后此计时器将不起作用) )。
int del _ timer (struct timer _ list * timer ) )。
如果不要求准确性,alarm (和signal )就足够了
代码:#include
#包含
#包含
voidSIGalrm_fn(intSIG ) )。
{
打印(警报! n ';
alarm(2;
返回;
}
入主(void ) )。
{
signal(sigalrm,signalrm_fn );
alarm(2;
while(1)。
pause (;
}
可以用select () )函数实现时序,可以精确到毫秒级#include
#包含
#包含
#包含
#包含
int count=0;
void set_timer ()
{
struct itimerval itv,oldtv;
itv.it_interval.tv_sec=5;
itv.it_interval.tv_usec=0;
itv.it_value.tv_sec=5;
itv.it_value.tv_usec=0;
setitimer(itimer_real,itv,oldtv );
}
voidSIGalrm_Handler(intSIG ) )。
{
出局;
printf('timersignal.%dn ',count );
}
int main () )
{
signal(Sigalrm,sigalrm_handler );
set_timer (;
wile (计数1000 ) )。
{}
退出(0;
}
基于定时机制的多线程编程
为了避免Qt系统中多线程编程带来的问题,也可以使用系统提供的定时器机制实现同样的功能。 计时器机制可序列化同时发生的事件,简化对同时发生的事件的处理,并避免thread-safe问题。
在以下示例中,有几个对象需要接收通过套接字、FIFO等进程间通信机制发送的消息,但消息是随机接收的,并且需要专门用于接收消息的GUI主线程。 接收到消息后,主线程初始化对应的对象并开始处理,同时返回。 这使主线程能够始终更新接口以显示和接收外部消息并同时控制多个对象; 另一方面,每个对象在处理消息后,需要通知GUI主线程。 针对这个问题,使用第3部分的用户定义事件的方法,在主线程上安装事件过滤器,捕获从各对象发送来的自定义事件,提示调用主线程内的槽函数
您还可以利用Qt的计时器机制实现类似的功能,而无需担心Thread-safe问题。 部分代码如下所示。
在用户定义的Server类中创建并启动了计时器,然后使用connect函数将计时器超时与读取设备文件数据相关联。 服务器:3360服务器(q构件*部件) : q构件(部件) )。
{
读时间=newq时间(this; //创建并启动计时器
connect(readtimer,signal ) timeout )、this,slot ) slotreadfile ); //每当计时器超时时,调用函数slotReadFile读取文件
读时间开始(100;
}
slotReadFile函数在计时器超时时从文件读取数据,然后重新启动计时器。 int server :短读()//消息读取和处理函数
{
读时间停止(; //暂停计时器计时
ret=read (文件,buf ); //读取文件
if(ret==null ) )。
{读时间开始(100; //如果没有新消息,请重新启动计时器
返回(-1;
}
else
根据buf的内容,将消息分发到各自合适的对象进行处理……;
读时间开始(100; //重新启动计时器
}
该程序在类似轮转的时间读取用户指定的设备文件,并根据读取的数据内容将信息发送到相应的每个对象。 用户可以在自己的GUI主线程中创建Server类以实现基本的消息接收过程,但其本身可以处理界面显示等问题。 每个对象完成处理后,通过重新启动计时器继续周期性读取下属设备文件的过程。 当然,如果每个对象的事件处理时间都很短,而且来自底层设备的消息频率相对较低,则此方法非常适合。 在这种情况下,上述方法可以完全满足用户的需求,并避免了与并发线程相关的复杂问题。