Reputation: 21865
I've implemented a library that simulates pipe()
system call , based on shared memory .
Now , the code works OK when I'm not using any fork()
, e.g. without invoking any child processes .
My library needs to work with any given int main()
program , so the basic problem here is that the modifications with the semaphores should be made with in the library , and not in a main
program .
The library :
Here is the library :
static int flag = FALSE;
static int mutex_init = 0;
static pthread_mutex_t lock;
#define BUFFER 4096
int my_new_finish()
{
return 1; // always successful
}
void error_out(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
Now , this library works OK when I'm not using main
program that invoke fork()
.
But , when I do use fork()
, all hell brakes loose .
For example :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int spd, pid, rb;
char buff[4096];
my_new_init();
if (my_new_fifo("tmp_shm_pipe",0666) < 0)
{
perror("my_new_fifo");
exit(1);
}
if (fork())
{
spd = my_new_open("tmp_shm_pipe", O_RDONLY, 0600);
if (spd < 0)
{
perror("PARENT: my_new_open");
exit(1);
}
rb = my_new_read(spd, buff, sizeof(buff));
if (rb > 0)
write(1, buff, rb);
}
else
{
spd = my_new_open("tmp_shm_pipe", O_WRONLY, 0600);
if (spd < 0)
{
perror("SON: my_new_open");
exit(1);
}
my_new_write(spd, "hello world!\n", sizeof("hello world!\n"));
}
my_new_close(spd);
my_new_un_link("tmp_shm_pipe");
my_new_finish();
return 0;
}
My questions are :
How can I use semaphores with the above library , where I don't "know" the main()
program that I'd be given ?
I've tried to put semaphores in the library (not in the main()
program) but
it didn't work out good . Can you please explain how can I do that correctly ?
Remarks :
Please pay attention that this main
is just an example , and I could be given countless other main
program.
This is homework
Much appreciated
Upvotes: 2
Views: 1439
Reputation: 19403
In your function my_new_init
you'd need to create a shared semaphone in shared memory - but have a guard around it so that it is only called once; this guard would typically be inside the library module using a module static (or class static) variable.
sem_t *my_semaphone;
static int init = 0;
int my_new_init()
{
if (!init)
{
my_semaphone = mmap(NULL, sizeof *my_semaphone, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (!sem_init(my_semaphone, 1, 1))
{
init = TRUE;
}
else
perror("Sem_init");
}
return 1; // always successful
}
Then in my_new_read at the top:
ssize_t my_new_read(int spd, void *buf, size_t count)
{
char array[4096];
memset(array, '\0', 4096);
ssize_t returnVal = 0;
sem_wait(my_semaphone);
and in my_new_write release the semaphone after you've written something.
sem_post(my_semaphone);
return returnVal;
The above may need improvement as it is possible that sem_wait will return before data is ready so it may be wise to use a control structure at the beginning of your shared memory segment.
Upvotes: 2
Reputation: 2043
Ok, i'll try my best, as i do not know how familiar you are with the whole concept.
1) the most likley "correct" place for semaphores is in the read and write functions. To synchronize processes on the memorysegment, you have to put the semaphores in shared memory too. (in order to make them accessable to all Processes)
http://pdfcast.org/download/semaphores-sharedmem.pdf
this is a pdf with a good, english commented codeexample of creating, using and destroying semaphores, with a sample main. Its title is in german, but there is nothing else in there that isn't C or english.
I hope it helps and isn't too "low-leveled" for your skills^^
Upvotes: 2