While trying to resolve some debugging issues , I added some printf-s to my code :
I used that code :
struct PipeShm
{
int init;
sem_t sema;
...
...
}
struct PipeShm * sharedPipe = NULL;
func2:
int func2()
{
if (!sharedPipe)
{
int myFd = shm_open ("/myregion", O_CREAT | O_TRUNC | O_RDWR, 0666);
if (myFd == -1)
error_out ("shm_open");
// allocate some memory in the region in the size of the struct
int retAlloc = ftruncate (myFd, sizeof * sharedPipe);
if (retAlloc < 0) // check if allocation failed
error_out("ftruncate");
// map the region and shared in with all the processes
sharedPipe = mmap (NULL, sizeof * sharedPipe,PROT_READ | PROT_WRITE,MAP_SHARED , myFd, 0);
if (sharedPipe == MAP_FAILED) // check if the allocation failed
error_out("mmap");
// put initial value
int value = -10;
// get the value of the semaphore
sem_getvalue(&sharedPipe->semaphore, &value);
if (sharedPipe->init != TRUE) // get in here only if init is NOT TRUE !
{
if (!sem_init (&sharedPipe->semaphore, 1, 1)) // initialize the semaphore to 0
{
sharedPipe->init = TRUE;
sharedPipe->flag = FALSE;
sharedPipe->ptr1 = NULL;
sharedPipe->ptr2 = NULL;
sharedPipe->status1 = -10;
sharedPipe->status2 = -10;
sharedPipe->semaphoreFlag = FALSE;
sharedPipe->currentPipeIndex = 0;
printf("\nI'm inside the critical section! my init is: %d\n" , sharedPipe->init);
}
else
perror ("shm_pipe_init");
printf("\nI'm out the critical section! my init is: %d\n" , sharedPipe->init);
}
}
return 1; // always successful
}
With that main :
int main()
{
int spd, pid, rb;
char buff[4096];
fork();
func2();
return 0;
}
And got this :
shm_pipe_mkfifo: File exists
I'm inside the critical section! my init is: 1
I'm out the critical section! my init is: 1
Output:hello world!
I'm inside the critical section! my init is: 1
I'm out the critical section! my init is: 1
It seems that the shared memory is not so shared , why ?
-
The segment is shared between all processes due to
MAP_SHARED | MAP_ANONYMOUS, so why both processes have the samebeforeandaftervalues ? -
It seems that each process has its own semaphore even though it was shared between them , so what went wrong ?
Thanks
Since you use the
MAP_ANONYMOUSflag tommap, themyFdargument is ignored, and you create two independent shared memory chunks, one in each process, which have no relation to each other.If you get rid of
MAP_ANONYMOUSyou’ll then only have one shared memory chunk, but you then have the problem of not callingsem_init. On Linux with NPTL it will actually work, as clearing a sem_t to all 0 bytes (the initial state here) is equivalent tosem_init(&sema, anything, 0);(NPTL ignores the pshared flag), but that’s not portable to other systems.Per Karoly’s comment on another answer, there’s also a race condition due O_TRUNC on the open call. If the second thread calls
openafter the first thread has already started modifying the semaphore, that TRUNC will clobber the semaphore state. Probably the best solution is to move the code creating, opening, and mmaping the shared memory to a different function that is called BEFORE calling fork.edit
To fix the O_TRUNC problem, you can’t have more than one process calling shm_open with O_TRUNC. But if you just get rid of the O_TRUNC, then you have the startup problem that if the shared memory object already exists (from a previous run of the program), it may not be in a predictable state. On possibility is to split off the beginning of func2:
Alternately you could keep the same code (just get rid of O_TRUNC) and add a cleanup before the fork:
In all cases you’ll still have problem if you run multiple copies of your program at the same time.