Linux Mutex and synchronization application (iv): Mutual exclusion and synchronization of POSIX semaphores

Source: Internet
Author: User
Tags function prototype mutex posix semaphore

"Copyright Notice: respect for the original, reproduced please retain the source: blog.csdn.net/shallnet or .../gentleliu, the article is for learning communication only, do not use for commercial purposes"In the previous IPC shared memory said that the shared memory itself does not have a synchronization mechanism, if you want to achieve synchronization requires the use of semaphores and other means to achieve, now we say that the use of POSIX signal volume to achieve the POSIX multi-process shared memory synchronization.        In fact, semaphores can also be used between different threads in the same process. The semaphore is a variable containing a nonnegative integer, with two atomic operations, wait and post, or P and V operations, the P operation minus one, and the V Operation adds one to the signal volume.        If the semaphore is greater than the 0,p operation directly minus one, otherwise the 0,p operation will block the calling process (thread) until another process (thread) performs a V operation. Semaphores can be understood as the amount of a resource, which is allocated to achieve synchronization or mutual exclusion. When the value of the semaphore is 1 o'clock, mutual exclusion can be achieved, when the semaphore is a binary semaphore, if the value of the semaphore is greater than the moment, the process (thread) can be implemented concurrently. The difference between the semaphore and the mutex condition variable is that the mutex must be unlocked by the process (thread) that locks it, and that the semaphore P operation does not have to be performed by the process (thread) that performed the V operation; The mutex is similar to a two-value semaphore, is either locked or unlocked, and when signaled to the condition variable, If there are no threads waiting on the condition variable at this time, the signal will be lost, and the semaphore will not. Semaphores are primarily used for synchronization between, but can also be used between threads.        Mutexes and condition variables are primarily used for thread synchronization, but can also be used for inter-process synchronization. The POSIX semaphore is a sem_t variable type with a known semaphore and a nameless semaphore, and the nameless semaphore is used in the case of shared semaphore memory, which is better than the number of different threads in a process, or between parent and child processes, withthe kernel lasts, so we can manipulate them across multiple programs.
1. Function Sem_open Create a known semaphore or open a semaphore that already exists. The function prototypes are as follows:
       #include <fcntl.h>/* for o_* Constants */       #include <sys/stat.h>/* for Mode constants */       #include < ;semaphore.h>       sem_t *sem_open (const char *name, int oflag);       sem_t *sem_open (const char *name, int oflag, mode_t mode, unsigned int value);       Link With-pthread
The parameter name is the POSIX IPC name, and the parameter Oflag can be 0, o_creat, or O_creat | O_EXCL, if O_creat is specified, the third to fourth parameter needs to be specified. Mode is the specified permission bit, the value parameter specifies the semaphore initial value, the values of the binary semaphore are typically 1, and the value of the count semaphore is usually greater than 1. The function returns a pointer that executes the SEM_T data type, and an error returns sem_failed.
2. Function Sem_close Close the known semaphore.
       #include <semaphore.h>       int sem_close (sem_t *sem);       Link With-pthread.    
3. Function Sem_unlink Delete the named semaphore.
       #include <semaphore.h>       int sem_unlink (const char *name);       Link With-pthread.    
4. function sem_wait and function sem_trywait test the value of the semaphore, if the semaphore value is greater than 0, the function will reduce the value of the semaphore immediately return, if the value of the semaphore equals the 0,sem_wait function to start sleep, until the value of the semaphore is greater than 0, which is again minus the return immediately, The sem_trywait function does not sleep directly and returns a Eagain error. The function prototypes are:
       #include <semaphore.h>       int sem_wait (sem_t *sem);       int sem_trywait (sem_t *sem);       int sem_timedwait (sem_t *sem, const struct TIMESPEC *abs_timeout);       Link With-pthread.
5. The function Sem_post performs and sem_wait the opposite action. When a process (thread) finishes executing, it should call Sem_post, add one to the specified semaphore, and then wake up the process (thread) that is waiting for the semaphore to be 1. Function Prototypes:
       #include <semaphore.h>       int sem_post (sem_t *sem);       Link With-pthread.
6. Function Sem_getvalue Gets the current value of the specified semaphore, if the current semaphore is locked, returns 0, or is a negative number, the absolute value of the thread that waits for the unlock of that semaphore.
       #include <semaphore.h>       int sem_getvalue (sem_t *sem, int *sval);       Link With-pthread.
