timerfd

来源:互联网 发布:json与xml的比较 编辑:程序博客网 时间:2024/05/16 11:55

http://blog.csdn.net/gdutliuyun827/article/details/8470777

看一下timerfd的例子,上代码:

[cpp] view plaincopy
  1. #include <sys/timerfd.h>  
  2. #include <sys/time.h>  
  3. #include <time.h>  
  4. #include <unistd.h>  
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7. #include <stdint.h>        /* Definition of uint64_t */  
  8.   
  9. #define handle_error(msg) \  
  10.        do { perror(msg); exit(EXIT_FAILURE); } while (0)  
  11.   
  12. void printTime()  
  13. {    
  14.     struct timeval tv;    
  15.     gettimeofday(&tv, NULL);    
  16.     printf("printTime:  current time:%ld.%ld ", tv.tv_sec, tv.tv_usec);  
  17. }  
  18.   
  19. int main(int argc, char *argv[])  
  20. {  
  21.    struct timespec now;  
  22.    if (clock_gettime(CLOCK_REALTIME, &now) == -1)  
  23.        handle_error("clock_gettime");  
  24.   
  25.    struct itimerspec new_value;  
  26.    new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);  
  27.    new_value.it_value.tv_nsec = now.tv_nsec;  
  28.    new_value.it_interval.tv_sec = atoi(argv[2]);  
  29.    new_value.it_interval.tv_nsec = 0;  
  30.   
  31.    int fd = timerfd_create(CLOCK_REALTIME, 0);  
  32.    if (fd == -1)  
  33.        handle_error("timerfd_create");  
  34.   
  35.    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)  
  36.        handle_error("timerfd_settime");  
  37.   
  38.    printTime();  
  39.    printf("timer started\n");  
  40.      
  41.    for (uint64_t tot_exp = 0; tot_exp < atoi(argv[3]);)   
  42.    {  
  43.        uint64_t exp;  
  44.        ssize_t s = read(fd, &exp, sizeof(uint64_t));  
  45.        if (s != sizeof(uint64_t))  
  46.            handle_error("read");  
  47.   
  48.        tot_exp += exp;  
  49.        printTime();  
  50.        printf("read: %llu; total=%llu\n",exp, tot_exp);  
  51.    }  
  52.   
  53.    exit(EXIT_SUCCESS);  
  54. }  

相关结构体如下:

[cpp] view plaincopy
  1. struct timespec {  
  2.    time_t tv_sec;                /* Seconds */  
  3.    long   tv_nsec;               /* Nanoseconds */  
  4. };  
  5.   
  6. struct itimerspec {  
  7.    struct timespec it_interval;  /* Interval for periodic timer */  
  8.    struct timespec it_value;     /* Initial expiration */  
  9. };  

代码L25-L29:初始化定时器的参数,初始间隔与定时间隔。

L32:创建定时器fd,CLOCK_REALTIME:真实时间类型,修改时钟会影响定时器;CLOCK_MONOTONIC:相对时间类型,修改时钟不影响定时器。

L35:设置定时器的值。

L44:阻塞等待定时器到期。返回值是未处理的到期次数。比如定时间隔为2秒,但过了10秒才去读取,则读取的值是5。

编译运行:编译时要加rt库(g++ -lrt timerfd.cc -o timerfd)

[root@localhost appTest]# ./timerfd 5 2 10
printTime:  current time:1357391736.146196 timer started
printTime:  current time:1357391741.153430 read: 1; total=1
printTime:  current time:1357391743.146550 read: 1; total=2
printTime:  current time:1357391745.151483 read: 1; total=3
printTime:  current time:1357391747.161155 read: 1; total=4
printTime:  current time:1357391749.153934 read: 1; total=5
printTime:  current time:1357391751.157309 read: 1; total=6
printTime:  current time:1357391753.158384 read: 1; total=7
printTime:  current time:1357391755.150470 read: 1; total=8
printTime:  current time:1357391757.150253 read: 1; total=9
printTime:  current time:1357391759.149954 read: 1; total=10
[root@localhost appTest]#

