Last active
July 25, 2020 14:23
-
-
Save spacelatte/6638d93517bb825dc5ef4cc4e37856d5 to your computer and use it in GitHub Desktop.
send & receive #pipe pair example in #c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <signal.h> | |
#include <unistd.h> | |
#include <time.h> | |
#include "pipe.h" | |
typedef struct PidPair { | |
pid_t reader; | |
pid_t writer; | |
} pid_pair_t; | |
void | |
sleeper(long id, pipe_t *chan) { | |
srandomdev(); | |
long period = 1000L + random()%9000L; | |
char buf[80]; sprintf(buf, "%3ld: sleeping for %ld...", id, period); | |
pipe_send(chan, buf); | |
usleep(1000L * period); | |
return; | |
} | |
void handler(int sig) { | |
fprintf(stderr, "Got %d, exiting... (%d)\n", sig, getpid()); | |
return exit(0); | |
} | |
pid_t | |
main_worker(long id, pipe_t *channel, const char *expr) { | |
pid_t pid = fork(); | |
if(pid) return pid; | |
signal(SIGTERM, handler); | |
signal(SIGINT, handler); | |
char buf[80]; | |
snprintf(buf, sizeof(buf), "%3ld: calculating: '%s'...", id, expr); | |
pipe_send(channel, buf); | |
sleeper(id, channel); | |
srandomdev(); | |
char res[80]; | |
snprintf(res, sizeof(res), "%3ld: random result for ya: %ld", id, random()); | |
pipe_send(channel, res); | |
//char *resp = calloc(PIPE_PACKET_SIZE, sizeof(char)); | |
//pipe_recv(channel, &resp); | |
//fprintf(stdout, "%3ld: recv: '%s'\n", id, resp); | |
//free(resp); | |
//sleeper(id, channel); | |
kill(getppid(), SIGUSR1); | |
close(channel->io.write); | |
close(channel->io.read); | |
return (-id); | |
} | |
pid_t | |
main_decoder(long id, pipe_t *chan) { | |
pid_t pid = fork(); | |
if(pid) return pid; | |
signal(SIGPIPE, handler); | |
while(chan && chan->io.read) { | |
char *buf = calloc(PIPE_PACKET_SIZE, sizeof(char)); | |
pipe_recv(chan, &buf); | |
printf("%3ld: recv: '%s'\n", id, buf); | |
free(buf); | |
//pipe_send(chan, "got your message bro!"); | |
usleep(1000L); | |
continue; | |
} | |
return (-pid); | |
} | |
pid_pair_t | |
main_program(const char *arg) { | |
static long monotonic_counter; | |
pipe_t *pipefd = NULL; | |
pid_pair_t pair; | |
monotonic_counter += 1; | |
if(!pipefd) { | |
pipefd = malloc(sizeof(pipe_t)); | |
pipe(pipefd->rawfd); | |
} | |
pair.reader = main_decoder(monotonic_counter, pipefd); | |
pair.writer = main_worker(monotonic_counter, pipefd, arg); | |
return pair; | |
} | |
void main_signal_handler(int sig) { | |
fprintf(stderr, "main-sig: %d\n", sig); | |
return; | |
} | |
int | |
main(int argc, char const **argv) { | |
pid_pair_t pairs[argc]; | |
srandomdev(); | |
signal(SIGUSR1, main_signal_handler); | |
signal(SIGUSR2, main_signal_handler); | |
//signal(SIGTERM, main_signal_handler); | |
//signal(SIGCHLD, main_signal_handler); | |
//signal(SIGPIPE, main_signal_handler); | |
//signal(SIGINT, main_signal_handler); | |
for(int i=0; i<argc; i++) { | |
pid_pair_t child = main_program(argv[i]); | |
if(child.reader < 0 || child.writer < 0) { | |
exit(0); break; | |
} | |
//fprintf(stderr, "> read:%8d write:%8d\n", child.reader, child.writer); | |
pairs[i] = child; | |
continue; | |
} | |
fprintf(stderr, "Spawning killer...\n"); | |
pid_t killer = fork(); | |
if(!killer) { // killer kills all processes after timeout | |
signal(SIGINT, exit); | |
sleep(11); | |
fprintf(stderr, "Timeout Reached! Interrupting!\n"); | |
for(int i=0; i<argc; i++) { | |
kill(pairs[i].reader, SIGINT); | |
kill(pairs[i].writer, SIGINT); | |
continue; | |
} | |
return 0; | |
} | |
for(int i=0; i<argc; i++) waitpid(pairs[i].writer, NULL, 0); | |
fprintf(stderr, "Program done, killing killer...\n"); | |
kill(killer, SIGINT); // ok, kill the killer :) | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env make -f | |
CC = cc | |
LD = ld | |
CFLAGS = -g -O0 | |
LDFLAGS = -lSystem -arch x86_64 -macosx_version_min 10.9 | |
MODULES = $(addsuffix .o, pipe main) | |
TARGET = main.exe | |
all: $(TARGET) | |
./$(TARGET) hello world some parameters hell yeah | |
clean: | |
rm -f $(MODULES) $(TARGET) | |
$(TARGET): $(MODULES) | |
$(LD) $(LDFLAGS) -o $@ $^ | |
%.o: %.c | |
$(CC) $(CFLAGS) -o $@ -c $^ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include "pipe.h" | |
static unsigned long pipe_monotonic_counter; | |
ssize_t | |
pipe_send(pipe_t *chan, const char *msg) { | |
data_t data; | |
data.id = pipe_monotonic_counter++; | |
data.length = strlen(msg); | |
strncpy(data.buffer, msg, PIPE_PACKET_SIZE); | |
return write(chan->io.write, &data, sizeof(data)); | |
} | |
ssize_t | |
pipe_recv(pipe_t *chan, char **buffer) { | |
data_t data; | |
ssize_t result = read(chan->io.read, &data, sizeof(data)); | |
if(!buffer || !*buffer) { | |
*buffer = realloc(*buffer, PIPE_PACKET_SIZE); | |
} | |
strncpy(*buffer, data.buffer, PIPE_PACKET_SIZE); | |
return result; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _PIPE_H_ | |
#define _PIPE_H_ | |
#include <stdint.h> | |
#include <unistd.h> | |
#define PIPE_PACKET_SIZE 128 | |
typedef union Pipe { | |
int rawfd[2]; | |
struct PipeIO { | |
int read; | |
int write; | |
} io; | |
} pipe_t; | |
typedef struct Data { | |
uint32_t id; | |
uint32_t length; | |
char buffer[PIPE_PACKET_SIZE]; | |
} data_t; | |
ssize_t pipe_send(pipe_t *, const char *); | |
ssize_t pipe_recv(pipe_t *, char **); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment