semop

semaphore operations

copy
19
0
/* this code based on code found at http://www.minek.com/files/unix_examples/semab.html it was modified to show semaphore use to protect multiple processes accessing a critical section */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> /* The semaphore key is an arbitrary long integer which serves as an external identifier by which the semaphore is known to any program that wishes to use it. */ #define KEY (1492) int id; /* Number by which the semaphore is known within a program */ void initsem() { /* The next thing is an argument to the semctl() function. Semctl() does various things to the semaphore depending on which arguments are passed. We will use it to make sure that the value of the semaphore is initially 0. */ union semun { int val; struct semid_ds *buf; ushort * array; } argument; argument.val = 1; // mark semaphore available to take /* Create the semaphore with external key KEY if it doesn't already exists. Give permissions to the world. */ id = semget(KEY, 1, 0666 | IPC_CREAT); /* Always check system returns. */ if (id < 0) { fprintf(stderr, "Unable to obtain semaphore.\n"); exit(0); } /* What we actually get is an array of semaphores. The second argument to semget() was the array dimension - in our case 1. */ /* Set the value of the number 0 semaphore in semaphore array # id to the value 1. (available for taking) */ if (semctl(id, 0, SETVAL, argument) < 0) { fprintf(stderr, "Cannot set semaphore value.\n"); } else { fprintf(stderr, "Semaphore %d initialized.\n", KEY); } } int getsem(int pid) { struct sembuf operations[1]; /* An "array" of one operation to perform on the semaphore. */ int retval; /* Return value from semop() */ /* Do a semaphore P-operation. */ //printf("Process id is %d\n", pid); /* Set up the sembuf structure. */ /* Which semaphore in the semaphore array : */ operations[0].sem_num = 0; /* Which operation? Subtract 1 from semaphore value : */ operations[0].sem_op = -1; /* Set the flag so we will wait : */ operations[0].sem_flg = 0; /* So do the operation! */ retval = semop(id, operations, 1); if (retval != 0) { printf("semb: P-operation did not succeed for %d errno = %d.\n", pid, errno); } return retval; } int returnsem(int pid) { struct sembuf operations[1]; /* An "array" of one operation to perform on the semaphore. */ int retval; /* Return value from semop() */ /* Set up the sembuf structure. */ /* Which semaphore in the semaphore array : */ operations[0].sem_num = 0; /* Which operation? Add 1 to semaphore value : */ operations[0].sem_op = 1; /* Set the flag so we will wait : */ operations[0].sem_flg = 0; /*printf("return sem for pid %d\n", pid);*/ /* So do the operation! */ retval = semop(id, operations, 1); if (retval != 0) { printf("sema: V-operation did not succeed pid = %d.\n", pid); } return retval; } int main(int argc, char *argv[]) { int i, ret, pid; initsem(); /* set up semaphore first, child processes inherit it */ fork(); /* then there were 2 */ fork(); /* then there were 4 */ pid = getpid(); /* my pid for printing */ for (i = 0; i < 5; i++) { ret = getsem(pid); /* we only pass pid for printf (semid is global) */ if (ret != 0) continue; /* BEGIN critical section */ printf("%d working on %d\n", pid, i); usleep(2000); printf("%d done with %d\n", pid, i); /* END critical section */ ret = returnsem(pid); sleep(pid%10); /* randomize time to next iteration */ } printf(" exiting %d\n", pid); } this code based on code found at http://www.minek.com/files/unix_examples/semab.html it was modified to show semaphore use to protect multiple processes accessing a critical section

6 years, 4 months ago JohnJohnson 0 | details |