導航:首頁 > 操作系統 > linux高精度定時器

linux高精度定時器

發布時間:2023-06-09 12:26:12

A. 求linux毫秒級定時器的實現

1 nanosleep函數可以提供最高解析度,一般是納秒級
2 select、poll函數的定時是毫秒級,pselect是納秒級
以上三個函數都可以實現你的要求

B. Linux 下 Qt關於微秒級別的定時器

select可以達到微妙級別,態如你網路下select timer,下面是win下面使用洞念select的例子
#include<iostream>
#include <iomanip>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{

DWORD dwVersion = 0; WSADATA wsaData; DWORD dwErr = 0;
dwErr = WSAStartup(MAKEWORD(0x2, 0x2), &wsaData);
if (0 != dwErr)
{printf("winsock init error!\n");return -1;}
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == s)
{
printf("create a socket error!\n");
WSACleanup();
return -1;
}
// 設置為納閉困非阻塞
int nRet = 0;
u_long lRet = 1;
nRet = ioctlsocket(s, FIONBIO, &lRet);
if (SOCKET_ERROR == nRet)
{
printf("set socket error!\n");
closesocket(s);
WSACleanup();
return -1;
}
int time=0;
while( 1 ){
fd_set rfds ;
struct timeval tval;

FD_ZERO( &rfds ) ;
FD_SET(1,&rfds);
tval.tv_sec = 1 ; /*秒*/
tval.tv_usec =0 ; /*微秒, 1秒=10的3次方毫秒=10的6次方微妙*/
int ret =select( 1, &rfds, NULL, NULL, &tval );
if(ret==0 ){
cout<<setfill('0')<<setw(3)<<++time<<" s"<<endl;
}
else
{cout<<WSAGetLastError()<<endl;
break;
}

}
WSACleanup();
return 0;
}

C. linux下的幾種時鍾和定時器機制

1. RTC(Real Time Clock)

所有PC都有RTC. 它和CPU和其他晶元獨立。它在電腦關機之後還可以正常運行。RTC可以在IRQ8上產生周期性中斷. 頻率在2Hz--8192HZ.

Linux只是把RTC用來獲取時間和日期. 當然它允許進程通過對/dev/rtc設備來對它進行編程。Kernel通過0x70和0x71 I/O埠來訪問RTC。

 

2. TSC(Time Stamp Counter)

80x86上的微處理器都有CLK輸入針腳. 從奔騰系列開始. 微處理器支持一個計數器. 每當一個時鍾信號來的時候. 計數器加1. 可以通過匯編指令rdtsc來得到計數器的值。通過calibrate_tsc可以獲得CPU的頻率. 它是通過計算大約5毫秒里tsc寄存器裡面的增加值來確認的。或者可以通過cat /proc/cpuinfo來獲取cpu頻率。tsc可以提供比PIT更精確的時間度量。

 

3. PIT(Programmable internval timer)

除了RTC和TSC. IBM兼容機提供了PIT。PIT類似微波爐的鬧鍾機制. 當時間到的時候. 提供鈴聲. PIT不是產生鈴聲. 而是產生一種特殊中斷. 叫定時器中斷或者時鍾中斷。它用來告訴內核一個間隔過去了。這個時間間隔也叫做一個滴答數。可以通過編譯內核是選擇內核頻率來確定。如內核頻率設為1000HZ,則時間間隔或滴答為1/1000=1微秒。滴答月短. 定時精度更高. 但是用戶模式的時間更短. 也就是說用戶模式下程序執行會越慢。滴答的長度以納秒形式存在tick_nsec變數裡面。PIT通過8254的0x40--0x43埠來訪問。它產生中斷號為IRQ 0.

下面是關於pIT裡面的一些宏定義:

HZ:每秒中斷數。

CLOCK_TICK_RATE:值是1,193,182. 它是8254晶元內部振盪器頻率。

LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用來編程PIT。

setup_pit_timer()如下:

spin_lock_irqsave(&i8253_lock, flags);

outb_p(0x34,0x43);

udelay(10);

outb_p(LATCH & 0xff, 0x40);

udelay(10);

outb (LATCH >> 8, 0x40);

spin_unlock_irqrestore(&i8253_lock, flags);

 

 

4. CPU Local Timer

最近的80x86架構的微處理器上的local apic提供了cpu local timer.他和pit區別在於它提供了one-shot和periodic中斷。它可以使中斷發送到特定cpu。one-shot中斷常用在實時系統裡面。

D. 在linux環境中,如何實現多線程中使用多個定時器,POSIX定時器可以嗎,如何用

個局御辯人解決了,以下是一個實現:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <pthread.h>
#include <time.h>

#if 1
pthread_attr_t attr;
timer_t hard_timer, software_timer;
struct sigevent hard_evp, software_evp;

static void watchdog_hard_timeout(union sigval v)
{
time_t t;
char p[32];
timer_t *q;
struct itimerspec ts;
int ret;

time(&t);
strftime(p, sizeof(p), "%T", localtime(&t));
printf("watchdog hard timeout!\n");
printf("%s thread %d, val = %u, signal captured.\n", p, (unsigned int)pthread_self(), v.sival_int);

q = (timer_t *)(v.sival_ptr);
printf("hard timer_t:%d add:%p, q:%p!\n", (int)hard_timer, &hard_timer, q);
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 6;
ts.it_value.tv_nsec = 0;

ret = timer_settime(*q, CLOCK_REALTIME, &ts, NULL);
if (ret != 0) {
printf("settime err(%d)!\n", ret);
}
}

static void watchdog_software_timeout(union sigval v)
{
time_t t;
char p[32];
timer_t *q;
struct itimerspec ts;
int ret;

time(&t);
strftime(p, sizeof(p), "%T", localtime(&t));
printf("watchdog software timeout!\n");
printf("%s thread %d, val = %u, signal captured.\n"桐缺, p, (unsigned int)pthread_self(), v.sival_int);

q = (timer_t *)(v.sival_ptr);
printf("hard timer_t:%d add:%p, q:%p!\拆讓n", (int)hard_timer, &hard_timer, q);
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 10;
ts.it_value.tv_nsec = 0;

ret = timer_settime(*q, CLOCK_REALTIME, &ts, NULL);
if (ret != 0) {
printf("settime err(%d)!\n", ret);
}
}

static void dcmi_sol_pthread_attr_destroy(pthread_attr_t *attr)
{
pthread_attr_destroy(attr);
}

static int dcmi_sol_pthread_attr_init(pthread_attr_t *attr)
{
int ret;

if ((ret = pthread_attr_init(attr) != 0)) {
goto err;
}
if ((ret = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)) != 0) {
dcmi_sol_pthread_attr_destroy(attr);
goto err;
}
/* 設置線程的棧大小,失敗則用系統默認值 */
pthread_attr_setstacksize(attr, 128 * 1024);

return 0;
err:
printf("set ptread attr failed(ret:%d)!\n", ret);
return -1;
}

int main(void)
{
struct itimerspec ts;
int ret;

ret = dcmi_sol_pthread_attr_init(&attr);
if (ret != 0) {
printf("init pthread attributes fail(%d)!\n", ret);
exit(-1);
}

memset(&hard_evp, 0, sizeof(struct sigevent));
hard_evp.sigev_value.sival_ptr = &hard_timer;
hard_evp.sigev_notify = SIGEV_THREAD;
hard_evp.sigev_notify_function = watchdog_hard_timeout;
hard_evp.sigev_notify_attributes = NULL;//&attr;

memset(&software_evp, 0, sizeof(struct sigevent));
software_evp.sigev_value.sival_ptr = &software_timer;
software_evp.sigev_notify = SIGEV_THREAD;
software_evp.sigev_notify_function = watchdog_software_timeout;
software_evp.sigev_notify_attributes = NULL;//&attr;

ret = timer_create(CLOCK_REALTIME, &hard_evp, &hard_timer);
if(ret != 0) {
perror("hard timer_create fail!");
exit(-1);
}
ret = timer_create(CLOCK_REALTIME, &software_evp, &software_timer);
if (ret != 0) {
timer_delete(hard_timer);
perror("software timer_create fail!");
exit(-1);
}

ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 6;
ts.it_value.tv_nsec = 0;

ret = timer_settime(hard_timer, CLOCK_REALTIME, &ts, NULL);
if(ret != 0) {
perror("hard timer_settime fail!");
timer_delete(hard_timer);
timer_delete(software_timer);
exit(-1);
}

ts.it_value.tv_sec = 10;
ret = timer_settime(software_timer, CLOCK_REALTIME, &ts, NULL);
if(ret != 0) {
perror("hard timer_settime fail!");
timer_delete(hard_timer);
timer_delete(software_timer);
exit(-1);
}

while(1) {
printf("main ready sleep!\n");
sleep(15);
printf("main sleep finish!\n");
}

return 0;
}
#endif

