Skip to content
Snippets Groups Projects
Commit af680233 authored by Christian Dietrich's avatar Christian Dietrich
Browse files

Dec 13 -- Santas Postbox (2)

Article:  https://ibr.cs.tu-bs.de/advent/13-postbox/
Workload: ~118 source-code lines
parent 67eabc0b
No related branches found
Tags template_13
No related merge requests found
PROG = postbox
DEPS = postbox.c fifo.c domain.c
DEPS += mq_send signalfd.c mqueue.c
${PROG}: ${DEPS}
gcc ${PROG}.c -o $@ -Wall -g -lrt
run: ${PROG}
./${PROG}
mq_send: mq_send.c
gcc $< -o $@ -Wall -g -lrt
strace: ${PROG}
strace ./${PROG}
clean:
rm -f ./${PROG}
int domain_prepare(int epoll_fd) {
printf("... by socket: echo 2 | nc -U socket\n");
return -1;
}
void domain_accept(int epoll_fd, int sock_fd, int events) {
}
void domain_recv(int epoll_fd, int sock_fd, int events) {
}
int fifo_prepare(int epoll_fd) {
printf("... by fifo: echo 1 > fifo\n");
return -1;
}
void fifo_handle(int epoll_fd, int fifo_fd, int events) {
}
#include <mqueue.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while(0)
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "usage: %s DATA\n", argv[0]);
return -1;
}
int msg_fd = mq_open("/postbox", O_WRONLY);
if (msg_fd < 0) die("mq_open");
int rc = mq_send(msg_fd, argv[1], strlen(argv[1]), 0);
if (rc < 0) die("mq_send");
}
int mqueue_prepare(int epoll_fd) {
printf("... by mq_send: ./mq_send 4 (see also `cat /dev/mqueue/postbox`)\n");
return -1;
}
void mqueue_handle(int epoll_fd, int msg_fd, int events) {
}
#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <assert.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <mqueue.h>
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while(0)
// Adds a file descriptor to an open epoll instance's list of
// interesting file descriptors.
//// events - For which events are we waiting (usually EPOLLIN)
//// data - The kernel returns this data when an event occurs
void epoll_add(int epoll_fd, int fd, int events) {
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
die("epoll_ctl: activate");
}
}
// Remove a file descriptor from the interest list.
void epoll_del(int epoll_fd, int fd) {
if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) {
die("epoll_ctl: reset");
}
}
#include "fifo.c"
#include "domain.c"
#include "signalfd.c"
#include "mqueue.c"
struct postbox {
int fd;
int (*prepare)(int epoll_fd);
void (*handle)(int epoll_fd, int fd, int events);
};
struct postbox boxes[] = {
{-1, fifo_prepare, fifo_handle},
{-1, domain_prepare, domain_accept},
{-1, signalfd_prepare, signalfd_handle},
{-1, mqueue_prepare, mqueue_handle},
// This must be the last entry
{-1, NULL, domain_recv}, // Fallback
};
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
int main() {
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1)
die("epoll_create");
printf("Santas Postbox is open! Send your requests ...\n");
// Initialize all backends by calling the prepare method
for (int i = 0; i < ARRAY_SIZE(boxes); i++) {
if (boxes[i].prepare) {
boxes[i].fd = boxes[i].prepare(epoll_fd);
}
}
while (true) {
// We use epoll_wait(2) to wait for at least one event, but we
// can receive up to ten events. We do not set a timeout but
// wait forever if necessary.
struct epoll_event event[10];
int nfds = epoll_wait(epoll_fd, event, 10, -1);
for (int n = 0; n < nfds; n++) {
int fd = event[n].data.fd;
for (int i = 0; i < ARRAY_SIZE(boxes); i++) {
if (boxes[i].fd == fd || boxes[i].fd == -1) {
boxes[i].handle(epoll_fd, fd, event[n].events);
break;
}
}
}
}
}
int signalfd_prepare(int epoll_fd) {
printf("... by signal: /bin/kill -USR1 -q 3 %d \n", getpid());
return -1;
}
void signalfd_handle(int epoll_fd, int signal_fd, int events) {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment