[英]Linux C++: “Holes” in time sampling
我有一個運行while(1)循環的線程。 在那個循環中,我會不斷檢查時間,因為我需要在某些時間執行某些任務。 但是,當我將時間打印到屏幕上時,我發現幾秒鍾后就會出現近700ms的“空洞”。 我嘗試設置prcoess優先級:
policy = SCHED_FIFO;
param.sched_priority = 18;
if( sched_setscheduler( id, policy, ¶m ) == -1 )
{
printf("Error setting scheduler/priority!\n");
}
以及線程優先級:
pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
param.sched_priority = 50;
pthread_attr_setschedparam(&attr, ¶m);
m_INVThreadID = pthread_create( &m_BaseStationLocatorsThread, &attr,
ThreadBaseStationLocatorsHandler, (void*)
(this));//Linux
但這沒有幫助。
我得到時間的方式是:
struct timespec start;
clock_gettime( CLOCK_MONOTONIC_RAW, &start);
//gettimeofday(&tim, NULL);
//wInitTime = tim.tv_sec*1000 + tim.tv_usec/1000.0;
double x = start.tv_sec;
double y = start.tv_nsec;
x=x*1000;
y = y/1000000;
double result = x+ y;
return result;
要么:
STime TimeHandler::GetTime()
{
STime tmpt;
time_t rawtime;
tm * timeinfo;
time(&rawtime);
timeinfo=localtime(&rawtime);
tmpt.day_of_month = timeinfo->tm_mday;
tmpt.month = timeinfo->tm_mon+1;
tmpt.year = timeinfo->tm_year+1900;
tmpt.Hours = timeinfo->tm_hour;
tmpt.Min = timeinfo->tm_min;
tmpt.Sec = timeinfo->tm_sec;
tmpt.MilliSeconds = GetCurrentTimeMilliSeconds();
return tmpt;
}
現在使用以下命令打印時間:
STime timeinfo = GetTime();
string curTime;
int datePart;
string datePartSTR;
std::ostringstream convert;
datePart =timeinfo.day_of_month;
convert << datePart;
//curTime.append( convert.str());
convert << "/";
datePart = timeinfo.month;
convert << datePart;
//curTime.append( convert.str());
convert << "/";
datePart =timeinfo.year;
convert << datePart;
//curTime.append( convert.str());
convert << " ";
datePart =timeinfo.Hours;
if (timeinfo.Hours<10)
convert <<0;
convert << datePart;
//curTime.append( convert.str());
convert << ":";
datePart =timeinfo.Min;
if (timeinfo.Min<10)
convert <<0;
convert << datePart;
//curTime.append( convert.str());
convert << ":";
datePart =timeinfo.Sec;
if (timeinfo.Sec<10)
convert <<0;
convert << datePart;
convert << ":";
datePart =timeinfo.MilliSeconds;
if (timeinfo.MilliSeconds<100)
convert << 0;
if (timeinfo.MilliSeconds<10)
convert << 0;
convert << datePart;
curTime.append( convert.str());
return curTime;
有任何想法嗎?
謝謝!
首先,最好使用Cron進行作業調度,而不是手動等待必要的循環時間然后手動啟動作業。
根據“時間漏洞”:正如jdv-Jan de Vaan在評論中所說,Linux不是實時操作系統(以及Windows和大多數其他面向消費者的操作系統)。 鑒於此,您永遠無法確保線程在預期的時間段內處於活動狀態,且精度為毫秒。 操作系統調度程序,系統活動,甚至CPU節流/節能都可能導致您的應用休眠時間超過一毫秒。 因此,與其固定時間,不如考慮一些閾值間隔。
好吧,這可能是調度程序延遲問題,但是另一方面,現代計算機上700mS的時間太長了,除非計算機真正過載或功率不足,否則我不希望有那么多的調度程序延遲。
另一種可能性是,沒有時間差,而是您用來打印當前時間的邏輯錯誤。 我建議您讓程序將時空值轉換為微秒(自紀元),然后以該格式打印經過的時間。 這樣,您就可以避免日歷日期的變化。 像這樣:
uint64_t GetMicrosecondsSinceEpoch()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return 0; // error!
return (((uint64_t)ts.tv_sec)*1000000) + ((uint64_t)(ts.tv_nsec)/1000)));
}
[...]
static uint64_t prevMicros = 0;
uint64_t nowMicros = GetMicrosecondsSinceEpoch();
int64_t elapsedMicros = nowMicros-prevMicros;
if (prevMicros != 0)
{
printf("Elapsed microseconds since previous time is %lli\n", elapsedMicros);
if (elapsedMicros >= 500000) printf("ERROR, more than 500mS passed since last time!?\n");
}
prevMicros = nowMicros;
如果以上顯示錯誤,則可能是調度問題; 如果不是,則可能是日期轉換問題。
順便說一句,如果您為每個要喚醒的事件計算微秒-自-紀元值,則只需取所有這些值中的最小值,然后從該最小值中減去GetMicrosecondsSinceEpoch()返回的當前值,然后睡眠那么長的時間...這樣,您只有在(大約)該時間處理下一個事件時才會醒來。 與定期醒來僅再次回到睡眠狀態相比,這將為您提供更好的時間准確性和更少的CPU /功耗使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.