In: Computer Science
You need to write and run C programs (as processes on your Linux machine), and monitor their behavior. Consider the following problem: A program is to be written to print all numbers between 1 and 1000 (inclusive) that are not (evenly) divisible by either 2 or 3. This problem is to be solved using three processes (P0, P1, P2) and two one-integer buffers (B0 and B1) as follows:  P0 is to generate the integers from 1 to 1000, and place them in B0 one at a time. After placing 1000 in the buffer, P0 places the sentinel 0 in the buffer, and terminates.  P1 is to read successive integers from B0. If a value is not divisible by 2, the value is placed in B1. If the value is positive and divisible by 2, it is ignored. If the value is 0, 0 is placed in B1, and P1 terminates.  P2 is to read successive integers from B1. If a value is not divisible by 3, it is printed. If the value is positive and divisible by 3, it is ignored. If the value is 0, P2 terminates. Write a program to implement P0, P1, and P2 as separate processes and B0 and B1 as separate pieces of shared memory {each the size of just one integer}. Use semaphores to coordinate processing. Access to B0 should be independent of access to B1; for example, P0 could be writing into B0 while either P1 was writing into B1 or P2 was reading.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
   // Creating the shared buffers and semaphores.
   int b0_shmId, b1_shmId;
   int s0_shmId, s1_shmId, s2_shmId, mutex_shmId;
   b0_shmId = shmget(IPC_PRIVATE, 1 * sizeof(int),
0777 | IPC_CREAT);
   b1_shmId = shmget(IPC_PRIVATE, 1 * sizeof(int), 0777 |
IPC_CREAT);
   s0_shmId = shmget(IPC_PRIVATE, 1 * sizeof(sem_t), 0777
| IPC_CREAT);
   s1_shmId = shmget(IPC_PRIVATE, 1 * sizeof(sem_t), 0777
| IPC_CREAT);
   s2_shmId = shmget(IPC_PRIVATE, 1 * sizeof(sem_t), 0777
| IPC_CREAT);
   mutex_shmId = shmget(IPC_PRIVATE, 1 * sizeof(sem_t),
0777 | IPC_CREAT);
   int *b0, *b1;
   sem_t *s0, *s1, *s2, *mutex;
   b0 = (int *) shmat(b0_shmId, 0, 0);
   b1 = (int *) shmat(b1_shmId, 0, 0);
   s0 = (sem_t *) shmat(s0_shmId, 0, 0);
   s1 = (sem_t *) shmat(s1_shmId, 0, 0);
   s2 = (sem_t *) shmat(s2_shmId, 0, 0);
   mutex = (sem_t *) shmat(mutex_shmId, 0, 0);
   // Initialising the semaphores.
   sem_init(s0, 0, 1);
   sem_init(s1, 0, 0);
   sem_init(s2, 0, 0);
   sem_init(mutex, 0, 1);
   // Creating the processes.
   pid_t p0, p1, p2;
   if((p0 = fork()) == 0)
   {
       int i;
       for(i=1; i<=1001; i++)
       {
          
sem_wait(s0);
          
           b0[0] = i;
          
sem_post(s1);
       }
       exit(1);
   }
   if((p1 = fork()) == 0)
   {
       int x = -1;
       while(x <= 1000)
       {
          
sem_wait(s1);
x = b0[0];
          
sem_post(s0);
           if(x % 2 !=
0)
           {
          
    sem_wait(mutex);
b1[0] = x;
          
    sem_post(mutex);
          
    sem_post(s2);
           }
       }
       exit(2);
   }
   if((p2 = fork()) == 0)
   {
       int x = -1;
       while(x <= 1000)
       {
          
sem_wait(s2);
          
sem_wait(mutex);
x = b1[0];
sem_post(mutex);
           if(x % 3 !=
0)
           {
          
    printf("%d\n", x);
           }
       }
       exit(3);
   }
   // Waiting for all three processes to finish.
   while(wait(NULL) != 0)
       ;
   // Detaching and destroying the shared
memories.
   shmdt(b0);
   shmdt(b1);
   shmdt(s0);
   shmdt(s1);
   shmdt(s2);
   shmdt(mutex);
   shmctl(b0_shmId, IPC_RMID, 0);
   shmctl(b1_shmId, IPC_RMID, 0);
   shmctl(s0_shmId, IPC_RMID, 0);
   shmctl(s1_shmId, IPC_RMID, 0);
   shmctl(s2_shmId, IPC_RMID, 0);
   shmctl(mutex_shmId, IPC_RMID, 0);
   return 0;
}