I am trying to improvise a program I had written for single producer multiple consumer multi threading using counting semaphores. I want to implement inter process communication using shared memory (mmap() system call). I want to use anonymous mapping with no backing file.
This is the structure I want to share between the parent and its multiple child processes.
typedef struct Buffer{
char **Tuples;
sem_t buf_mutex,empty_count,fill_count;
} Buffer;
Buffer buffer[100];
The parent process is the mapper()
function which does produces something and puts it in buffer[i], based on some inputs. The child processes go to reducer()
function which consumes what is put in its buffer[j]. Each reducer or child process should have access to its buffer. The child processes are forked() in the main function and then the parent process control goes to mapper()
. I have initialized the synchronization primitives to be process shared.
Is my main()
method the correct way of doing it ? I am also getting type casting errors for return value of mmap()
, which is a pointer, but I am not sure how to handle it and then use it. I also think malloc()
should not be used in line 47 for allocating space to tuples but instead mmap()
itself should be used. Can anyone please help ? This is my program -
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
typedef struct Buffer{
char **Tuples;
// int count;
sem_t buf_mutex,empty_count,fill_count;
} Buffer;
Buffer buffer[100];
int numOfSlots;
int numOfReducers;
void mapper(){
//Synchronization primitives (counting semaphores) used for synchronization
//Produce something and put it in buffer[i]
}
void reducer(long b){
//Synchronization primitives (counting semaphores) for synchronization
//Consume from buffer[b]
}
int main (int argc, char *argv[]){
if(argc != 3) {
if(argc < 3)
printf("Insufficient arguments passed\n");
else
printf("Too many arguments passed\n");
return 1;
}
int i;
long r;
numOfSlots = atoi(argv[1]);
numOfReducers = atoi(argv[2]);
for(i=0; i<numOfReducers; i++){
buffer[i] = (struct Buffer *) mmap(NULL, sizeof(buffer[i]), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (buffer[i] == MAP_FAILED)
errExit("mmap");
buffer[i].Tuples = malloc(numOfSlots * sizeof(char *));
sem_init(&buffer[i].buf_mutex, 1, 1);
sem_init(&buffer[i].fill_count, 1, 0);
sem_init(&buffer[i].empty_count, 1, numOfSlots);
}
for(r=0;r<numOfReducers;r++){ // loop will run n times (n=5)
if(fork() == 0){
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
Reducer(r);
exit(0);
}
}
mapper();
for(r=0;r<numOfReducers;r++) // loop will run n times (n=5)
wait(NULL);
}
These are the links I am trying to follow - https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_init.txt https://github.com/bradfa/tlpi-dist/blob/master/mmap/anon_mmap.c
Thanks, Harrish
After researching on the net. I came up with this solution which works. One more thing I learnt is char *var="hello"
is stored in read only memory in the text segment, which means the child processes can also access it. So strcpy()
would be a better option for anything else.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <string.h>
typedef struct Buffer{
char **Tuples;
// int count;
sem_t buf_mutex,empty_count,fill_count;
int inSlotIndex;
int outSlotIndex;
} Buffer;
Buffer *buffer;
int numOfSlots;
int numOfReducers;
int *done;
void mapper(){
//Synchronization primitives (counting semaphores) used for synchronization
//read continuously from a file, produce something and put it in buffer[i]
//Here is an example
char *temp = "trail";
sem_wait(&buffer[1].empty_count);
sem_wait(&buffer[1].buf_mutex);
// Use strcpy() for anything other than string literal
buffer[1].Tuples[0] = temp;
buffer[1].inSlotIndex = 3;
buffer[1].outSlotIndex = 4;
sem_post(&buffer[1].buf_mutex);
sem_post(&buffer[1].fill_count);
*done = 1;
}
void reducer(long tid, Buffer *buffer, int *done){
//Synchronization primitives (counting semaphores) used for synchronization
//Consume from buffer[b]
sem_wait(&buffer[tid].fill_count);
sem_wait(&buffer[tid].buf_mutex);
printf("%s\n", buffer[tid].Tuples[0]);
printf("%d\n", buffer[tid].inSlotIndex);
printf("%d\n", buffer[tid].outSlotIndex);
sem_post(&buffer[tid].buf_mutex);
sem_post(&buffer[tid].empty_count);
if(*done == 1)
printf("DONE\n");
}
int main (int argc, char *argv[])
{
if(argc != 3) {
if(argc < 3)
printf("Insufficient arguments passed\n");
else
printf("Too many arguments passed\n");
return 1;
}
srand(time(NULL));
int i, j;
long r;
char *temp;
numOfSlots = atoi(argv[1]);
numOfReducers = atoi(argv[2]);
buffer = (struct Buffer *)mmap(NULL, numOfReducers * sizeof(struct Buffer), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(buffer == MAP_FAILED){
printf("EXITING");
exit(EXIT_FAILURE);
}
done = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (done == MAP_FAILED){
printf("exiting\n");
}
*done = 0;
for(i=0; i<numOfReducers; i++){
buffer[i].Tuples = mmap(NULL, numOfSlots * sizeof(char *), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(buffer[i].Tuples == MAP_FAILED){
printf("EXITING");
exit(EXIT_FAILURE);
}
for(j=0; j<numOfSlots; j++){
temp = (char *)mmap(NULL, 30 * sizeof(char), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
temp = strcpy(temp, "");
buffer[i].Tuples[j] = temp;
}
sem_init(&buffer[i].buf_mutex, 1, 1);
sem_init(&buffer[i].fill_count, 1, 0);
sem_init(&buffer[i].empty_count, 1, numOfSlots);
}
for(r=0;r<numOfReducers;r++){ // loop will run n times (n=5)
if(fork() == 0){
printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
reducer(r, buffer, done);
exit(0);
}
}
mapper();
for(r=0;r<numOfReducers;r++) // loop will run n times (n=5)
wait(NULL);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.