#include #include #include #include #include #include #include #include union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #define SEGSIZE 10 //void usage(); //void writeshm(int shmid, char *segptr, char *text); //void changemode(int shmid, char *mode); //void removeshm(int shmid); //void readshm(int shmid, char *segptr); int semid; int *segptr; main(int argc, char *argv[]) { key_t key, keysem; pid_t pid; int shmid; int id, cntr; union semun semopts; // if(argc == 1) // usage(); /* Create unique key via call to ftok() */ key = ftok(".", 'M'); keysem = ftok(".", 'S'); /* Open the shared memory segment - create if necessary */ if((shmid = shmget(key, (SEGSIZE*4)+1, IPC_CREAT|IPC_EXCL|0666)) == -1) { printf("Shared memory segment exists - opening as client\n"); /* Segment probably already exists - try as a client */ if((shmid = shmget(key, (SEGSIZE*4)+1, 0)) == -1) { perror("shmget"); exit(1); } } else { printf("Creating new shared memory segment\n"); } /* Attach (map) the shared memory segment into the current process */ if((segptr = (int *)shmat(shmid, 0, 0)) == (int *)-1) { perror("shmat"); exit(1); } //Creating the semaphore array printf("Attempting to create new semaphore set with 5 members\n"); if((semid = semget(key, 5, IPC_CREAT|IPC_EXCL|0666)) == -1) { fprintf(stderr, "Semaphore set already exists!\n"); exit(1); } semopts.val = SEGSIZE; semctl(semid, 0, SETVAL, semopts); semopts.val = 0; semctl(semid, 1, SETVAL, semopts); semopts.val = 1; semctl(semid, 2, SETVAL, semopts); semopts.val = 0; semctl(semid, 3, SETVAL, semopts); semopts.val = 0; semctl(semid, 4, SETVAL, semopts); //Creating the three consumer processes id = 0; for(cntr = 0; cntr < 3; cntr++) { pid = fork(); if(pid < 0) { perror("Process creation failed"); exit(1); } if(pid == 0) { //This is a son consumer(id); cntr = 3; } else { //This is the father id++; } } //We enter the producer's code producer(); } unsigned short get_member_count(int sid) { union semun semopts; struct semid_ds mysemds; semopts.buf = &mysemds; /* Return number of members in the semaphore set */ return(semopts.buf->sem_nsems); } void locksem(int sid, int member) { struct sembuf sem_lock={ 0, -1, 0}; if( member<0 || member>4) //(get_member_count(sid)-1)) { fprintf(stderr, "semaphore member %d out of range\n", member); return; } sem_lock.sem_num = member; if((semop(sid, &sem_lock, 1)) == -1) { fprintf(stderr, "Wait failed\n"); exit(1); } // else // printf("Semaphore resources decremented by one (locked)\n"); } void unlocksem(int sid, int member) { struct sembuf sem_unlock={ member, 1, 0}; int semval; if( member<0 || member>4) // (get_member_count(sid)-1)) { fprintf(stderr, "semaphore member %d out of range\n", member); return; } sem_unlock.sem_num = member; /* Attempt to unlock the semaphore set */ if((semop(sid, &sem_unlock, 1)) == -1) { fprintf(stderr, "Signal failed\n"); exit(1); } // else // printf("Semaphore resources incremented by one (unlocked)\n"); } writeshm(int index, int value) { //strcpy(segptr, text); segptr[index] = value; if(index > 0) printf("(Producer) Wrote %d\n", value); fflush(stdout); } int readshm(int id, int index) { if(index > 0) printf("(Consumer %d) Read %d\n", (id+1), segptr[index]); return segptr[index]; } removeshm(int shmid) { shmctl(shmid, IPC_RMID, 0); printf("Shared memory segment marked for deletion\n"); } producer() { int out = 0; int value = 0; while(1 == 1) //While true { locksem(semid,0); writeshm(out+1,value); value++; out = (out+1)%SEGSIZE; unlocksem(semid,1); } } consumer(int id) { int value; int in; while(1 == 1) //While true { locksem(semid,2+id); locksem(semid,1); in = readshm(id,0); value = readshm(id,in+1); in = (in+1)%SEGSIZE; writeshm(0,in); unlocksem(semid,0); unlocksem(semid,2+((id+1)%3)); } }