Semaphore API
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>int semget (key_t key, int nsems, int SEMFLG); int semctl (int semid, int semnum, int cmd, ...); int semop (int semid, struct sembuf *sops, unsigned nsops);
Semget
int Semget (key_t key, int nsems, int semflg);
Create/access a semaphore set
Parameters:
Key: Signal set key (key)
Nsems: number of signals in the signal set
SEMFLG: Consists of nine permission flags, which are used in the same way as when creating files using the mode pattern flag
Return value: Successfully returns a non-negative integer, which is the identifier of the signal set ; failure returns-1;
Each semaphore in the semaphore set created at this time will have a default value of 0, if you need to change the value, you need to call the SEMCTL function, change the initial value;
/** Example 1: Encapsulates a function that creates a semaphore set that contains 1 semaphores; the permission is 0666**/int sem_create (key_t key) { int semid = Semget (key, 1, ipc_creat| ipc_excl|0666); if (Semid = =-1) err_exit ("Sem_create error"); return semid;}
/** Example 2: Open a semaphore set Nsems (semaphore number) can be filled with 0,SEMFLG (semaphore permission) can also be filled in 0, indicating that the default permissions to open **/int Sem_open (key_t key) { int semid = Semget ( Key, 0, 0); if (Semid = =-1) err_exit ("Sem_open error"); return semid;}
Shmctl
int semctl (int semid, int semnum, int cmd, ...);
Control semaphore Set
Parameters
SEMID: Signal set identification code returned by Semget
semnum: sequence number of signals in the signal set (note: Starting from 0 The semaphores in a set is numbered starting at 0.)
cmd: The action to be taken (common values are as follows)
If the function requires a fourth argument (sometimes without the fourth argument, depending on the value of the CMD), the following Union must be defined in the program:
Union semun{ int val; /* Value for Setval */ struct semid_ds *buf; /* Buffer for Ipc_stat, Ipc_set */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for Ipc_info (linux-specific) */};
The struct Semid_ds:linux core is a data structure maintained by the System V Semaphore struct semid_ds{ struct ipc_perm sem_perm; /* Ownership and Permissions */ time_t sem_otime;/* Last Semop time */ time_t sem_ctime;/* Last Chan GE Time * * * unsigned long sem_nsems; */* No. of semaphores in Set */};
/** Example 1: Set the value of the first semaphore in the semaphore set Semid to Setval Note: The Semun consortium needs to be given (copied from man-page) **/union semun{int val; /* Value for Setval */struct SEMID_DS *buf; /* Buffer for Ipc_stat, Ipc_set */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for Ipc_info (linux-specific) */};int sem_setval (int semid, int value) {Union Semun su; Su.val = value; if (Semctl (semid, 0, setval, su) = =-1) err_exit ("Sem_setval error"); return 0;}
/** Example 2: Gets the value associated with the first signal in the semaphore set (getval) Note: The fourth parameter can be blank at this point, and the value associated with the semaphore can be returned by the Semctl return value (the value of Semval.) **/int sem_getval (int semid) {int value = Semctl (semid, 0, Getval); if (value = =-1) err_exit ("Sem_getval error"); return value; return 0;}
/** Example 3: Delete a semaphore set (note that the entire collection is deleted) Ipc_rmid Immediately Remove (delete now) The semaphore set, awakening all processes blocked in Semop (2 ) calls on the set (with a error return and errno set to EIDRM) [then wakes up all processes blocking on the semaphore]. The argument semnum is ignored[ignores the second parameter].**/int sem_delete (int semid) {if (Semctl (semid, 0, ipc_rmid) = =-1) E Rr_exit ("Sem_delete error"); return 0;} Test code int Main (int argc,char *argv[]) {int semid = sem_create (0x1234);//Create a Semaphore set Sem_setval (Semid, 500);//Set Value Cou T << sem_getval (semid) << endl;//Get the value sleep (10); Sem_delete (Semid);//Delete the collection}
/** Example 4: Get/Set Semaphore permissions Note: Be sure to set the struct semid_ds struct to specify which field to use Semun **/int sem_getmode (int semid) { Union semun su; Note: The following two lines of statements must be set. (Tell the kernel which field to use for the Semun) struct semid_ds sd; Su.buf = &sd; if (semctl (semid, 0, ipc_stat, su) = =-1) err_exit ("Sem_getmode error"); printf ("Current permissions is:%o\n", su.buf->sem_perm.mode); return 0;} int sem_setmode (int semid, char *mode) { Union semun su; Note: The following two lines of statements must be set. (Tell the kernel which field to use for the Semun) struct semid_ds sd; Su.buf = &sd; sscanf (Mode, "%o", (unsigned int *) &su.buf->sem_perm.mode); if (Semctl (semid, 0, ipc_set, su) = =-1) err_exit ("Sem_setmode error"); return 0;}
Semop
int semop (int semid, struct sembuf *sops, unsigned nsops);
used to manipulate a semaphore set for p,v operation
Parameters:
Semid: Is the identifier of the semaphore, which is the return value of the Semget function
SOPs: A pointer to an array of structures (if there is only one semaphore in the semaphore set, only one struct)
Nsops: The number of semaphores set (if nsops>1, you need to set the sops[second parameter] to an array of structures, referring to the example code given by Man-page), the third parameter actually indicates the number of objects represented by the second parameter;
SEMBUF structure struct sembuf{ unsigned short sem_num; /*semaphore Number: Semaphore (starting from 0) */short sem_op; /* Semaphore operation (+1, 0,-1) */short sem_flg; /* Operation flags: Commonly used values are Sem_undo (explained below) */};
SEM_OP is the signal amount of a PV operation added and minus the value, generally only use two values, one is "1", that is, p operation, waiting for the semaphore to become available, and the other is "+1", that is, v operation, The emitted semaphore has become available, and the parameter can be equal to 0, indicating that the process will block until the semaphore value equals 0;
SEM_FLG has three values: Sem_undo(at the end of the process, the process is restored to the semaphore operation [i.e.: Cancel the process for all semaphores operation], recommended), ipc_nowait (non-blocking) or 0 (default action, not undo operation);
/** Example: p,v operation Encapsulation * * You can set the third parameter of the SEMBUF to ipc_nowait/0 to see the change in the state of the program **/int sem_p (int semid) { struct sembuf SOPs = {0,-1, SEM _undo}; if (Semop (Semid, &sops, 1) = =-1) err_exit ("sem_p error"); return 0;} int sem_v (int semid) { struct sembuf SOPs = {0, +1, sem_undo}; if (Semop (Semid, &sops, 1) = =-1) err_exit ("Sem_v error"); return 0;}
/** signal Volume Application Example: After the compilation is complete, run directly./semtool, the program will print the use of the tool; The following function calls are only minor changes to the encapsulated functions above, and it is not difficult to understand them; **///semtool.cpp#include " Usage.h "int main (int argc,char *argv[]) {int opt = getopt (argc, argv," CDPVS:GFM: "); if (opt = = '? ') Exit (Exit_failure); else if (opt = =-1) {usage (); Exit (Exit_failure); } key_t key = Ftok (".", ' s '); int semid; Switch (opt) {case ' C ': sem_create (key); Break Case ' d ': Semid = Sem_open (key); Sem_delete (Semid); Break Case ' P ': Semid = Sem_open (key); Sem_p (Semid); Sem_getval (Semid); Break Case ' V ': Semid = Sem_open (key); Sem_v (Semid); Sem_getval (Semid); Break Case ' s ': Semid = Sem_open (key); Sem_setval (Semid, Atoi (Optarg)); Sem_getval (Semid); Break Case ' g ': Semid = Sem_open (key); Sem_getval (Semid); Break Case ' f ': Semid = Sem_open (key); Sem_getmode (SEMID); Break Case ' m ': Semid = Sem_open (key); Sem_setmode (Semid, argv[2]); Sem_getmode (Semid); Break Default:break; } return 0;}
Usage.h#ifndef usage_h_included#define usage_h_included#include <iostream> #include <string> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string.h> #include <sys/types.h > #include <sys/stat.h> #include <sys/ipc.h> #include <sys/wait.h> #include <sys/time.h># Include <sys/msg.h> #include <sys/shm.h> #include <sys/mman.h> #include <sys/sem.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #include <grp.h> #include <pwd.h># Include <time.h> #include <errno.h> #include <mqueue.h>using namespace std;inline void Err_quit (std:: String message), inline void Err_exit (std::string message), void usage () {cerr << "usage:" << Endl; Cerr << "./semtool-c #create" << Endl; Cerr << "./semtool-d #delte" << Endl; Cerr << "./semtool-p #signal" << Endl; Cerr << "./seMtool-v #wait "<< Endl; Cerr << "./semtool-s <val> #set-value" << Endl; Cerr << "./semtool-g #get-value" << Endl; Cerr << "./semtool-f #print-mode" << Endl; Cerr << "./semtool-m <mode> #set-mode" << Endl;} int sem_create (key_t key) {int semid = Semget (key, 1, ipc_creat| ipc_excl|0666); if (Semid = =-1) err_exit ("Sem_create error"); return semid;} int Sem_open (key_t key) {int semid = Semget (key, 0, 0); if (Semid = =-1) err_exit ("Sem_open error"); return semid;} Union semun{int Val; /* Value for Setval */struct SEMID_DS *buf; /* Buffer for Ipc_stat, Ipc_set */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for Ipc_info (linux-specific) */};int sem_getmode (int semid) {Union Semun su; Note: The following two lines of statements must be set. (Tell the kernel which field to use for the Semun) struct Semid_ds sd; Su.buf = &sd;if (Semctl (semid, 0, ipc_stat, su) = =-1) err_exit ("Sem_getmode error"); printf ("Current permissions is:%o\n", Su.buf->sem_perm.mode); return 0;} int sem_setmode (int semid, char *mode) {Union Semun su; Note: The following two lines of statements must be set. (Tell the kernel which field to use for the Semun) struct Semid_ds sd; Su.buf = &sd; SSCANF (Mode, "%o", (unsigned int *) &su.buf->sem_perm.mode); if (Semctl (semid, 0, ipc_set, su) = =-1) err_exit ("Sem_setmode error"); return 0;} int sem_getval (int semid) {int value = Semctl (semid, 0, Getval); if (value = =-1) err_exit ("Sem_getval error"); cout << "Current value:" << value << Endl; return value;} int sem_setval (int semid, int value) {Union Semun su; Su.val = value; if (Semctl (semid, 0, setval, su) = =-1) err_exit ("Sem_setval error"); return 0;} int sem_delete (int semid) {if (Semctl (semid, 0, ipc_rmid) = =-1) err_exit ("Sem_delete error"); return 0;} In order to be able to print the amount of signalContinue to change, so sem_flg we do not use sem_undo//but we recommend using Sem_undoint sem_p (int semid) {struct Sembuf SOPs = {0,-1, 0}; if (Semop (Semid, &sops, 1) = =-1) err_exit ("Sem_p error"); return 0;} int sem_v (int semid) {struct Sembuf SOPs = {0, +1, 0}; if (Semop (Semid, &sops, 1) = =-1) err_exit ("Sem_v error"); return 0;} inline void Err_quit (std::string message) {std::cerr << message << Std::endl; Exit (exit_failure);} inline void Err_exit (std::string message) {perror (Message.c_str ()); Exit (exit_failure);} #endif//usage_h_included
Attached-makefile
. Phony:clean all CC = g++ Cppflags =-wall-gbin = Semtoolsources = $ (bin.=.cpp) All: $ (BIN)%.O:%.c $ (CC) $ (cppflags) -C $^-o [email protected]main:main.o $ (CC) $ (cppflags) $^-lrt-o [email protected]clean: -rm-rf $ (bin) *.o bin /Obj/core
Linux IPC Practice (one)--system v Semaphore (1)