/* SHARING MEMORY BETWEEN PROCESSES In this example, we show how two processes can share a common portion of the memory. Recall that when a process forks, the new child process has an identical copy of the variables of the parent process. After fork the parent and child can update their own copies of the variables in their own way, since they dont actually share the variable. Here we show how they can share memory, so that when one updates it, the other can see the change. */ #include #include #include /* This file is necessary for using shared memory constructs */ main() { int shmid; int *a, *b; int i; /* The operating system keeps track of the set of shared memory segments. In order to acquire shared memory, we must first request the shared memory from the OS using the shmget() system call. The second parameter specifies the number of bytes of memory requested. shmget() returns a shared memory identifier (SHMID) which is an integer. Refer to the online man pages for details on the other two parameters of shmget() */ shmid = shmget(IPC_PRIVATE, 2*sizeof(int), 0777|IPC_CREAT); /* We request an array of two integers */ /* After forking, the parent and child must "attach" the shared memory to its local data segment. This is done by the shmat() system call. shmat() takes the SHMID of the shared memory segment as input parameter and returns the address at which the segment has been attached. Thus shmat() returns a char pointer. */ if (fork() == 0) { /* Child Process */ /* shmat() returns a char pointer which is typecast here to int and the address is stored in the int pointer b. */ b = (int *) shmat(shmid, 0, 0); for( i=0; i< 10; i++) { sleep(1); printf("\t\t\t Child reads: %d,%d\n",b[0],b[1]); } } else { /* Parent Process */ /* shmat() returns a char pointer which is typecast here to int and the address is stored in the int pointer a. Thus the memory locations a[0] and a[1] of the parent are the same as the memory locations b[0] and b[1] of the parent, since the memory is shared. */ a = (int *) shmat(shmid, 0, 0); a[0] = 0; a[1] = 1; for( i=0; i< 10; i++) { sleep(1); a[0] = a[0] + a[1]; a[1] = a[0] + a[1]; printf("Parent writes: %d,%d\n",a[0],a[1]); } wait(); } } /* POINTS TO NOTE: In this case we find that the child reads all the values written by the parent. Also the child does not print the same values again. 1. Modify the sleep in the child process to sleep(2). What happens now? 2. Restore the sleep in the child process to sleep(1) and modify the sleep in the parent process to sleep(2). What happens now? Thus we see that when the writer is faster than the reader, then the reader may miss some of the values written into the shared memory. Similarly, when the reader is faster than the writer, then the reader may read the same values more than once. Perfect inter-process communication requires synchronization between the reader and the writer. Further note that "sleep" is not a synchronization construct. We use "sleep" to model some amount of computation which may exist in the process in a real world application. */