I have 3 processes and two pipes. Process Producer generates a character and sends it to process Buffer via the Input pipe. Process Buffer stores the data in an array, then sends it to process Consumer via the Output pipe. Consumer then prints the data. Is it possible to do this in a nonblocking way?
Currently, the Consumer process only reads once a second and the Producer process outputs once every 0.3 seconds. The Consumer call blocks the Buffer process and the multiple Producer outputs are not stored in the buffer, staying in the Input pipe until the next loop. The program currently runs for 5 seconds, which can be modified by the length variable at the beginning of main().
#include "stdio.h"//get from and print to console
#include "stdlib.h"//free and malloc
#include "unistd.h"//fork(), exec(), sleep(), and pid_t
#include "sys/types.h"//pid_t
#include <string.h>//strtok
#include "sys/wait.h"//waitpid()
#include <time.h>//time()
#include <fcntl.h>//O_NONBLOCK, fd manipulation
#include <sys/stat.h>//mkfifo()
const int BUFFSIZE = 1000;
void buffer(time_t start, int len, char* buff, const char *ppipe, const char *cpipe);
void producer(time_t start, int len, const char *ppipe);
void consumer(time_t start, int len, const char *cpipe);
void main() {
int length = 5;//length of program (seconds)
char *buff = malloc(BUFFSIZE*sizeof(char));
for(int i = 0;i<BUFFSIZE;i++) {
buff[i] = '*';
}
//create the needed pipes
const char *pfifo1 = "producer1";
const char *cfifo1 = "consumer1";
mkfifo(pfifo1, 0666);
mkfifo(cfifo1, 0666);
time_t start = time(NULL);
srand(start);
pid_t buf_p = fork();//fork off the buffer
if(buf_p == 0) {
buffer(start, length, buff, pfifo1, cfifo1);
}
pid_t prod_p = fork();//fork off the producer
if(prod_p == 0) {
producer(start, length, max_p, pfifo1);
}
pid_t con_p = fork();//fork off the consumer
if(con_p == 0) {
consumer(start, length, max_c, cfifo1);
}
pid_t wpid;//wait til the processes are finished
while((wpid=wait(NULL))!=-1) {
}
unlink(pfifo1);//delete the pipes
unlink(cfifo1);
free(buff);
printf("All processes terminated.\n");
}
void buffer(time_t start, int len, char *buff, const char *ppipe, const char *cpipe) {
char input;
int check;//checks if the pipe has a value
int exitind = 0;
int inputind = 0;
int infd = open(ppipe, O_RDONLY, O_NONBLOCK);
int exfd = open(cpipe, O_WRONLY, O_NONBLOCK);
while(time(NULL)-start<len) {//loop until the program time ends
//get the product from the producers
if(buff[inputind]=='*') {//if the buffer is not full
check = read(infd, &input, 1);//read from the input pipe
if(check !=-1) {//ie there was input in the pipe
buff[inputind] = input;//add it to the buffer
inputind=(inputind+1)%BUFFSIZE;//inputind loops.
}
}
//write from the array to the exit pipe
if(buff[exitind]!='*') {//if the buffer has data
char output = buff[exitind];
check = write(exfd, &output, 1);
if(check!=-1) {
buff[exitind] = '*';//clear the entry
exitind=(exitind+1)%BUFFSIZE;//exitind loops.
}
}
}
for(int i = 0;i<BUFFSIZE;i++) {
printf("%c ", buff[i]);
if((i+1)%40 ==0) {
printf("\n");
}
}
close(infd);
close(exfd);
printf("Buffer ended.\n");
exit(0);
}
//function that each producer process runs.
void producer(time_t start, int len, const char *ppipe) {
int fd = open(ppipe, O_WRONLY);
while(time(NULL)-start<len) {//loop until the program time ends
char output = 'A'+(rand()%26);//generate random character,
printf("Producer value = %c\n", output);
write(fd, &output, 1);//write it to the input pipe
usleep(300000);//0.3 seconds of sleep
}
close(fd);
printf("Producer ended\n");
exit(0);
}
//function that each consumer process runs.
void consumer(time_t start, int len, const char *cpipe) {
int fd = open(cpipe, O_RDONLY);
char input;
while(time(NULL)-start<len) {//loop until the program time ends
sleep(1);
//read a character from the buffer
read(fd, &input, 1);
printf("Consumer, value = %c\n", input);
}
close(fd);
printf("Consumer ended\n");
exit(0);
}