Linux Timer定時器【轉】
轉自:https://www.jianshu.com/p/66b3c75cae81
timerfd為Linux為用戶程序提供的定時器接口,該接口基於文件描述符,通過文件描述符的可讀事件進行超時通知,且能夠被用於epoll/select。主要有三個函數。
頭文件: include <sys/timerfd.h>
int timerfd_create(int clockid, int flags)
功能: 生成定時器,返回文件描述符。
clockid: CLOCK_MONOTONIC或CLOCK_REALTIME,其中CLOCK_MONOTONIC表示獲取的時間為系統重啟到現在的時間,更改系統時間對其沒有影響。CLOCK_REALTIME表示從1970.1.1到目前的時間,更改系統時間會更改獲取的值。
return: timer的文件描述符。
int timerfd_settime(int tfd, int flags, const struct itimerspec *newValue, struct itimerspec *oldValue)
功能: 用於啟動或關閉指定fd的定時器。
tfd: timerfd,由timerfd_create函數返回。
flags: 1表示設置的是絕對時間;0表示相對時間。
newValue: 指定新的超時時間,若newValue.it_value非0則啟動定時器,否則關閉定時器。若newValue.it_interval為0則定時器只定時一次,否則之後每隔設定時間超時一次。
return:失敗則返回-1。
struct timespec
{
time_t tv_sec; //秒
long tv_nsec; //納秒
}
struct itimerspec
{
struct timespec it_interval; //首次超時後,每隔it_interval超時一次
struct timespec it_value; //首次超時時間
int timerfd_gettime(int fd, struct itimerspec *curValue)
功能: 用於獲取距離下次超時還剩下的時間。如果調用時定時器已經到期(即超過it_value時間),並且定時器處於循環模式(即it_interval不為0), 那麽調用該函數後定時器重新開始計時。
fd: timerfd,由timerfd_create函數返回。
curValue: 返回距離下次超時剩下的時間。
return:失敗返回-1
讀取timerfd
當定時器超時,timerfd可讀,返回uint64_t類型的整數,為超時的數目(指有多少個超時未讀),如果定時器沒有發生超時事件,若timerfd為阻塞時,read將阻塞,若timerfd為非阻塞時,返回EAGAIN錯誤。如果read是的數據小於8字節以EINVAL錯誤返回。
樣例代碼
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdint.h>
#include <iostream>
using namespace std;
const int EPOLL_SIZE = 10;
int main(int argc, char* argv[])
{
int tfd, epfd, nfds;
struct epoll_event event;
struct epoll_event events[EPOLL_SIZE];
//創建timerfd, CLOCK_REALTIME為絕對時間,TFD_NONBLOCK為非阻塞
tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
if (tfd < 0)
{
cerr << "timerfd_create error!" << endl;
return -1;
}
struct timespec startTime, intervalTime;
startTime.tv_sec = 0;
startTime.tv_nsec = 1; //相當於立即到達超時時間
intervalTime.tv_sec = 3; //首次超時後,每三秒超時一次
intervalTime.tv_nsec = 0;
struct itimerspec newValue;
newValue.it_value = startTime;
newValue.it_interval = intervalTime;
//設置超時時間,且為相對時間
if (timerfd_settime(tfd, 0, &newValue, NULL) < 0)
{
cerr << "timerfd_settime error!" << endl;
return -1;
}
//用epoll來監聽描述符
epfd = epoll_create(EPOLL_SIZE);
if (epfd < 0)
{
cerr << "epoll_create error!" << endl;
return -1;
}
event.data.fd = tfd;
event.events = EPOLLIN;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, tfd, &event) < 0)
{
cerr << "epoll_ctl error!" << endl;
return -1;
}
uint64_t count = 0;
while (1)
{
//非阻塞等待
nfds = epoll_wait(epfd, events, EPOLL_SIZE, 0);
if (nfds == 0) continue;
for (int i = 0; i < nfds; i++)
{
if (events[i].events & EPOLLIN)
{
uint64_t data;
read(events[i].data.fd, &data, sizeof(uint64_t));
count += data;
cout << "read: " << data << ", timer count: " << count << endl;
}
}
}
return 0;
}
小禮物走一走,來簡書關註我
作者:agin719
鏈接:https://www.jianshu.com/p/66b3c75cae81
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。
Linux Timer定時器【轉】