From 04576dc2a3f761eb041b808b56f13a58052e7655 Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Sun, 24 May 2020 12:19:52 +0200 Subject: Moved back to 02_exercise --- 02_exercise/beispiele/pipe_bidirect/pingpong.c | 125 +++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 02_exercise/beispiele/pipe_bidirect/pingpong.c (limited to '02_exercise/beispiele/pipe_bidirect/pingpong.c') diff --git a/02_exercise/beispiele/pipe_bidirect/pingpong.c b/02_exercise/beispiele/pipe_bidirect/pingpong.c new file mode 100644 index 0000000..f38394f --- /dev/null +++ b/02_exercise/beispiele/pipe_bidirect/pingpong.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include + +static int split(int fd[2]); +static int redir(int fd, const char *file); +static void sig_handler(int sig); + +static int parent; + +int main(void) { + ssize_t bytes; + char buf[256]; + int fd[2]; + + // disable buffering for stdout + setvbuf(stdout, NULL, _IONBF, 0); + + // redirect stdout to write into a file + if (redir(1, "log.txt") < 0) { + perror("redir()"); + exit(-1); + } + + // install the signal handler for Ctrl+C + if (signal(SIGINT, sig_handler) == SIG_ERR) { + perror("signal()"); + exit(-1); + } + + // split processes and assign file descriptors for communication + switch (split(fd)) { + case -1: // error + exit(-1); + + case 0: // child + while ((bytes = read(fd[0], buf, sizeof(buf))) > 0) { + printf("[%u]: %s\n", getpid(), buf); + sleep(1); + write(fd[1], "pong", 5); + } + break; + + case 1: // parent + parent = 1; + write(fd[1], "ping", 5); + while ((bytes = read(fd[0], buf, sizeof(buf))) > 0) { + printf("[%u]: %s\n", getpid(), buf); + sleep(1); + write(fd[1], "ping", 5); + } + break; + } + + // close the file descriptors + close(fd[0]); + close(fd[1]); + + return 0; +} + +int split(int fd[2]) { + int pfd[2][2]; + + if (pipe(pfd[0]) < 0) { + perror("pipe()"); + goto err_pipe1; + } + + if (pipe(pfd[1]) < 0) { + perror("pipe()"); + goto err_pipe2; + } + + switch (fork()) { + case -1: + perror("fork()"); + goto err_fork; + + case 0: // child process + close(pfd[0][1]); // close write for child + close(pfd[1][0]); // close read for parent + fd[0] = pfd[0][0]; // keep read for child + fd[1] = pfd[1][1]; // keep write for parent + return 0; + + default: // parent process + close(pfd[1][1]); // close write for parent + close(pfd[0][0]); // close read for child + fd[0] = pfd[1][0]; // keep read for parent + fd[1] = pfd[0][1]; // keep write for child + return 1; + } + +err_fork: + close(pfd[1][0]); + close(pfd[1][1]); +err_pipe2: + close(pfd[0][0]); + close(pfd[0][1]); +err_pipe1: + return -1; +} + +int redir(int fd, const char *file) { + int fd2 = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + + if (fd2 < 0) + return -1; + + dup2(fd2, fd); + close(fd2); + + return 0; +} + +void sig_handler(int sig) { + if (parent) { + const char msg[] = "Programmabbruch durch Nutzer\n"; + write(1, msg, sizeof(msg) - 1); + } + exit(0); +} -- cgit v1.2.3-54-g00ecf