定时器与超时的设置
- 一、相關(guān)時(shí)間函數(shù)
- 1. gettimeofday()
- 2. time()
- 3. clock()
- 二、間隔定時(shí)器
- 1. setitimerval()
- 2. getitimerval()
- 3. 實(shí)時(shí)定時(shí)器的使用
- 三、為阻塞操作設(shè)置超時(shí)
- 1. alarm()
- 2. 給read()設(shè)置讀超時(shí)
- 一、相關(guān)時(shí)間函數(shù)
一、相關(guān)時(shí)間函數(shù)
1. gettimeofday()
獲取日歷時(shí)間。
#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz);- timeval結(jié)構(gòu)體
2. time()
返回自Epoch(格林威治標(biāo)準(zhǔn)時(shí)間1970.01.01 0:00AM)以來的秒數(shù)。
#include <time.h>time_t time(time_t *timep);參數(shù)timep存儲(chǔ)返回的時(shí)間。若timep為空,則直能從函數(shù)返回值獲得。
time_t t = time(NULL);3. clock()
計(jì)時(shí)函數(shù)。返回值為從程序啟動(dòng)到調(diào)用該函數(shù)所占用CPU的時(shí)間,實(shí)際為CPU時(shí)鐘計(jì)時(shí)單元(clock tick)數(shù)。
#include <time.h>clock_t clock(void) ;由于不同系統(tǒng)或編譯器對(duì)于每秒的時(shí)鐘單元數(shù)定義不同,所以直接輸出會(huì)有所不同。所以還定義了常量CLOCKS_PER_SEC,表示一秒鐘會(huì)有多少個(gè)時(shí)鐘計(jì)時(shí)單元,其定義如下:
#define CLOCKS_PER_SEC ((clock_t)1000)CLOCKS_PER_SEC在Linux 4.15.0-32-generic系統(tǒng)上數(shù)值為1000000。
二、間隔定時(shí)器
1. setitimerval()
使用系統(tǒng)調(diào)用setitimer()來創(chuàng)建間隔定時(shí)器,這種定時(shí)器會(huì)在一定時(shí)間后到期,并可以在到期后每隔一段時(shí)間到期一次。
#include <sys/time.h>int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);which參數(shù)的可選項(xiàng):
ITIMER_REAL
以真實(shí)時(shí)間計(jì)時(shí),到期產(chǎn)生SIGALARM信號(hào)ITIMER_VIRTUAL
以虛擬時(shí)間(用戶模式下CPU時(shí)間)計(jì)時(shí)ITIMER_PROF
創(chuàng)建profiling定時(shí)器以內(nèi)核態(tài)與用戶態(tài)CPU時(shí)間總和計(jì)時(shí),到期會(huì)產(chǎn)生SIGPROF信號(hào)
itimerval結(jié)構(gòu)體
其中,it_value表示距離定時(shí)器到期的剩余時(shí)間,it_interval記錄定時(shí)器的周期時(shí)間(或不進(jìn)行周期性定時(shí),it_interval中兩個(gè)值同為0時(shí)表示沒有周期性定時(shí),即一次性定時(shí)器)。若進(jìn)行周期性定時(shí),則在每次到時(shí)后會(huì)將it_interval重新存儲(chǔ)倒計(jì)時(shí)的間隔時(shí)間。
2. getitimerval()
獲取定時(shí)器當(dāng)前狀態(tài)。
#include <sys/time.h>int getitimerval(int which, struct itimerval *curr_value );curr_value存儲(chǔ)定時(shí)器當(dāng)前狀態(tài),其內(nèi)容與調(diào)用setitimerval()返回的old_value內(nèi)容相同。
3. 實(shí)時(shí)定時(shí)器的使用
/* 運(yùn)行說明:./timer 1 800000 1 0第二個(gè)參數(shù)為倒計(jì)時(shí)的秒數(shù),第三個(gè)參數(shù)為倒計(jì)時(shí)的微秒數(shù),第四個(gè)參數(shù)為定時(shí)器間隔時(shí)間的秒數(shù),第五個(gè)參數(shù)為定時(shí)器間隔時(shí)間的微秒數(shù)后四個(gè)參數(shù)可以省略,默認(rèn)為 2 0 0 0 */#include <iostream> #include <string.h> #include <sys/time.h> #include <signal.h>static volatile sig_atomic_t gotAlam = 0;/* 打印時(shí)間,includeTimer表示是否為第一次打印,第一次只打印前兩個(gè)數(shù)字 */ static void displayTimes( const char *msg, bool includeTimer ) {struct itimerval itv;static struct timeval start; // 起始狀態(tài)struct timeval curr; // 當(dāng)前狀態(tài)static int callNum = 0; // 當(dāng)前函數(shù)被調(diào)用次數(shù)if( callNum == 0 ) {if( gettimeofday( &start, nullptr ) == -1 ) {perror( "gettimeofday" );}}/* 每20行打印一次提示信息 */if( callNum % 20 == 0 ) {printf(" Elapsed Value Interval\n");}if( gettimeofday( &curr, NULL ) == -1 ) {perror( "gettimeofday" );}printf("%-7s %6.2f", msg, curr.tv_sec - start.tv_sec + (curr.tv_usec - start.tv_usec) / 1000000.0 );/* 可以打印后兩個(gè)數(shù)字 */if( includeTimer ) {if( getitimer( ITIMER_REAL, &itv ) == -1 ) {perror( "getitimer" );}printf(" %6.2f %6.2f", itv.it_value.tv_sec + itv.it_value.tv_usec / 1000000.0, itv.it_interval.tv_sec + itv.it_interval.tv_usec / 1000000.0);}printf("\n");callNum++; }/* 信號(hào)處理函數(shù) */ static void sigalrmHandler( int sig ) {gotAlam = 1; }int main( int argc, char **argv ) {struct itimerval itv;clock_t preClock;int maxSigs = 0; // 信號(hào)觸發(fā)最大次數(shù)int sigCnt = 0; // 信號(hào)已觸發(fā)次數(shù)struct sigaction sa;sigemptyset( &sa.sa_mask );sa.sa_flags = 0;sa.sa_handler = sigalrmHandler;if( sigaction( SIGALRM, &sa, NULL ) == -1 ) {perror( "sigaction" );}maxSigs = ( itv.it_interval.tv_sec == 0 && itv.it_interval.tv_usec == 0 ) ? 1 : 3;displayTimes( "start:", false );itv.it_value.tv_sec = (argc > 1) ? atoi( argv[1] ) : 2;itv.it_value.tv_usec = (argc > 2) ? atoi( argv[2] ) : 0;itv.it_interval.tv_sec = (argc > 3) ? atoi( argv[3] ) : 0;itv.it_interval.tv_usec = (argc > 4) ? atoi( argv[4] ) : 0;if( setitimer( ITIMER_REAL, &itv, 0 ) == -1 ) {perror( "setitimer" );}preClock = clock();while( true ) {while( ( clock() - preClock ) * 10 / CLOCKS_PER_SEC < 5 ) {/* 定時(shí)器時(shí)間到 */if( gotAlam ) {gotAlam = false;displayTimes( "ALARM:", true );sigCnt++;if( sigCnt >= maxSigs ) {printf("That's all folk\n");exit( EXIT_SUCCESS );}}}preClock = clock();displayTimes( "Main:", true );} }三、為阻塞操作設(shè)置超時(shí)
1. alarm()
創(chuàng)建一次性實(shí)時(shí)定時(shí)器。
#include <unistd.h>unsigned int alarm(unsigned int seconds);seconds表示倒計(jì)時(shí)的秒數(shù)。到期后會(huì)發(fā)送SIGALARM信號(hào)。
調(diào)用alarm(0)可以屏蔽所有現(xiàn)有定時(shí)器。
2. 給read()設(shè)置讀超時(shí)
#include <iostream> #include <string.h> #include <sys/time.h> #include <signal.h> #include <unistd.h> using namespace std;const int BUFFER_SIZE = 200;/* 信號(hào)處理函數(shù) */ static void handler( int sig ) {printf("caught signal\n"); }int main( int argc, char **argv ) {struct sigaction sa;char buf[BUFFER_SIZE];ssize_t numRead;int savedErrno;sa.sa_flags = ( argc > 2 ) ? SA_RESTART : 0;sigemptyset( &sa.sa_mask );sa.sa_handler = handler;if( sigaction( SIGALRM, &sa, NULL ) == -1 ) {perror("sigaction");}/* 設(shè)置倒計(jì)時(shí) */alarm( (argc > 1) ? atoi(argv[1]) : 10 );numRead = read( STDIN_FILENO, buf, BUFFER_SIZE - 1 );savedErrno = errno;alarm(0); // 將現(xiàn)有定時(shí)器屏蔽errno = savedErrno;if( numRead == -1 ) {if( errno == EINTR ) { // read系統(tǒng)調(diào)用被信號(hào)打斷,即收到超時(shí)信號(hào)printf("Read timed out\n");} else {perror("read");}} else { // 未超時(shí)printf("Successful read %ld bytes : %.*s", long(numRead), int(numRead), buf);}exit(EXIT_SUCCESS); }總結(jié)
- 上一篇: 想自学混合开发 财富值58
- 下一篇: win10宽带连接断网自动重连