Inter-process communication

Source: Internet
Author: User
Tags mutex semaphore

Inter-process communication

Inter-process communication (Inter process Communication, IPC) has 3 main problems:

(1) How a process transmits information to another process;

(2) Ensuring that two or more processes do not intersect in key activities;

(3) The timing of the process with the collaborative relationship.

Two or more processes read and write some shared data, and the final result depends on the precise timing of the process being run, called the race condition (race condition). The program fragment that we access to shared memory is called the critical region (critical regions) or the critical section (critical), and if we can guarantee that two processes cannot be in the critical zone at the same time, Can avoid competitive conditions. To avoid competitive conditions, some means to ensure that the current process is using a shared variable or file, other processes cannot do the same thing, called mutexes (Mutual exclusion).

A good mutex scheme needs to meet the following 4 conditions:

(1) No two processes can be in their critical section at the same time;

(2) The process of running outside the critical area shall not obstruct other processes;

(3) The process shall not be allowed to wait indefinitely for entry into the critical section;

(4) Do not make any assumptions about the speed and quantity of the CPU.

Here are a few scenarios to implement mutual exclusion:

1. Busy waiting (busy waiting)

1.1 Shielding interrupts

In a single-processor system, the simplest approach is to have each process block all interrupts immediately after entering the critical area and open the interrupts before leaving. After a shielded interrupt, the CPU will not switch to another process.

However, this is not a good solution, the right to block the interruption of the user process will be a risk, if the process is not opened after blocking, will cause the entire system to terminate. In addition, in a multi-CPU system, the blocking interrupt is only valid for the CPU executing the disable instruction, and the other CPUs will continue to run and have access to shared memory.

1.2 Lock variable

Imagine a shared lock variable with an initial value of 0. 0 indicates that there is no process in the critical section and 1 indicates that a process has entered the critical section.
When a process enters a critical section, the lock is tested first, and if the value of the lock is 0, the process sets it to 1 and enters the critical section, and if the lock has a value of 1, the process waits until its value becomes 0.
Flaw in lock variable: If a process reads out a lock variable with a value of 0, but before it is set to 1, another process is scheduled to run and the lock variable is set to 1. When the first process is able to run again, it also sets the lock to 1, at which point two processes enter the critical section.

1.3 Strict Rotation method

1 //Process 02  while(True) {3          while(Turn! =0);//wait turn equals 04 critical_region ();5turn =1;//leave the critical section6 noncritical_region ();7 }8 9 //Process 1Ten  while(True) { One      while(Turn! =1);//wait turn equals 1 A critical_region ();  -turn =0;//leave the critical section - noncritical_region ();  the}

The strict rotation method uses a busy wait, that is, to test a variable continuously until a value appears, the lock used for the busy waiting is called the spin lock (Spin lock), which is usually avoided by wasting CPU time.
Code Description: Process 0 leaves the critical section, set turn to 1 to allow process 1 to enter its critical section. Assuming that process 1 quickly leaves the critical section, two processes are outside the critical section, and the value of turn is set to 0. If process 1 suddenly ends the non-critical section and returns the start of the loop, however, it cannot enter the critical section because the value of turn is 0, and process 0 is still busy with the non-critical section, Process 1 has to continue while loop until process 0 changes the value of turn to 1. This actually violates the mutually exclusive condition described earlier (2), where a process running outside the critical zone must not block other processes.

1.4 Peterson Solution

1 #defineN 2//Number of processes2 intTurn//Lock Variable3 intInterested[n]; 4   5 voidEnter_region (intprocess) {  6     intOther ; 7other =1-process;//Other Processes8Interested[process] =True; 9turn =process; Ten      while(turn==process && interested[other]==true);//wait for other to leave the critical section One }   A    - voidLeave_region (intprocess) {   -Interested[process] =False;  the}

Code Description: At first, no process is in the critical section, and now process 0 calls Enter_region, which sets the array element and turn to zero to indicate that it wants to enter the critical section. Since process 1 is not in the critical section, Enter_region returns quickly. If process 1 calls enter_region at this point, process 1 will hang here until Interested[0] becomes false, and the event will occur only if process 0 calls Leave_region exits the critical section.

