Linuxタイマ

3676 ワード

timerfdはLinuxがユーザプログラムに提供するタイマインタフェースであり、このインタフェースはファイル記述子に基づいてファイル記述子の読み取り可能なイベントによってタイムアウト通知を行い、epoll/selectに使用することができる.主に3つの関数があります.
ヘッダファイル:include
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は相対時間を表します.新Value:新タイムアウト時間を指定し、新Value.it_valueが0でない場合はタイマを起動し、そうでない場合はタイマを閉じます.もしnewValue.it_intervalが0の場合、タイマは1回だけタイミングを決めます.そうしないと、設定時間ごとにタイムアウトします.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は読み取り可能になりuint 64_を返すtタイプの整数は、タイムアウトの数(タイムアウト未読が何個あるかを指す)であり、タイマにタイムアウトイベントが発生していない場合、timerfdがブロックである場合、readはブロックされ、timerfdが非ブロックである場合、EAGAINエラーが返される.readが8バイト未満のデータがEINVALエラーで返された場合.
サンプルコード
#include   
#include 
#include 
#include 
#include 
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;
}