Signal is a programming architecture designed by E. W. Dijkstra at the end of 1960s. Dijkstra's model is related to railway operations: assuming a railway is a single line, only one train is allowed at a time. The signal will be used to synchronize the train passing through the track. Before a train enters a single track, it must wait for the signal light to change to the permitted status. After a train enters the track, the signal status changes to prevent other trains from entering the track. When the train leaves this track, it must change the Signal status again to allow other trains to enter the track. In computer versions, signals are expressed as simple integers. The thread waits for permission to continue running, and then sends a signal indicating that the thread has continued running by performing the P operation on the signal. The thread must wait until the signal value is positive before changing the value by subtracting 1 from the signal value. After this operation is completed, the thread executes the V operation, that is, the value is changed by adding 1 to the signal value. These operations must be performed in an atomic manner and cannot be divided into sub-operations. That is, other operations cannot be performed on signals between these sub-operations. In the P operation, the signal value must be positive before it is reduced to ensure that the generated signal value is not negative and 1 smaller than the value before it is reduced. In P and V Operations, operations must be performed without interference. If two V operations are performed on the same signal at the same time, the actual result is that the new value of the signal is 2 larger than the original value. For most people, just like remembering that Dijkstra is a Dutch, remembering the meaning of P and V is not important. However, from an academic point of view, P represents prolagen, a term evolved from proberen te verlagen, which means trying to reduce it. V represents verhogen, which means adding. Dijkstra's technical description EWD74 describes these meanings. Sem_wait (3RT) and sem_post (3RT) correspond to the P and V Operations of Dijkstra respectively. Sem_trywait (3RT) is a condition form for P operations. If the call thread cannot reduce the signal value without waiting, the call immediately returns a non-zero value. There are two basic signals: Binary and counting semaphores. The binary signal value can only be 0 or 1, and the count semaphores can be
 
It can be any non-negative value. The binary signal is logically equivalent to a mutex lock.
 
However, although not mandatory, the mutex lock should be unlocked only by the thread holding the lock. Because the concept of "the thread holding the signal" does not exist, any thread can perform the V or sem_post (3RT) operation. The function of counting semaphores and mutex lock is almost as powerful as that of conditional variables. In many cases, the Code implemented using the Count semaphore is simpler than the Code implemented using the conditional variable. However, when the mutex lock is used as a condition variable, an implicit bracket exists. The brackets clearly indicate the protected part of the program. This is not necessary for signals. You can use go to in concurrent programming to call them. The signal function is powerful, but it is easy to use in unstructured and uncertain ways.
 
1. Named semaphores and unnamed semaphores
 
POSIX signals can be untitled or named. The unnamed signal is allocated in the process memory and initialized. Unnamed signals may be available to multiple processes, depending on the signal distribution and initialization methods. Unnamed signals can be private signals inherited by fork (), or they can be protected by the access protection function of conventional files used to allocate and map these signals. The naming signal is similar to the signal shared by the process. The difference is that the naming signal is referenced by the path name rather than the pshared value. The naming signal can be shared by multiple processes. The naming signal has the main user ID, group ID, and protection mode. For the open, retrieve, close, and remove naming signals, you can use the following functions: sem_open, sem_getvalue, sem_close, and sem_unlink. By using sem_open, you can create a naming signal whose name is defined in the file system namespace.
 
2 count semaphores Overview
 
In terms of concept, semaphores are a non-negative integer count. Semaphores are usually used to coordinate access to resources. The signal count is initialized to the number of available resources. Then, the thread increases the count when the resource is increased, and reduces the count when the resource is deleted. These operations are performed in an atomic manner. If the signal count is zero, no resources are available. When the count is zero, the thread that attempts to reduce the signal will be blocked until the count is greater than zero.
 
Because the signal does not need to be acquired and released by the same thread, the signal can be used for asynchronous event notifications, such as in signal processing programs. At the same time, because the signal contains the status, it can be used asynchronously, instead of having to obtain mutex as the conditional variable does. However, the signal efficiency is not as high as the mutex lock. By default, if multiple threads are waiting for a signal, the order of unblocking is uncertain. The signal must be initialized before use, but the signal has no attribute.
 
3. initialize semaphores
 
Use sem_init (3RT) to initialize the unnamed signal variable indicated by sem as value.
 
Sem_init syntax
 
Int sem_init (sem_t * sem, int pshared, unsigned int value );
 
# Include <semaphore. h>
 
Sem_t sem;
 
Int pshared;
 
Int ret;
 
Int value;
 
/* Initialize a private semaphore */
 
Pshared = 0;
 
Value = 1;
 
Ret = sem_init (& sem, pshared, value );
 
If the pshared value is zero, the signal cannot be shared between processes. If the pshared value is not zero, the signal can be shared among processes.
 
Note:
 
1) multiple threads must not initialize the same signal.
 
2) Do not reinitialize the signal being used by other threads.