1. semaphores basic terms
In modern computer systems, multiple processes can be executed concurrently, and there must be problems of resource sharing and mutual cooperation between processes.
Synchronization mainly involves the mutual collaboration between multiple processes to complete tasks, which is a direct issue of inter-process constraints. Mutual Exclusion is mainly used for the use of limited resources when multiple processes are used.
Semaphore is an effective tool for inter-process synchronization and mutex proposed by Dijkstra in 1965. Semaphores are usually used as an integer variable in the operating system. These semaphores are called integer semaphores. Physical significance of semaphores s:
S> = 0 indicates the number of available resources;
S <0 its absolute value indicates the number of processes in the blocked queue waiting for this resource;
The two methods of semaphore operation are PV, P operation is S = S-1; indicates applying for a resource, V operation is S = S + 1; indicates releasing a resource. The addition and subtraction of Integers (1) is performed in one command, while the hardware can ensure that the interruption only occurs between commands. Therefore, the PV operation is not interrupted and the execution result is not disturbed.
P
{
S = S-1;
If (S <0)
Wait (s); -------- the current process enters the waiting queue
}
V
{
S = S + 1;
If (S <= 0)
Resume (s); ---------- wake up a process in the waiting queue
}
2. Mutual Exclusion using semaphores
The initial semaphores mutex = 1. When a process enters the critical section, the P operation is performed, and the V operation is performed when the process exits the critical section.
P (mutex)
Code in the critical section; (operations on mutually exclusive resources)
V (mutex)
3. Use semaphores for synchronization
In this case, we can think of a signal as a message. If S = 0, the message is not generated. If S> 0, the message is generated. For example:
(1) producer and consumer issues in a single buffer zone.
The producer process P1 continuously produces the product and sends it to the buffer. The consumer process P2 continuously extracts the product consumption from the buffer. To synchronize processes P1 and P2, you need to set a semaphore S1 and initialize it to 1, indicating that the buffer zone is empty and the product can be placed in the buffer zone; you also need to set another semaphore S2. The initial value is 0, indicating that there is no product in the buffer zone and consumption can be extracted.
P1: generate a product ---> P (S1) to test whether the buffer zone is null -----> the product sends the buffer zone ----> V (S2) is configured with the product ----> repeated
P2: P (S2) test whether a product exists -----> retrieve the product from the buffer -------> V (S1) set the buffer to null -------> consume ---> duplicate
(2) Multi-buffer synchronization
There is a producer and a consumer. The buffer zone can store N items. Producers continuously produce products and consumers continuously consume products.
Set three semaphores, S, S1, and S2. S indicates that the initial value of a mutex semaphore is 1, and the buffer zone resources are mutex controlled. S1 indicates whether items can be placed in the buffer zone. The initial value is N, and S2 indicates whether there are items in the buffer zone, the initial value is 0. The synchronization process is as follows:
P1: produce a product -----> P (S1) ---> P (S) ---> product delivery buffer ---> V (s) ----> V (S2)
P2: P (S2) ------> P (S) ---> fetch a product from the buffer -----> V (s) -----> V (S1) -----> consume
The source code for using semaphores on Windows and UNIX platforms is attached:
As for what is semaphore, there is a lot of relevant information on the Internet. I will not repeat it once I search for it. Just paste the sample program about using semaphores as a note. It would be better if it could help you a little bit. The Windows platform code comes from msdn, And the UNIX platform code comes from Google. </P> <p> Part 1-example program of semaphore on Windows platform <br/> # include <stdio. h> <br/> # include <windows. h> </P> <p> # define max_sem_count 10 <br/> # define threadcount 12 </P> <p> handle ghsemaphore; </P> <p> DWORD winapi threadproc (lpvoid); </P> <p> void main (INT argc, char * argv []) <br/>{< br/> handle athread [threadcount]; <br/> DWORD threadid; <br/> int I; </P> <p> // create a semaphore with initial and Max counts of Max _ Sem_count </P> <p> ghsemaphore = createsemaphore (<br/> null, // default security attributes-l1_maphoreattributes is the secure attribute of semaphores <br/> max_sem_count, // initial count-linitialcount is the initial semaphore <br/> max_sem_count, // maximum count-lmaximumcount is to allow the semaphore to be increased to the maximum value <br/> null ); // unnamed semaphore-lpname is the semaphore name </P> <p> If (ghsemaphore = NULL) <br/>{< br/> printf ("createsemaphore error: % d/N ", getlasterror (); <Br/> return; <br/>}</P> <p> // create worker threads </P> <p> for (I = 0; I <threadcount; I ++) <br/>{< br/> athread [I] = createthread (<br/> null, // default security attributes <br/> 0, // default stack size <br/> (lpthread_start_routine) threadproc, <br/> null, // no thread function arguments <br/> 0, // default creation flags <br/> & threadid ); // receive thread identifier </P> <p> If (athread [I] = NULL) <br/>{< br/> printf ("createthread error: % d/N", getlasterror (); <br/> return; <br/>}</P> <p> // wait for all threads to terminate </P> <p> waitformultipleobjects (threadcount, athread, true, infinite); </P> <p> // close thread and semaphore handles </P> <p> for (I = 0; I <threadcount; I ++) <br/> closehandle (athread [I]); </P> <p> closehandle (ghsemaphore); <br/>}</P> <p> DWORD winapi thre Adproc (lpvoid lpparam) <br/>{< br/> DWORD dwwaitresult; <br/> bool bcontinue = true; </P> <p> while (bcontinue) <br/> {<br/> // try to enter the semaphore gate. <br/> dwwaitresult = waitforsingleobject (<br/> ghsemaphore, // handle to semaphore <br/> 0l ); // zero-second time-out interval </P> <p> switch (dwwaitresult) <br/>{< br/> // The semaphore object was signaled. <br/> case wait_object_0: <br/> // Todo: perform task <br/> printf ("thread % d: Wait succeeded/N", getcurrentthreadid ()); </P> <p> // ensure a thread performs only once <br/> bcontinue = false; </P> <p> // simulate thread spending time on task <br/> sleep (5 ); </P> <p> // release the semaphore when task is finished </P> <p> If (! Releasesemaphore (<br/> ghsemaphore, // handle to semaphore-hsemaphore is the semaphore handle to be added <br/> 1, // increase count by one-lreleasecount is the increase count <br/> null )) // not interested in previous count-lppreviouscount is the value before the increase returned <br/>{< br/> printf ("releasesemaphore error: % d/N ", getlasterror (); <br/>}< br/> break; </P> <p> // The semaphore was nonsignaled, so a time-out occurred. <br/> case wait_timeout: <br /> Printf ("thread % d: Wait timed out/N", getcurrentthreadid (); <br/> break; <br/>}< br/> return true; <br/>}</P> <p> Part 2-semaphore) sample program <br/>/* semabinit. c-initialize a semaphore for use by programs Sema and Semb */</P> <p> # include <sys/types. h> <br/> # include <sys/IPC. h> <br/> # include <sys/SEM. h> <br/> # include <stdio. h> </P> <p>/* the semaphore key is an arbitrary long integ Er which serves as an <br/> external identifier by which the semaphore is known to any program <br/> that wishes to use it. */</P> <p> # define key (1492) </P> <p> void main () <br/>{< br/> int ID; /* number by which the semaphore is known within a program */</P> <p>/* The next thing is an argument to the semctl () function. semctl () <br/> does various things to the semaphore depending on which arguments <br/> Are passed. we will use it to make sure that the value of the <br/> semaphore is initially 0. */</P> <p> Union semun {<br/> int val; <br/> struct semid_ds * Buf; <br/> ushort * array; <br/>} argument; </P> <p> argument. val = 0; </P> <p>/* Create the semaphore with external key if it doesn't already <br/> exists. give permissions to the world. */</P> <p> id = semget (Key, 1, 0666 | ipc_creat); </P> <p>/* always Check System returns. */</P> <p> If (ID <0) <br/> {<br/> fprintf (stderr, "unable to obtain semaphore. "); <br/> exit (0); <br/>}</P> <p>/* what we actually get is an array of semaphores. the second <br/> argument to semget () was the array dimension-in our case <br/> 1. */</P> <p>/* set the value of the number 0 semaphore in semaphore array <br/> # ID to the value 0. */</P> <p> If (semctl (ID, 0, setval, argu Ment) <0) <br/>{< br/> fprintf (stderr, "cannot set semaphore value. "); <br/>}< br/> else <br/>{< br/> fprintf (stderr," semaphore % d initialized. ", key); <br/>}</P> <p>/* semaphore example program a (Sema. c) */<br/>/* we have two programs, Sema and Semb. semb may be initiated at any <br/> time, but will be forced to wait until Sema is executed. sema and <br/> Semb do not have to be executed The same user! */</P> <p> # include <stdio. h> <br/> # include <sys/types. h> <br/> # include <sys/IPC. h> <br/> # include <sys/SEM. h> </P> <p> # define key (1492) <br/>/* This is the external name by which the semaphore is known to any <br/> program that wishes to access it. */</P> <p> void main () <br/> {<br/> int ID;/* internal identifier of the semaphore. */<br/> struct sembuf operations [1]; <br/>/* an "array" of one operation To perform on the semaphore. */</P> <p> int retval;/* return value from semop () */</P> <p>/* Get the index for the semaphore with external name key. */<br/> id = semget (keys, 1, 0666); <br/> If (ID <0) <br/>/* semaphore does not exist. */<br/>{< br/> fprintf (stderr, "program Sema cannot find semaphore, exiting. "); <br/> exit (0); <br/>}</P> <p>/* do a semaphore V-operation. */<br/> printf ("program Sema Bout to do a V-operation. "); </P> <p>/* set up the sembuf structure. */<br/>/* which semaphore In the semaphore array: */<br/> operations [0]. sem_num = 0; <br/>/* which operation? Add 1 to semaphore value: */<br/> operations [0]. sem_op = 1; <br/>/* set the flag so we will wait: */<br/> operations [0]. sem_flg = 0; </P> <p>/* So do the operation! */<Br/> retval = semop (ID, operations, 1); </P> <p> If (retval = 0) <br/>{< br/> printf ("successful V-operation by program Sema. "); <br/>}< br/> else <br/> {<br/> printf (" Sema: V-operation did not succeed. "); <br/> perror (" reason "); <br/>}</P> <p>/* think carefully about what the V-operation does. if Sema is executed <br/> twice, then Semb can execute twice. */</P> <p>/* semaphore example program B (Semb. c) */<br/>/* we have two programs, Sema and Semb. semb may be initiated at any <br/> time, but will be forced to wait until Sema is executed. sema and <br/> Semb do not have to be executed by the same user! */</P> <p>/* how to test: <br/> execute Semb & <br/> the & is important-otherwise you wowould have to move to <br/> A different terminal to execute Sema. </P> <p> then execute Sema. <br/> */</P> <p> # include <stdio. h> <br/> # include <sys/types. h> <br/> # include <sys/IPC. h> <br/> # include <sys/SEM. h> </P> <p> # define key (1492) <br/>/* This is the external name by which the semaphore is known to any <br/> prog Ram that wishes to access it. */</P> <p> void main () <br/> {<br/> int ID;/* internal identifier of the semaphore. */<br/> struct sembuf operations [1]; <br/>/* an "array" of one operation to perform on the semaphore. */</P> <p> int retval;/* return value from semop () */</P> <p>/* Get the index for the semaphore with external name key. */<br/> id = semget (keys, 1, 0666); <br/> If (ID <0) <br/>/* semaphore Does not exist. */<br/>{< br/> fprintf (stderr, "program Semb cannot find semaphore, exiting. "); <br/> exit (0); <br/>}</P> <p>/* do a semaphore p-operation. */<br/> printf ("program Semb about to do a p-operation. "); <br/> printf (" process ID is % d ", getpid (); </P> <p>/* set up the sembuf structure. */<br/>/* which semaphore In the semaphore array: */<br/> operations [0]. sem_num = 0; <br/>/* which OP Eration? Subtract 1 from semaphore value: */<br/> operations [0]. sem_op =-1; <br/>/* set the flag so we will wait: */<br/> operations [0]. sem_flg = 0; </P> <p>/* So do the operation! */<Br/> retval = semop (ID, operations, 1); </P> <p> If (retval = 0) <br/>{< br/> printf ("successful p-operation by program Semb. "); <br/> printf (" process ID is % d ", getpid ()); <br/>}< br/> else <br/> {<br/> printf ("Semb: p-operation did not succeed. "); <br/>}</P> <p>/* think carefully about what the V-operation does. if Sema is executed <br/> twice, then Semb can execute twice. */<br/>