I want to do the following:
Parent process creates a child process. Then the child process reads n int's from the user and store them in a shared memory. The parent process then displays them.
I reached the following:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSIZE 27
int main() {
int shmid;
int *shm;
int *n;
if(fork() == 0) {
shmid = shmget(2009, SHMSIZE, 0);
shm = shmat(shmid, 0, 0);
n = shm;
int i;
for(i=0; i<5; i++) {
printf("Enter number<%i>: ", i);
scanf("%d", n++);
}
printf ("Child wrote <%d>\n",shm);
shmdt(shm);
}
else {
wait();
int *s;
shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
shm = shmat(shmid, 0, 0);
s = shm;
wait(NULL);
printf ("Parent reads <%d>\n",shm) ;
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
}
return 0;
}
And the output is just this line:
Enter number<1>:
And if I entered a number, let's say 25, it outputs this:
Parent reads <r>
r: random -ve number changes every time I execute the code
It never went through the child process code ! Am I doing this in a wrong way ?
Ok, better collect in an answer instead...
There are several problems with you program. If you enable warnings when building (I use
-Wall -Wextra
) a lot of them will be quite evident.The first two problems I already mentioned in my comments, but I explain them here:
wait()
. There is nowait
function in C or POSIX that takes no argument.scanf
call, you are calling it with*++
, where*n
takes the value of the memory pointed to byn
which most likely can result in a crash. Remove the asterisk.n
) and as a string. You cant really do both, pick one or the other.Edit I came up with this instead, which seems to work for me. I added comments on the things I changed.
Do note that point 5 in the list above have not been resolved.
One problem is that the child process is attempting to use get the shared memory before it has been created by the parent. The parent has a
wait()
call before creating the shared memory, so it won't exist when the client tries to retrieve the id. Even if the wait() call is moved, it may not work because there is a race condition. The call toshmget
may need to precede thefork
call (or use some synchronization to make sure it actually exists before retrieving it in the child process).And (as others have already pointed out), the child is attempting to write integers to the memory while the reading (printing of it) tries to treat it as a character string.
Your description seems to not be correct since there is no code that outputs "Parent Wrote <>".
You are reading numbers and storing them as int in *n++, but then you are appending a '\n' character to the n-int array and you are treating shm as a string?
It seems to me that in your child you are creating a shared memory, writing to it and then closing (discarding) the shared memory. Then your second part opens a new shared memory with the same segment, but yet it is a new shared memory. Normally one process creates a shared memory, then the second opens it and when the last process closes the shared memory, then it is freed by the OS.
My problem was so stupid. I need to provide the Child process with the ability to write into the SHM. This line in the if-block :
Will become like this:
Thanks to you all and especially to @JoachimPileborg :)