第一个参数5为第一次定时器到期间隔,第二个参数2为定时器的间隔,第三个参数为定时器到期10次则退出。程序运行(5+2*10)S退出。

详细信息可以:man timerfd_create

#include <sys/timerfd.h>#include <sys/time.h>#include <time.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <stdint.h>        /* Definition of uint64_t */#define handle_error(msg) \   do { perror(msg); exit(EXIT_FAILURE); } while (0)void printTime(){  struct timeval tv;  gettimeofday(&tv, NULL);  printf("printTime:  current time:%ld.%ld ", tv.tv_sec, tv.tv_usec);}int main(int argc, char *argv[]){   struct timespec now;   if (clock_gettime(/*CLOCK_REALTIME*/CLOCK_MONOTONIC, &now) == -1)   handle_error("clock_gettime");   struct itimerspec new_value;   new_value.it_value.tv_sec = /*now.tv_sec +*/ atoi(argv[1]);   new_value.it_value.tv_nsec =/*now.tv_nsec*/0;   new_value.it_interval.tv_sec = atoi(argv[2]);   new_value.it_interval.tv_nsec = 0;   int fd = timerfd_create(/*CLOCK_REALTIME*/CLOCK_MONOTONIC, 0);   if (fd == -1)   handle_error("timerfd_create");   if (timerfd_settime(fd, /*TFD_TIMER_ABSTIME*/0, &new_value, NULL) == -1)   handle_error("timerfd_settime");   printTime();   printf("timer started\n");      for (uint64_t tot_exp = 0; tot_exp < atoi(argv[3]);)    {       uint64_t exp;   ssize_t s = read(fd, &exp, sizeof(uint64_t));   if (s != sizeof(uint64_t))   handle_error("read");   tot_exp += exp;   printTime();   printf("read: %llu; total=%llu\n",exp, tot_exp);   }   exit(EXIT_SUCCESS);}



#include <iostream>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <errno.h>using namespace std;int filedes[2];int main( void ){    char buf[80];    pid_t pid;        pipe( filedes );    fcntl(filedes[0], F_SETFL, O_NONBLOCK);    fcntl(filedes[1], F_SETFL, O_NONBLOCK);    int epoll_fd = epoll_create(20);    if (epoll_fd!= -1)fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);     epoll_event ev = { 0, { 0 } };    ev.events = EPOLLIN | EPOLLERR | EPOLLET;    ev.data.fd = filedes[0];    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, filedes[0], &ev);    pid=fork();            if (pid > 0)    {        printf( "This is in the father process,here write a string to the pipe.\n" );        char s[] = "Hello world , this is write by pipe.\n";        write( filedes[1], s, sizeof(s) );while(1){sleep(10);epoll_event ev = { 0, { 0 } };  ev.events = EPOLLIN | EPOLLERR | EPOLLET;  ev.data.fd = filedes[0];  epoll_ctl(epoll_fd, EPOLL_CTL_MOD, filedes[0], &ev);printf( "interrupt send\n" );}    }    else if(pid == 0)    {        printf( "This is in the child process,here read a string from the pipe.\n" );while(1){epoll_event events[128];int num_events = epoll_wait(epoll_fd, events, 20, 10000);for (int i = 0; i < num_events; ++i){int  fd = events[i].data.fd;if (fd == filedes[0]){printf("interrupt recv\n");}}}           }     close( filedes[0] );     close( filedes[1] );      close(epoll_fd);    //waitpid( pid, NULL, 0 );        return 0;}


timerfd简单的性能测试:
申请1000个定时器,超时间定位1s,每秒超时一次,发现cpu占用率在3.0G的cpu上大概为1%,10000个定时器的话再7%左右,而且不会出现同时超时两个的情况,如果有printf到前台,则一般会出现定时器超时多次(3-5)才回调。


0 0
原创粉丝点击