1.5 TSL Directive/xchg directive

On some computers, there are instructions such as the following:
TSL RX, LOCK
The TSL (Test and Set Lock) instruction reads a memory word lock into the Register RX and then saves the memory address with a value other than 0. Read and write operations are guaranteed to be indivisible, meaning that the memory word is not allowed to be accessed by other processors until the end of the instruction. The CPU executing the TSL instruction locks the memory bus to prevent other CPUs from accessing memory before the end of this instruction.

Enter and leave the critical section with the TSL command  enter_region:      TSL Register, lock,  copy lock variable to register, and set lock to 1      CMP Register, #0          JNE enter_ Region    ; If the lock is not equal to 0, continue to loop waiting for      ret    leave_region:      MOVE Lock, #0      ret  

As can be seen from the code, the process calls enter_region before entering the critical section, which results in a busy wait until the lock is idle, and the easygoing it obtains the lock and returns. It calls Leave_region when the process returns from the critical section, which sets the lock to 0.
An alternative to the TSL directive is XCHG, which atomically swaps the contents of two locations.

Enter and leave the critical section with the XCHG command  enter_region:      move Register, #1         XCHG Register, lock, the contents of the interchange register and the lock variable      CMP REGISTER, #0    ; Test lock      JNE enter_region    ; If the lock is not equal to 0, continue to loop waiting for      ret    leave_region:      move lock, #0      ret  

2 sleeping and Waking (sleep & Wake Up)

The disadvantage of busy waiting: When a process to enter the critical section, first check whether to allow access, if not allowed, the process will wait in situ until allowed.


Consider a situation in which there are now two processes H and l,h with higher priority, l in the critical section, and h in the ready state. Since the priority of H is higher than l,l will not be dispatched and therefore cannot leave the critical section, then H will always be busy waiting, which is called priority inversion problem.
Sleep is blocking a process that cannot enter a critical section, not a busy wait, and the process is suspended until another process wakes it up.

1 #defineN 100//Buffer size2 intCount =0; 3   4 //Data Producers5 voidProducervoid){  6     intitem; 7      while(True) {8item = Produce_item ();//generate next new data item9         if(count==n) sleep ();//Enter hibernation if the buffer is fullTenInsert_item (item);//putting new data items into a buffer Onecount++;  A         if(count==1) Wakeup (consumer);//Wake-up consumer -     }   - }   the    - //Data Consumers - voidConsumervoid){   -     intitem;  +      while(True) { -         if(count==0) sleep ();//The buffer is empty and goes into hibernation +item = Remove_item ();//take a data item from the buffer Acount--;  at         if(count==n-1) Wakeup (producer);//Wake-up producer - Consume_item (item);  -     }   -}

Code Description: In the producer-consumer (Producer-consumer) problem, two processes share a common fixed-size buffer (bounded-buffer), one of which is the producer, puts the information in the buffer, and the other is the consumer, which takes the information from the buffer. When the buffer is full, let the producer sleep and wake the consumer when one or more data items are removed from the buffer. Similarly, when consumers try to fetch data from an empty buffer, the consumer sleeps until the producer puts some data items into it and wakes it up.
However, the code above still has a problem because the access to count is not restricted. In this case, when the buffer is empty, the consumer has just read Count's value of 0, and the scheduler happens to suspend the consumer and start the producer, and the producer adds a data item to the buffer, Count plus 1. Now that the value of count is 1, it infers that because count was just 0, the consumer must be asleep, so the producer calls Wakeup to wake the consumer. However, the consumer does not sleep logically at this time, so the wakeup signal is lost. When the consumer runs again, it tests the count value that was previously read, finds it to be 0, and sleeps. Sooner or later the producer will fill the entire buffer, and two processes will sleep forever.
The essence of the above problem is that the wakeup signal sent to a sober process is lost. We can set a wake-up wait bit, when a sober process receives the wakeup signal, the wake-up wait is set to 1, and then if the process receives a sleep signal, first detects the wake-up wait bit, if the wake-up wait bit is 1, then does not sleep, but only will wake up waiting for the bit clear 0.

