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;
}