1. 程式人生 > >Linux Timer定時器【轉】

Linux Timer定時器【轉】

support block 相對 art get ring nis 是的 data-

轉自: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到目前的時間,更改系統時間會更改獲取的值。

flags: TFD_NONBLOCK(非阻塞), TFD_CLOEXEC(同O_CLOEXEC)。
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則定時器只定時一次,否則之後每隔設定時間超時一次。

oldValue:不為NULL時則返回定時器這次設置之前的超時時間。
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定時器【轉】