examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 44dc0f57e75e875fc0907b5e0afd6d936ca682d1
parent 78e7d57d4b5f79651731d3a16ecf4e5a37b9d70b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Wed, 10 Aug 2022 16:49:54 +0100

epoll: Generalize event-loop example

Diffstat:
Asrc/epoll.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/timerfd.c | 82-------------------------------------------------------------------------------
2 files changed, 101 insertions(+), 82 deletions(-)

diff --git a/src/epoll.c b/src/epoll.c @@ -0,0 +1,101 @@ +#include <sys/epoll.h> +#include <sys/timerfd.h> +#include <sys/signalfd.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <err.h> +#include <errno.h> + +static int timer, signals, event_queue; + +static void check_err(char const* msg) +{ + if (errno) + err(1, msg); +} + +static void stdin_event(void) +{ + char buf[64]; + int n = read(STDIN_FILENO, buf, sizeof buf - 1); + + if (n <= 0) + { + puts("Stdin closed."); + exit(0); + } + for (int i = 0; i < n; ++i) + if (iscntrl(buf[i])) + buf[i] = '.'; + buf[n] = '\0'; + + printf("Stdin: '%s'\n", buf); +} + +static void timerfd_event(void) +{ + static uint64_t ticks; + uint64_t new_ticks; + read(timer, &new_ticks, sizeof new_ticks); + ticks += new_ticks; + printf("Tick: +%lu %lu\n", new_ticks, ticks); +} + +static void signalfd_event(void) +{ + struct signalfd_siginfo buf; + read(signals, &buf, sizeof buf); + check_err("read"); + printf("Signal: %s\n", strsignal(buf.ssi_signo)); +} + +static void add_epollin(int fd, void(*cb)()) +{ + epoll_ctl(event_queue, EPOLL_CTL_ADD, fd, &(struct epoll_event){ + .events = EPOLLIN, + .data.ptr = cb, + }); + check_err("epoll_ctl"); +} + +int main() +{ + timer = timerfd_create(CLOCK_MONOTONIC, 0); + check_err("timerfd_create"); + timerfd_settime(timer, 0, &(struct itimerspec){ + .it_interval = {1, 0}, /* Interval for periodic timer */ + .it_value = {1, 0}, /* Initial expiration */ + }, NULL); + check_err("timerfd_settime"); + + sigset_t sigset; + sigemptyset(&sigset); + check_err("sigemptyset"); + sigaddset(&sigset, SIGINT); + check_err("sigaddset"); + sigprocmask(SIG_SETMASK, &sigset, NULL); + check_err("sigprocmask"); + signals = signalfd(-1, &sigset, 0); + check_err("signalfd"); + + event_queue = epoll_create1(0); + check_err("epoll_create2"); + add_epollin(STDIN_FILENO, stdin_event); + add_epollin(timer, timerfd_event); + add_epollin(signals, signalfd_event); + + for (;;) + { + struct epoll_event events[8]; + int n_events = epoll_wait(event_queue, events, sizeof events / sizeof *events, -1); + check_err("epoll_wait"); + + for (int i = 0; i < n_events; ++i) + ((void(*)(void))events[i].data.ptr)(); + } +} diff --git a/src/timerfd.c b/src/timerfd.c @@ -1,82 +0,0 @@ -#include <sys/epoll.h> -#include <sys/timerfd.h> -#include <unistd.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <ctype.h> - -static int timer, event_queue; - -static void succeed_or_die(int n, char const* msg) -{ - if (n >= 0) - return; - - perror(msg); - exit(1); -} - -static void stdin_event(void) -{ - char buf[64]; - int n = read(STDIN_FILENO, buf, sizeof buf - 1); - - if (n <= 0) - { - puts("Stdin closed."); - exit(0); - } - for (int i = 0; i < n; ++i) - if (iscntrl(buf[i])) - buf[i] = '.'; - buf[n] = '\0'; - - printf("Stdin: '%s'\n", buf); -} - -static void timerfd_event(void) -{ - static uint64_t ticks; - uint64_t new_ticks; - read(timer, &new_ticks, sizeof new_ticks); - ticks += new_ticks; - printf("Tick +%lu %lu\n", new_ticks, ticks); -} - -int main() -{ - timer = timerfd_create(CLOCK_MONOTONIC, 0); - succeed_or_die(timer, "timerfd_create"); - - int res = timerfd_settime(timer, 0, &(struct itimerspec){ - .it_interval = {1, 0}, /* Interval for periodic timer */ - .it_value = {1, 0}, /* Initial expiration */ - }, NULL); - succeed_or_die(res, "timerfd_settime"); - - event_queue = epoll_create1(0); - succeed_or_die(event_queue, "epoll_create2"); - - res = epoll_ctl(event_queue, EPOLL_CTL_ADD, STDIN_FILENO, &(struct epoll_event){ - .events = EPOLLIN, - .data.ptr = stdin_event, - }); - succeed_or_die(res, "epoll_ctl"); - - res = epoll_ctl(event_queue, EPOLL_CTL_ADD, timer, &(struct epoll_event){ - .events = EPOLLIN, - .data.ptr = timerfd_event, - }); - succeed_or_die(res, "epoll_ctl"); - - for (;;) - { - struct epoll_event events[8]; - int n_events = epoll_wait(event_queue, events, sizeof events / sizeof *events, -1); - succeed_or_die(n_events, "epoll_wait"); - - for (int i = 0; i < n_events; ++i) - ((void(*)(void))events[i].data.ptr)(); - } -}