基站開發的時候,我們需要做一個debug工具,以便將來做外場測試的時候用。
工具中有一個測量項是需要計算數據的速率。那麼我們都知道,除了在數據收集的地方做累加以外,還需要有一個定時器做時鐘的參考。
事實上數據是在線程中接收的,1ms內可能收到好幾個包,沒收到一個數據包,就對數據量做一次累加。 然後我們在外部起一個定時器用來週期性的收集並復位。
看似很簡單,但是我們遇到的問題是,當我們解析出來發現,我們收集的數據有時候會有誤差的。
經過調查,我們發現,定時器與線程在處理同一個變量的時候存在同步的問題,在這個問題上,我們可以將定時器看成是一個線程了。
上面問題的解決方法:不再timer中進行寫操作,而是通過 crt_value - old_value 來統計。
我們可以通過下面的小程序進行驗證:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
int g_num = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void action()
{
//pthread_mutex_lock(&mutex);
printf("timer:%d\n", g_num);
g_num = 0;
//pthread_mutex_unlock(&mutex);
}
void action2(void *arg)
{
while(1)
{
//pthread_mutex_lock(&mutex);
g_num++;
printf("pthread: %d\n", g_num);
//pthread_mutex_unlock(&mutex);
}
}
void init_timer()
{
struct itimerval val;
val.it_value.tv_sec = 0;
val.it_value.tv_usec = 1;
val.it_interval = val.it_value;
setitimer(ITIMER_REAL, &val, NULL);
}
int main()
{
pthread_t pid;
struct itimerval val;
signal(SIGALRM, action);
init_timer();
pthread_mutex_init(&mutex, NULL);
pthread_create(&pid, NULL, (void*)action2, NULL);
while(1)
;
return 0;
}
沒有加鎖的情況下,結果是:
顯而易見,定時器獲取的數據不是實時的。
解決方法就通過加互斥鎖。這裏我就不做演示,有興趣的可以自己在上面的程序中取消註釋,在跑一面就可以了。
然後互斥鎖的判斷是需要消耗資源的,所以最終我們接受了誤差,而沒有通過加鎖來實現精度。