I am building 3 multithreaded programs with pthread that need access to the same shared memory.
I have one program called parent that will create the shared memory and the other two, the children. I have been able to get the parent working with two threads, one that has a cond_wait and the other broadcasts. Then I went on to try and get it working with one of the children. I copied the code for the cond_wait thread to the child and tried to run it, but have had no luck.
This is because the child is not able to use the shared memory, I'm pretty certain it is because of how I create the shared object in the parent in the child but I have been stuck for a couple of hours and am not sure what to try now.
The parent uses this code to make the shared memory
bool create_shared_object( shared_memory_t* shm) {
const char* share_name = shared_memory_name;
shm_unlink(share_name);
shm->name = share_name;
shm->fd = shm_open(shm->name, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
if(shm->fd == -1){
fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);
return false;
}
if (ftruncate(shm->fd , MEMORY_SIZE)){
fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno);
return false;
}
shm = mmap(NULL, MEMORY_SIZE,
PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm == MAP_FAILED){
fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);
return false;
}
return true;
}
And this is what the child is using to open the object
bool create_shared_object( shared_memory_t* shm) {
const char* share_name = shared_memory_name;
shm->name = share_name;
shm->fd = shm_open(shm->name, O_RDWR, 0);
if(shm->fd == -1){
fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);
return false;
}
shm = mmap(NULL, MEMORY_SIZE,
PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm == MAP_FAILED){
fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);
return false;
}
return true;
}
For reference I define shm like this in each file shared_memory_t shm;
And this is the structure of shared_memory_t
typedef struct shm{
const char* name;
int fd;
shared_parking_t data;
}shared_memory_t;
The result of ls -l /dev/shm
shows the corresponding memory file:
-rwxr-xr-x 1 cab403 cab403 584 Sep 26 23:27 PARKING
If anyone can lend a hand I would be quite grateful
edit* I am not sure if this is important but I am using Linux
edit 2 I am checking if the child can use the shared memory by printing in a loop the value in the memory the parent changes. In this test the child only has open_shared_object and the printing for loop
edit 3 I have updated my code based on input from answers
CodePudding user response:
You should add some debug prints in the error branches to know which system call fails. For example:
#include <errno.h>
shm->fd = shm_open(shm->name, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
if(shm->fd == -1){
fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);
return false;
}
if (ftruncate(shm->fd , MEMORY_SIZE)){
fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno);
return false;
}
shm = mmap(NULL, MEMORY_SIZE,
PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm == MAP_FAILED) {
fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);
return false;
}
return true;
}
Do the same in the child...
Moreover, the code is incoherent as you pass shm
of type shared_memory_t
and you overwrite it with the mapped region?!? It should be:
[...]
shm->data = mmap(NULL, MEMORY_SIZE,
PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm->data == MAP_FAILED){
fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);
return false;
}
[...]
CodePudding user response:
First, why do you use O_CREAT
flag on child? It should open an existing area, not create a new one.
Secondly, have you made sure that your shared regions have same name and the name starts with /
and there is no name collisions?
Third, I don't think child should feed in the mode
parameter as they are not creating the area.
Also, you could have O_EXCL
flag in the parent just to make sure that you have created a new area and not just opened an old one.