timerfd.c (1848B)
1 #include <sys/epoll.h> 2 #include <sys/timerfd.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <ctype.h> 8 9 static int timer, event_queue; 10 11 static void succeed_or_die(int n, char const* msg) 12 { 13 if (n >= 0) 14 return; 15 16 perror(msg); 17 exit(1); 18 } 19 20 static void stdin_event(void) 21 { 22 char buf[64]; 23 int n = read(STDIN_FILENO, buf, sizeof buf - 1); 24 25 if (n <= 0) 26 { 27 puts("Stdin closed."); 28 exit(0); 29 } 30 for (int i = 0; i < n; ++i) 31 if (iscntrl(buf[i])) 32 buf[i] = '.'; 33 buf[n] = '\0'; 34 35 printf("Stdin: '%s'\n", buf); 36 } 37 38 static void timerfd_event(void) 39 { 40 static uint64_t ticks; 41 uint64_t new_ticks; 42 read(timer, &new_ticks, sizeof new_ticks); 43 ticks += new_ticks; 44 printf("Tick +%lu %lu\n", new_ticks, ticks); 45 } 46 47 int main() 48 { 49 timer = timerfd_create(CLOCK_MONOTONIC, 0); 50 succeed_or_die(timer, "timerfd_create"); 51 52 int res = timerfd_settime(timer, 0, &(struct itimerspec){ 53 .it_interval = {1, 0}, /* Interval for periodic timer */ 54 .it_value = {1, 0}, /* Initial expiration */ 55 }, NULL); 56 succeed_or_die(res, "timerfd_settime"); 57 58 event_queue = epoll_create1(0); 59 succeed_or_die(event_queue, "epoll_create2"); 60 61 res = epoll_ctl(event_queue, EPOLL_CTL_ADD, STDIN_FILENO, &(struct epoll_event){ 62 .events = EPOLLIN, 63 .data.ptr = stdin_event, 64 }); 65 succeed_or_die(res, "epoll_ctl"); 66 67 res = epoll_ctl(event_queue, EPOLL_CTL_ADD, timer, &(struct epoll_event){ 68 .events = EPOLLIN, 69 .data.ptr = timerfd_event, 70 }); 71 succeed_or_die(res, "epoll_ctl"); 72 73 for (;;) 74 { 75 struct epoll_event events[8]; 76 int n_events = epoll_wait(event_queue, events, sizeof events / sizeof *events, -1); 77 succeed_or_die(n_events, "epoll_wait"); 78 79 for (int i = 0; i < n_events; ++i) 80 ((void(*)(void))events[i].data.ptr)(); 81 } 82 }