这次项目我的部分在2个月前就已经完成,但是同事在最近的使用中经常发现我的程序模块出问题。我在我的电路板上运行的好好的为什么到他那就崩溃呢?经过2天的持续检查发现居然是定时器导致的,因为我使用了大量的sleep、select。下面我来说下原理。
首先我的同事使用的是setitimer()
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
setitimer()比alarm功能强大,支持3种类型的定时器:
ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号
下面我们举一个例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
int sec;
void sigroutine(int signo){
switch (signo){
case SIGALRM:
printf("Catch a signal -- SIGALRM \n");
signal(SIGALRM, sigroutine);
break;
}
return;
}
int main()
{
struct itimerval value;
signal(SIGALRM, sigroutine);
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &value, NULL);
while(1);
}
这个例子是每秒发送一个SIGALRM信号。
但这和select与sleep、usleep有什么关系呢?
关系大着呢,因为在linux系统中这三个都会被SIGALRM中断导致退出函数。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include "Camera.h"
#include "QuecOpen4G.h"
#include "Tool.h"
#include "ql_oe.h"
int sec;
void sigroutine(int signo){
switch (signo){
case SIGALRM:
printf("Catch a signal -- SIGALRM \n");
signal(SIGALRM, sigroutine);
break;
case SIGVTALRM:
printf("Catch a signal -- SIGVTALRM \n");
signal(SIGVTALRM, sigroutine);
break;
}
return;
}
int main()
{
char i = 0;
struct itimerval value, ovalue, value2;
signal(SIGALRM, sigroutine);
signal(SIGVTALRM, sigroutine);
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &value, &ovalue); //1秒打印一次信号
Camera_Paramete_Init();
Camera_Init_Internet_Ip("192.168.1.100", "255.255.255.0");
Camera_Init_Camera("192.168.1.64", 13851, 0, 10);
Camera_Start_Camera_Communicate();
Camera_Take_Picture(0, "1.jpg");
i = Camera_Get_Camera_Order_By_Id(0);
printf("%d\n", i);
while( i != READ_CAMERA_VERSION )
{
i = Camera_Get_Camera_Order_By_Id(0);
printf("%d\n", i);
sleep(2); //2秒打印一次i
}
Tool_Move_File("/usrdata/1.jpg", "/usrdata/11.jpg");
while(1);
return 0;
}
这段程序是2秒打印一次状态,1秒打印一次信号。实际真的这样吗?
完全不是,变成了1s打印一次状态,1s打印一次信号。
所以最后我同事开了一个线程用usleep去模拟一个定时器。是我考虑不周到,坑了同事。