Linux IPC Practice (one)--system v Semaphore (1)

Source: Internet
Author: User
Tags semaphore

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)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.