Reputation: 2052
I am trying to copy integers from a parent process to a child process. Many questions of this nature are redirected towards using a different IPC method. That will not work for my case. The solution MUST use <sys/shm.h>
. This a part of a much larger program. I am initializing the size, pointer, pid, and memory name like so:
const int SIZE = 4*sizeof(int);
const char *name = "OS";
pid_t pid;
int shm_fd;
void *ptr;
I call fork
pid = fork();
The parent process consumes the integers like so
/* open the shared memory segment */
shm_fd = shm_open(name, O_RDONLY, 0666);
if (shm_fd == -1) {
fprintf(stderr,"open shared memory failed\n");
exit(-1);
}
/* now map the shared memory segment in the address space of the process */
ptr = mmap(0,SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
fprintf(stderr,"Map failed in parent\n");
exit(-1);
}
printf("Parent got mapped pointer: %p\n",ptr);
/* now read from the shared memory region */
printf("Parent has received:");
for(int i=0; i < SIZE/sizeof(int); i++)
printf(" %d ", *(int *)(ptr +i));
printf("\n");
/* remove the shared memory segment */
if (shm_unlink(name) == -1) {
fprintf(stderr,"Error removing %s\n",name);
exit(-1);
}
printf("parent done\n");
The child produces the integers like so
printf("In Child process. I am the producer: my pid=%d\n",getpid());
time_t t;
srand(time(&t));
int integers[SIZE];
printf("Generating random integers: ");
for(int i=0; i < SIZE/sizeof(int); i++){
int value = (rand() -49) %49;
integers[i] = value;
printf(" %d ", value);
}
printf("\n");
/* create the shared memory segment */
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
fprintf(stderr,"open shared memory failed\n");
exit(-1);
}
/* configure the size of the shared memory segment */
ftruncate(shm_fd,SIZE);
/* now map the shared memory segment in the address space of the process */
ptr = mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
fprintf(stderr,"Map failed in child\n");
return -1;
}
printf("Child got mapped pointer: %p\n",ptr);
void *ptr2=ptr;//back up the pointer for later use
/* Now write to the shared memory region. Increment the value of ptr after each write. */
memcpy(ptr, integers, sizeof(int));
memcpy(ptr+1,integers+1, sizeof(int));
memcpy(ptr+2,integers+2, sizeof(int));
memcpy(ptr+3,integers+3, sizeof(int));
printf("Child has sent: ");
for(int i=0; i < SIZE/sizeof(int); i++)
printf(" %d ", *(int *)(ptr2+i));
printf("\n");
This is a simple consumer-producer IPC program, but for some reason when I run the program my output is incorrect. For example, when I generate a set of integers I get
In Parent process. I am the consumer: my child pid=19187
In Child process. I am the producer: my pid=19187
Generating random integers: 8 10 37 48
Child got mapped pointer: 0x7f91c9c09000
Child has sent: 807733768 3155210 12325 48
Parent got mapped pointer: 0x7f91c9c09000
Parent has received: 807733768 3155210 12325 48
parent done
It looks like the last memory location is valid, but the first 3 are incorrect. I would very much appreciate any help with this problem.
Upvotes: 0
Views: 552
Reputation: 16925
I'm afraid there is a typo in pointer arithmetic.
*(int *)(ptr +i)
should be *((int *)ptr+i)
*(int *)(ptr2+i)
should be *((int *)ptr2+i)
It meant "Increment from i
bytes then consider as integer pointer"
instead of
"consider as integer pointer and increment from i
elements".
There is the same problem with memcpy(ptr+i,
that should be
memcpy((int *)ptr+i,
.
An advice: declare immediately ptr
with the correct type,
this will avoid plenty of dangerous casts.
By the way, I cannot see any synchronisation between the child
writing and the parent reading.
Adding an ugly sleep(1);
(don't do this in real life!) before
printf("Parent has received:");
seems to give something correct.
And by another way, depending on the process scheduling, the
shm_open(name, O_RDONLY, 0666);
call in the parent can fail if the
child has not yet called shm_open(name, O_CREAT | O_RDWR, 0666);
(the segment does not exist yet).
Upvotes: 1