E. Linux下的定時器,怎麼用。

時事件,void(*handle)(union sigval v)參數就是處理事件的函數指針。
int omsSetTimer(timer_t *tId,int value,int interval)就是設置定時器。
按你說的,如果要同時起多個定時器,需要定義一個數組timer_t tm[n];int it[n];tm就是定時器結構,it用來記錄對應的定時器是否已經使用,使用中的就是1,沒用的就是0;
主進程消息來了就從it找一個沒用的好鎮來omsSetTimer,如果收到終止消息,那omsSetTimer 定時時間為0
int omsTimer(timer_t *tId,int iValue,int iSeconds ,void(*handle)(union sigval v),void * param)
{
struct sigevent se;
struct itimerspec ts;
memset (&se, 0, sizeof (se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = handle;
se.sigev_value.sival_ptr = param;
if (timer_create (CLOCK_REALTIME, &se, tId) < 0)
{
return -1;
}
ts.it_value.tv_sec = iValue;
// ts.it_value.tv_sec =3;
//ts.it_value.tv_nsec = (long)(iValue % 1000) * (1000000L);
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = iSeconds;
//ts.it_interval.tv_nsec = (long)(iSeconds % 1000) * (1000000L);
ts.it_interval.tv_nsec = 0;
if (timer_settime(*tId, TIMER_ABSTIME, &ts, NULL) < 0)
{
return -1;
}
return 0;
}
int omsSetTimer(timer_t *tId,int value,int interval)
{
struct itimerspec ts;
ts.it_value.tv_sec =value;
/高襪鄭/戚頌ts.it_value.tv_nsec = (long)(value % 1000) * (1000000L);
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = interval;
//ts.it_interval.tv_nsec = (long)(interval % 1000) * (1000000L);
ts.it_interval.tv_nsec = 0;
if (timer_settime(*tId, TIMER_ABSTIME, &ts, NULL) < 0)
{
return -1;
}
return 0;
}
另外,團IDC網上有許多產品團購,便宜有口碑

F. 嵌入式Linux下定時器問題,定時10us。

可以使用select函數實現定時,
timeval
tv;
tv.tv_usec=25;
tv.tv_sec=0;
select(1,NULL,NULL,NULL
&tv);

閱讀全文

與linux高精度定時器相關的資料

熱點內容
蘋果app怎麼掃描二維碼下載 瀏覽:957
css文件在線解壓 瀏覽:152
36歲程序員近況 瀏覽:283
哪裡可以下載不加密的歌 瀏覽:934
隱藏文件夾是什麼梗 瀏覽:918
插件注冊命令 瀏覽:497
梁一端加密一端不加密規范 瀏覽:82
代碼行數統計命令 瀏覽:104
單片機中2K表示什麼 瀏覽:482
紫禁城為什麼會斷開伺服器 瀏覽:580
華為手機的方舟編譯器在哪呢 瀏覽:123
下載壓縮虐殺原形2 瀏覽:905
linux腳本cd 瀏覽:167
間架結構pdf 瀏覽:843
重慶農村商業銀行app怎麼老出問題 瀏覽:471
慧編程配置要求 瀏覽:673
數控機床編程與操作視頻 瀏覽:461
文件夾資料誤刪怎麼辦 瀏覽:87
手機app怎麼下載安裝 瀏覽:494
最新的java版本 瀏覽:995