広告
Linuxのsignalfdを使ってシグナルをepollで監視する。
signalfd.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/epoll.h> #include <sys/signalfd.h> #include <errno.h> #define MAX_EVENTS 10 #define RET_OK (0) #define RET_NG (-1) #define PERROR(X) \ {\ char __strerr[128] = {0};\ int errcode = errno;\ \ strerror_r(errcode, __strerr, sizeof(__strerr));\ printf(X " failed(%d:%s)\n", errcode, __strerr);\ } static int createSignalFd(int* sfd); static int waitSignalEvent(int sfd); int main(void) { int sfd = -1; int ret = RET_OK; do { ret = createSignalFd(&sfd); if (RET_OK != ret) { printf("createSignalFd() failed(%d)\n", ret); break; } ret = waitSignalEvent(sfd); if (RET_OK != ret) { printf("waitSignalEvent"); close(sfd); break; } close(sfd); } while(0); return 0; } static int createSignalFd(int* sfd) { int ret = RET_OK; sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); do { if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { PERROR("sigprocmask()"); break; } *sfd = signalfd(-1, &mask, 0); if (*sfd < 0) { PERROR("signalfd()"); ret = RET_NG; break; } } while(0); return ret; } static int waitSignalEvent(int sfd) { int ret = RET_OK; int rc = 0; int epollfd = -1; int nfds = -1; struct epoll_event events[MAX_EVENTS]; struct epoll_event evt = { .events = EPOLLIN, .data = { .fd = sfd, }, }; epollfd = epoll_create(MAX_EVENTS); if (epollfd < 0) { PERROR("epoll_create()"); goto error_end; } rc = epoll_ctl(epollfd, EPOLL_CTL_ADD, sfd, &evt); if (rc != 0) { PERROR("epoll_ctl()"); close(epollfd); goto error_end; } for(;;) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds < 0) { PERROR("epoll_wait()"); close(epollfd); break; } int fd = 0; for (fd = 0; fd < MAX_EVENTS; fd++) { if (events[fd].data.fd == sfd) { struct signalfd_siginfo fdsi; ssize_t sz = read(sfd, &fdsi, sizeof(fdsi)); if (sz < 0) { PERROR("read()"); close(epollfd); break; } printf("ssi_signo = %d\n", fdsi.ssi_signo); } } } close(epollfd); error_end: return ret; } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 |
$ gcc -std=gnu99 signalfd.c -o signalfd $ ./signalfd ssi_signo = 1 ssi_signo = 2 ssi_signo = 3 Terminated #別端末から $ killall -SIGHUP signalfd $ killall -SIGINT signalfd $ killall -SIGQUIT signalfd $ killall -SIGTERM signalfd |
広告
広告