3 signal Volume (semaphore)

The semaphore is an integer variable that is set to accumulate the number of wakes. There are two kinds of operations for semaphores: down and up (generalized sleep and wankeup).
Performing a down operation on the semaphore is to check whether its value is greater than 0, and if the value is greater than 0, subtract its value by 1 and continue, and if the value is 0, the process will sleep. Here, checking values, modifying variable values, and possible sleep operations is an atomic operation (not interrupted by the middle).
The up operation is also inseparable from the signal volume by 1, the value added of the Semaphore 1, and the wake operation.

1 #defineN 100//Buffer size2typedefintSemaphore; 3Semaphore full =0;//number of buffers already in use4semaphore empty = N;//number of buffers remaining5Semaphore Mutex =1;//Control access to critical sections6   7 //Data Producers8 voidProducervoid){  9     intitem; Ten      while(True) { Oneitem = Produce_item ();//generate next new data item ADown (&empty);  -Down (&mutex);//Enter the critical section - Insert_item (item);  theUp (&mutex);//leave the critical section -Up (&Full );  -     }   - }   +    - //Data Consumers + voidConsumervoid){   A     intitem;  at      while(True) { -Down (&Full );  -Down (&mutex);  -item =Remove_item ();  -Up (&mutex);  -Up (&empty);  in Consume_item (item);  -     }   to}

Code Description: A mutex is a two-dollar semaphore, each process performs a down operation on it before entering the critical section, and an up operation is performed after leaving the critical section to enable mutual exclusion. Another function of the semaphore is to achieve synchronization (synchronization), with the semaphore full and empty used to ensure that the producer stops running when the buffer is in the air, and that the consumer stops when the buffer is empty.

4 Mutex (mutex)

A mutex is a degraded semaphore that has only two states: Lock and unlock so that only one bits can be represented.
Mutexes are useful when implementing user-level threading packages. When a thread needs access to a critical section, call Mutex_lock, and if the mutex is currently unlocked, this call succeeds and the calling thread can enter the critical section freely. If the mutex is already locked, the calling thread is blocked until the thread in the critical section completes and calls Mutex_unlock. If multiple threads are blocked on the mutex, a thread is randomly selected and allowed to acquire the lock.

1 Mutex_lock:2 TSL REGISTER, MUTEX3CMP REGISTER, #0; test the mutex amount4 jze OK; unlock5 Call Thread_yield; Mutex busy, scheduling another thread6 JMP Mutex_lock; Try again later.7 Ok:ret8   9 Mutex_unlock:TenMOVE MUTEX, #0   OneRet

As you can see, the thread mutex is similar to the process mutex implemented by the TSL instruction in section 1.5, but there is a key difference :
When the enter_region enters the critical section, it always repeats the test lock (Busy wait). In fact, because of the clock timeout, other processes are scheduled to run, so that sooner or later the lock-owning process goes into operation and releases the lock.
When the mutex_lock enters the critical section, it calls Thread_yield to actively release the CPU to another thread, so there is no busy waiting. This is because the thread does not have a clock interrupt , and the thread that gets the lock through a busy wait is forever cycled, never getting a lock, and no other thread has a chance to run.

Several calls related to thread mutexes are listed below

Pthread_mutex_init

Create a mutex

Pthread_mutex_destroy

Revoke an already existing mutex

Pthread_mutex_lock

Get a lock or block

Pthread_mutex_unlock

Unlock

Pthread_mutex_trylock

Get a lock or fail


In addition to the mutex, Pthread provides another synchronization mechanism-the condition variable (condition variable). The mutex allows or blocks access to the critical section, which allows the thread to block due to some conditions that are not met. Conditional variables and mutexes are often used together, a pattern used to lock a thread into a mutex, and then wait for a condition variable when it cannot get the result it expects. Finally another thread will signal to him so that it can continue to execute. Note: The condition variable does not exist in memory, and if a semaphore is passed to a condition variable that does not have a thread waiting, then the signal is lost.

Inter-process communication

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.