typedef __size_t | size_t |
typedef __pid_t | pid_t |
IMPORT_C int | semget | ( | key_t | key, |
int | nsems, | |||
int | semflg | |||
) |
SEM_R Read access for user. SEM_A Alter access for user. ( SEM_R>>3 ) Read access for group. ( SEM_A>>3 ) Alter access for group. ( SEM_R>>6 ) Read access for other. ( SEM_A>>6 ) Alter access for other. Note:The 'group' flags (SEM_R >> 3 and SEM_A >> 3) are ignored in Symbian OS.Based on the values of key and semflg, semget returns the identifier of a newly created or previously existing set of semaphores. The key is analogous to a filename: it provides a handle that names an IPC object. There are three ways to specify a key: IPC_PRIVATE may be specified, in which case a new IPC object will be created. An integer constant may be specified. If no IPC object corresponding to key is specified and the IPC_CREAT bit is set in semflg, a new one will be created. The ftok function may be used to generate a key from a pathname.
The mode of a newly created IPC object is determined by OR 'ing the following constants into the semflg argument: SEM_R Read access for user. SEM_A Alter access for user. ( SEM_R>>3 ) Read access for group. ( SEM_A>>3 ) Alter access for group. ( SEM_R>>6 ) Read access for other. ( SEM_A>>6 ) Alter access for other.
If a new set of semaphores is being created, nsems is used to indicate the number of semaphores the set should contain. Otherwise, nsems may be specified as 0.
#include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include <errno.h> #define SEM_SET_KEY 1000 #define NO_OF_SEMAPHORES 2 int main(void) { int sem_set_id; int perm; /* Create 2 semaphores in a set, with access only to the owner */ perm = SEM_R | SEM_A; if((sem_set_id = semget(SEM_SET_KEY, NO_OF_SEMAPHORES, IPC_CREAT | perm)) == -1) { printf("Semaphore creation failed with errno %d", errno); return -1; } return 0; }
Note :If the user need to create a semaphore which can be accessed from a different process, the 'other' flags (SEM_R >> 6 and SEM_A >> 6) must be added in parameter of shmflg. e.g The value of the variable perm used in the above example code should be as below perm = SEM_R | SEM_A | SEM_R >> 6 | SEM_A >> 6
IMPORT_C int | semop | ( | int | semid, |
struct sembuf * | sops, | |||
unsigned | nsops | |||
) |
The semop system call atomically performs the array of operations indicated by array on the semaphore set indicated by semid. The length of array is indicated by nops. Each operation is encoded in a struct sembuf , which is defined as follows:
struct sembuf { u_short sem_num; /* semaphore # */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */ };
For each element in array, sem_op and sem_flg determine an operation to be performed on semaphore number sem_num in the set. The values SEM_UNDO and IPC_NOWAIT may be ORed into the sem_flg member in order to modify the behavior of the given operation.
The operation performed depends as follows on the value of sem_op: When sem_op is positive and the process has alter permission, the semaphore's value is incremented by sem_op's value. If SEM_UNDO is specified, the semaphore's adjust on exit value is decremented by sem_op's value. A positive value for sem_op generally corresponds to a process releasing a resource associated with the semaphore. The behavior when sem_op is negative and the process has alter permission, depends on the current value of the semaphore: If the current value of the semaphore is greater than or equal to the absolute value of sem_op, then the value is decremented by the absolute value of sem_op. If SEM_UNDO is specified, the semaphore's adjust on exit value is incremented by the absolute value of sem_op. If the current value of the semaphore is less than the absolute value of sem_op, one of the following happens: If IPC_NOWAIT was specified, then semop returns immediately with a return value of EAGAIN. Otherwise, the calling process is put to sleep until one of the following conditions is satisfied: Some other process removes the semaphore with the IPC_RMID option of semctl . In this case, semop returns immediately with a return value of EIDRM. The semaphore's value is greater than or equal to the absolute value of sem_op. When this condition becomes true, the semaphore's value is decremented by the absolute value of sem_op, the semaphore's adjust on exit value is incremented by the absolute value of sem_op.
A negative value for sem_op generally means that a process is waiting for a resource to become available. When sem_op is zero and the process has read permission, one of the following will occur: If the current value of the semaphore is equal to zero then semop can return immediately. If IPC_NOWAIT was specified, then semop returns immediately with a return value of EAGAIN. Otherwise, the calling process is put to sleep until one of the following conditions is satisfied: Some other process removes the semaphore with the IPC_RMID option of semctl . In this case, semop returns immediately with a return value of EIDRM. The semaphore's value becomes zero.
For each semaphore a process has in use, an "adjust on exit" value is maintained, as alluded to earlier. When a process exits, either voluntarily or involuntarily, the adjust on exit value for each semaphore is added to the semaphore's value. This can be used to insure that a resource is released if a process terminates unexpectedly.
#include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> void File_Update(char* path, int val) { struct sembuf sem_op; FILE* fp; /* Wait on the semaphore till the value is non-negative. */ sem_op.sem_num = 0; sem_op.sem_op = -1; sem_op.sem_flg = 0; semop(sem_set_id, &sem;_op, 1); /* If we are here, then We have locked the semaphore, and are assured exclusive access to file. We can now manipulate the file */ fp = fopen(path, "w"); if (fp) { fprintf(fp, "%d", val); fclose(fp); } /* Increase the value of the semaphore by 1 so that others blocked on this semaphore get awakened. */ sem_op.sem_num = 0; sem_op.sem_op = 1; sem_op.sem_flg = 0; semop(sem_set_id, &sem;_op, 1); }
Bugs:
The semop system call may block waiting for memory even if IPC_NOWAIT was specified.
IMPORT_C int | semctl | ( | int | semid, |
int | semnum, | |||
int | cmd, | |||
... | ||||
) |
IPC_STAT Fetch the semaphore sets struct semid_ds , storing it in the memory pointed to by arg.buf . IPC_SET Changes the sem_perm.uid, sem_perm.gid, and sem_perm.mode members of the semaphore sets struct semid_ds to match those of the struct pointed to by arg.buf. IPC_RMID Immediately removes the semaphore set from the system. The calling processe'ss uid must equal the semaphore sets sem_perm.uid or sem_perm.cuid, GETVAL Return the value of semaphore number semnum. SETVAL Set the value of semaphore number semnum to arg.val. Outstanding adjust on exit values for this semaphore in any process are cleared. GETPID Return the pid of the last process to perform an operation on semaphore number semnum. GETNCNT Return the number of processes waiting for semaphore number semnum's value to become greater than its current value. GETZCNT Return the number of processes waiting for semaphore number semnum's value to become 0. GETALL Fetch the value of all of the semaphores in the set into the array pointed to by arg.array. SETALL Set the values of all of the semaphores in the set to the values in the array pointed to by arg.array. Outstanding adjust on exit values for all semaphores in this set, in any process are cleared.The semctl system call performs the operation indicated by cmd on the semaphore set indicated by semid. A fourth argument, a union semun arg , is required for certain values of cmd. For the commands that use the arg argument, union semun is defined as follows:
union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ u_short *array; /* array for GETALL & SETALL */ };
Commands are performed as follows:
IPC_STAT Fetch the semaphore sets struct semid_ds , storing it in the memory pointed to by arg.buf . IPC_SET Changes the sem_perm.uid, sem_perm.gid, and sem_perm.mode members of the semaphore sets struct semid_ds to match those of the struct pointed to by arg.buf. IPC_RMID Immediately removes the semaphore set from the system.
The calling process's uid must equal the semaphore sets sem_perm.uid or sem_perm.cuid, GETVAL Return the value of semaphore number semnum. SETVAL Set the value of semaphore number semnum to arg.val. Outstanding adjust on exit values for this semaphore in any process are cleared.
GETPID Return the pid of the last process to perform an operation on semaphore number semnum. GETNCNT Return the number of processes waiting for semaphore number semnum's value to become greater than its current value. GETZCNT Return the number of processes waiting for semaphore number semnum s value to become 0. GETALL Fetch the value of all of the semaphores in the set into the array pointed to by arg.array. SETALL Set the values of all of the semaphores in the set to the values in the array pointed to by arg.array. Outstanding adjust on exit values for all semaphores in this set, in any process are cleared.
struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ struct sem *sem_base; /* pointer to first semaphore in set */ u_short sem_nsems; /* number of sems in set */ time_t sem_otime; /* last operation time */ long sem_pad1; /* SVABI/386 says I need this here */ time_t sem_ctime; /* last change time */ /* Times measured in secs since */ /* 00:00:00 GMT, Jan. 1, 1970 */ long sem_pad2; /* SVABI/386 says I need this here */ long sem_pad3[4]; /* SVABI/386 says I need this here */ };
#include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include <errno.h> #define SEM_SET_KEY 1000 #define NO_OF_SEMAPHORES 2 int main(void) { int sem_set_id; union semun sem_val; /* Create 2 semaphores in a set, with access only to the owner */ if((sem_set_id = semget(SEM_SET_KEY, NO_OF_SEMAPHORES, IPC_CREAT | 0600)) == -1) { printf("Semaphore creation failed with errno %d", errno); return -1; } /* Initialize the first semaphore in our set to 1 */ sem_val.array = NULL; sem_val.buf = NULL; sem_val.val = 1; if(semctl(sem_set_id, 0, SETVAL, sem_val) == -1) { printf("Could not initialize first semaphore (errno %d)", errno); return -1; } /* Initialize the second semaphore in our set to 0 */ sem_val.val = 0; if(semctl(sem_set_id, 1, SETVAL, sem_val) == -1) { printf("Could not initialize second semaphore (errno %d)", errno); return -1; } /* Delete the semaphore set */ if(semctl(sem_set_id, NO_OF_SEMAPHORES, IPC_RMID) == -1) { printf("Could not delete semaphore set (errno %d)", errno); return -1; } return 0; }