7. The nameless semaphore is initialized with Sem_init () and the function prototype is:
       #include <semaphore.h>       int sem_init (sem_t *sem, int pshared, unsigned int value);       Link With-pthread.
SEM is an unnamed semaphore address, value is the semaphore initial value, pshared Specifies whether the semaphore is shared between the threads of the process or between processes, if the value is 0, is shared between threads of the process, and if not 0 is shared between incoming and outgoing, Nameless semaphores are mainly used between processes or threads that have a common ancestor.
This section uses POSIX shared memory for communication between processes, and uses POSIX semaphores to achieve mutual exclusion and synchronization purposes.          First, let's take a look at using semaphores to implement mutually exclusive access to shared memory segments. Access to the front-line uses the following methodsto achieve mutually exclusive access to public memory:
          pthread_mutex_t     mutex = Pthread_mutex_initializer, ... pthread_mutex_lock (&mutex);//Locking .../*share Memory handle*/... pthread_mutex_unlock (&mutex);//unlock ....
Now we are using a similar approach:
sem_t *sem_mutex = NULL; Sln_mutex_shm_lock (Sem_mutex_file, Sem_mutex);//locking .../*share memory handle*/... Sln_mutex_shm_unlock (Sem_mutex);//unlock ...
which Sem_mutex_file is the name of the well-known semaphore required for the Sem_open function.
two of these lock unlock implementations are:
#define Sln_mutex_shm_lock (Shmfile, Sem_mutex) do {    Sem_mutex = Sem_open (shmfile, O_RDWR | O_creat, 0666, 1);    if (sem_failed = = Sem_mutex) {        printf ("Sem_open (%d):%s\n", __line__, Strerror (errno));    }    Sem_wait (Sem_mutex);} while (0) #define SLN_MUTEX_SHM_UNLOCK (Sem_mutex) does {sem_post (Sem_mutex);} while (0)
is to initialize a binary semaphore, its initial value is 1, and perform a wait operation, so that the value of the semaphore becomes 0, when other processes want to operate shared memory also need to perform a wait operation, but at this time the value of the semaphore is 0, so start waiting for the semaphore value into 1. When the current process has finished operating the shared memory, it begins to unlock, and the post operation adds a value of the semaphore to the other process, where wait can be returned. The following is an example of a mutually exclusive access to shared memory, and a POSIX shared memory implementation, see the previous IPC article series. Ser process:
int Nms_shm_get (char *shm_file, void **shm, int mem_len) {    int fd;    FD = Shm_open (shm_file, O_RDWR | O_creat, 0666);    if (FD < 0) {        printf ("Shm_pen <%s> failed:%s\n", Shm_file, Strerror (errno));        return-1;    }    Ftruncate (FD, Mem_len);    *SHM = Mmap (NULL, Mem_len, Prot_read | Prot_write, map_shared, FD, 0);    if (map_failed = = *shm) {        printf ("Mmap:%s\n", Strerror (errno));        return-1;    }    return 0;} int main (int argc, const char *argv[]) {    sem_t *sem_mutex = NULL;    char *str = NULL;    Sln_mutex_shm_lock (Sem_mutex_file, Sem_mutex); Locking    Nms_shm_get (Shm_file, (void * *) &str, Shm_max_len);//The following three lines mutually exclusive access to the shared memory    sleep (6);    snprintf (str, Shm_max_len, "POSIX semphore server!");    Sln_mutex_shm_unlock (Sem_mutex); Unlock    sleep (6);    Shm_unlink (shm_file);    return 0;}
Client process:
int main (int argc, const char *argv[]) {    sem_t *sem_mutex;    char *str = NULL;    Sln_mutex_shm_lock (Sem_mutex_file, Sem_mutex);    Nms_shm_get (Shm_file, (void * *) &str, shm_max_len);    printf ("Client Get:%s\n", str);    Sln_mutex_shm_unlock (Sem_mutex);    return 0;}
Start the service process first with a lock, create shared memory and manipulate it, and lock in sleep for 6 seconds to test whether the client process is waiting while the service process is not releasing the lock. The client process starts immediately after the service process starts, is in a wait state, and the client process obtains shared memory information when the service process is unlocked after 6 seconds. After 6 seconds, the service process deletes the shared memory and the client process fails to acquire shared memory again.
#./server & [1] 21690 #./client Client Get:posix Semphore server! #./clientshm_open <share_memory_file> failed:no Such file or directoryclient get: (null) [1]+ done./server
POSIX-known semaphores create semaphore files and shared memory files in the/dev/shm/directory:
# ls/dev/shm/  Sem.sem_mutex Share_memory_file #
When two processes share data, when a process writes data to the shared memory, it needs to notify the other process, which requires synchronization between the two processes, where we add synchronous operations to the above program on a mutually exclusive basis. Synchronization is also accomplished using POSIX semaphores. Server process:
int main (int argc, const char *argv[]) {sem_t *sem_mutex = NULL;    sem_t *sem_consumer = null, *sem_productor = NULL;    int semval;    char *sharememory = NULL; Sem_consumer = Sem_open (Sem_consumer_file, O_creat, 0666, 0); Initialize the semaphore Sem_consumer and set the initial value to 0 if (sem_failed = = Sem_consumer) {printf ("Sem_open <%s>:%s\n", Sem_consume        R_file, Strerror (errno));    return-1; } sem_productor = Sem_open (Sem_productor_file, O_creat, 0666, 0);//Initialize the semaphore Sem_productor and set the initial value to 0 if (sem_failed = = s        Em_productor) {printf ("Sem_open <%s>:%s\n", Sem_productor_file, Strerror (errno));    return-1; } for (;;)        {//The service process has been circulating processing client process requests Sem_getvalue (Sem_consumer, &semval);        printf ("%d waiting...\n", semval); if (sem_wait (Sem_consumer) < 0) {//If the Sem_consumer is 0, then block here, wait for the customer process post operation to make Sem_consumer greater than 0, here and the customer process synchronizes printf ("Sem            _wait:%s\n ", Strerror (errno));        return-1;        } printf ("Get request...\n"); SlN_mutex_shm_lock (Sem_mutex, Sem_mutex);//here begins mutually exclusive access to shared memory Nms_shm_get (Shm_file, (void * *) &sharememory, Shm_max_len)        ;        Sleep (6);        snprintf (Sharememory, Shm_max_len, "Hello, this is server ' s message!");        Sln_mutex_shm_unlock (Sem_mutex);    Sem_post (sem_productor);//Make the semaphore sem_productor plus one so that the blocked client process continues to execute printf ("Response request...\n");    } sem_close (Sem_consumer);    Sem_close (Sem_productor); return 0;}
Client process:

int main (int argc, const char *argv[]) {sem_t *sem_consumer = null, *sem_productor = NULL;    struct TIMESPEC timeout;    int ret;    char *sharememory = NULL;    Sem_t *sem_mutex; Sem_consumer = Sem_open (Sem_consumer_file, O_RDWR);//Gets the value of the semaphore Sem_consumer if (sem_failed = = Sem_consumer) {print        F ("Sem_open <%s>:%s\n", Sem_consumer_file, Strerror (errno));    return-1;        } sem_productor = Sem_open (Sem_productor_file, O_RDWR);//Gets the value of the semaphore sem_productor if (sem_failed = = Sem_productor) {        printf ("Sem_open <%s>:%s\n", Sem_productor_file, Strerror (errno));    return-1;    }//clear_exist_sem (Sem_productor);    Sln_mutex_shm_lock (Sem_mutex, Sem_mutex);//mutually exclusive access to shared memory Nms_shm_get (Shm_file, (void * *) &sharememory, Shm_max_len);    printf ("Sharememory:%s\n", sharememory);    Sln_mutex_shm_unlock (Sem_mutex);   Sem_post (Sem_consumer);///Semaphore Sem_consumer plus one, wake-up is a service process that blocks on that semaphore printf ("post...\n"); Sem_wait (sem_productor);//wait for the service process to respond/* Timeout. tv_sec = Time (NULL) + sem_timeout_sec;    timeout.tv_nsec = 0;    ret = sem_timedwait (Sem_productor, &timeout);    if (Ret < 0) {printf ("sem_timedwait:%s\n", Strerror (errno));    } */printf ("Get response...\n");    Sem_close (Sem_consumer);    Sem_close (Sem_productor); return 0;}
Sample source download for this section: Click the Open link

Linux Mutex and synchronization application (iv): Mutual exclusion and synchronization of POSIX semaphores

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.