There are two main elements to this. A simple structure, that we're going to change in the child (and see the change in the parent. And a static int that we're going to change in the parent, but not see change in the child.
Our program is going start by defining out structure and int.
struct msg { int i; char str[100]; } msg static int statInt = 1;Then create some shared memory to put a single instance of the structure in
key = getpid(); shmflg = IPC_CREAT | 0770; shmid = shmget(key, sizeof(msg), shmflgNext, we need to attach the shared memory block to our process and we'll write some stuff to it.
segadr = (struct msg*)shmat(shmid, 0, 0); segadr->i = 10; sprintf((char*)segadr->str,"A message from parent %d\n", getpid());Now we're going to call fork and depending on the return, we'll know if we are in the child or parent process.
if (fork() == 0) { /* Is child*/ } else { /* Is parent */ }The Child
Our child is now going to print the value of statInt and is also going to attach itself to the shared memory block above, then read from it.
printf("In Child: statInt %d\n", statInt); shmid = shmget(key, sizeof(msg), 0); chdadr = (struct msg *)shmat(shmid, 0, 0); fprintf(stdout, "This is child %d, gets %s\n", getpid(),chdadr->str)Now our child is going to write back a message
sprintf((char*)chdadr->str, "A message from child\n"); printf("In Child: We've written a message back\n");And then detach itself from shared memory
if (shmdt(chdadr) == -1) { perror("Child - detach"); }We're now going to sleep for 1 second, then look at statInt one last time, to see if it's changed.
sleep(1); printf("In Child: statInt %d\n", statInt);The Parent
Our parent (the block of code in the else) Is going to start by changing statInt to 2. The it's going to wait for the child to finish.
statInt = 2; printf("In Parent: We just changed statInt to %d\n", statInt); wait(&stat)wait() will block until the child dies, at this point we're going to read from the shared block, we don't need to attach again because our Pid hasn't changed.
fprintf(stdout, "In parent: segadr = %s\n", segadr->str);Then finally, like good citizens, we're going to mark our shared block to be destroyed.
cmd = IPC_RMID; if (shmctl(shmid, cmd, buf) == -1) { perror("Parent - remove"); }
That's the whole thing done. What you should see, (depending on timing), is the parent change statInt, but the child won't see the change. That's because fork() takes a snapshot of the state. So the child wont' see any changes in that state, except by using shared memory. You'll see it read from this and the parent will see the change made by the child. This is an example:
In parent: shmid = 40730676 shmget errno Success shmat errno Success In Parent: We just changed statInt to 2 In Child: statInt 1 In child: shmid = 40730676 In Child: shmat errno Success This is child 6751, gets A message from parent 6749 In Child: We've written a message back In Child: statInt 1 In parent: segadr = A message from child
You can see the full code listing on my public git repo This includes some debug printing, and some comment about what I had to change in the original to get it working.