Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <time.h>
#define ARR_SIZE 30
union semun {
int val;
struct semid_ds *buf;
ushort_t *array;
};
int random_num(int one, int two);
int main()
{
struct sembuf oper;
pid_t child_processes[3];
char buffer[ARR_SIZE];
int shmid, *shmptr;
pid_t child_pid;
int status;
int i, j, k;
char int_counter;
int child_process_status;
int semid;
int parent_pid;
int rand_n;
pid_t current_child;
/* returns the value of created segment */
shmid = shmget( IPC_PRIVATE, ARR_SIZE*sizeof(char), SHM_R | SHM_W );
if(shmid == -1) {
perror("Shared memory segment not created\n");
exit(1);
}
/* maps the shared segment onto process' address. Ret ptr to it */
(void *)shmptr = (char *)shmat(shmid, 0, 0);
if(!shmptr) {
perror("Did not attach mem to the process\n");
exit(1);
}
/* initialize shared memory to the array in this driver. */
int_counter = (char *)shmptr;
/* initialize the first index of the array to the counter... is zero*/
/* we always subtract 33 from that counter to */
/* get the real number */
(int) int_counter = 0;
/* set the beginning of the array of chars, which is int_counter +1 */
buffer[1] = (char *) ( (void *) shmptr+sizeof(char) );
/* semaphores segement */
if( ( semid = semget(IPC_PRIVATE, 1, 0777 ) ) < 0 ) {
perror("Semaphore allocation failed\n");
exit(1);
}
semctl( semid, 0, SETVAL, (union semun)1 );
/* forking */
for( i = 0; i < 3; i++ ) {
child_pid = fork();
switch( child_pid ) {
case -1:
perror("Fork failed\n");
exit(1);
break;
case 0: /* child part */
child_processes[i] = getpid();
printf("Child no %d of process id %ld just forked\n",
i+1, child_processes[i]);
switch(i) {
case 0: /* child no 1 */
oper.sem_num = 0;
oper.sem_op = -1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("Child1 semaphore down: OK - proceed to CS.\n");
/* ...........................CS............................................ */
for( j = 0; j < 50; j++) {
if((int)int_counter >= 29)
;
else if((int)int_counter < 29) {
int_counter = int_counter + sizeof(char);;
rand_n = random_num(26, 65);
printf("Random number for 1 is %d\n", rand_n);
fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", rand_n);
}
for(k = 0; k < (int)int_counter; k++) {
usleep(random_num(751, 8000));
fprintf(stdout, "%c ", shmptr + k*(sizeof(char))); /* + sizeof(char) */
}
}
/* ............................end of CS ................................... */
oper.sem_num = 0;
oper.sem_op = 1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("Child1 semaphore up: OK - child exit CS.\n");
break;
case 1: /* child no 2 */
oper.sem_num = 0;
oper.sem_op = -1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("Child2 semaphore down: OK - proceed to CS.\n");
/* ...........................CS.......................................... */
for( j = 0; j < 50; j++) {
if((int)int_counter >= 29)
;
else if((int)int_counter < 29) {
int_counter = int_counter + sizeof(char);
rand_n = random_num(26, 97);
printf("Random number for 2 is %d\n", rand_n);
fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", rand_n);
}
for(k = 0; k < (int)int_counter; k++) {
usleep(random_num(7501, 8000));
fprintf(stdout, "%c ", shmptr + k*(sizeof(char)));
}
}
/* ............................end of CS ................................... */
oper.sem_num = 0;
oper.sem_op = 1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("\nChild2 semaphore up: OK - child exit CS.\n");
break;
case 2: /* child no 3 */
oper.sem_num = 0;
oper.sem_op = -1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("Child3 semaphore down: OK - proceed to CS.\n");
/* ............................CS........................................ */
for( j = 0; j < 50; j++) {
if((int)int_counter <= 0)
; /* do nothing, can't remove a char if arr empty */
else if((int)int_counter > 0) {
fprintf((shmptr+sizeof(char)+(int)int_counter), "%c", NULL);
(int)int_counter -= (int)int_counter;
}
for(k = 0; k < (int)int_counter; k++) {
usleep(random_num(7501, 8000));
fprintf(stdout, "%c ", shmptr + k); /* buffer? */
}
}
/* ............................end of CS ................................... */
printf("Child3 semaphore up?\n");
oper.sem_num = 0;
oper.sem_op = 1;
oper.sem_flg = 0;
semop(semid, &oper, 1);
printf("Child3 semaphore up: OK - child exit CS.\n");
break;
default: printf("Error\n");
exit(1);
break;
}
break;
default: /* parent part */
break;
}
}
wait(&child_process_status);
printf("All child processes exited.\n");
printf("Removing shared memory segments and semaphores\n");
/* when mem not needed anymore, free it after all processes are gone ???????*/
*shmptr = 0; /* OR shmptr = (char *)shmat(shmid, 0, 0); ?????? */
/* detach memory */
shmdt( shmptr );
/* free it */
shmctl( shmid, IPC_RMID, shmptr );
/* remove the semaphore */
semctl( semid, 0, IPC_RMID );
printf("Parent %ld exits.\n", parent_pid);
return 0;
}
/* three cases here: uppercase is 26, 65, lowercase is 26, 97 */
/* and for usleep is e.g 51, 50 */
int random_num(int one, int two)
{
srand(time(NULL));
return( rand() % one + two);
}