1
1
. V UNIX IPC (interprocess communication) :
;
;
- .
, , .
, .
(key), , .
get, ; (flag). . IPC_PRIVATE . IPC_CREAT , , IPC_EXCL, , . , , , creat open.
: = . , , 100 , , 1, , 1, 101, 201 .. , : , get. , , . . 1 , 201, , 301. , 201, , . , , .
, , , , , control ( ), - - , , .
, , , , ( , , ..), .
control, , . , , , , . , ( ), , ; . , , ( ). , , , , . , , , . , . , , , .
2
|
|
(. Spinlock ) , .
- - . - , . - , - - ( busy-waiting). , - . - , , , , .
- , , IRQL. : , IRQL PASSIVE_ LEVEL - . IRQL DISPATCH_LEVEL, -, , -, . , , - , IRQL ! , , IRQL IRQL IRQL -. IRQL - IRQL, -, IRQL . , , IRQL, , -, IRQL - IRQL . - IRQL IRQL -, .
NT -:
|
|
- -, - /, / (. /).
- - .
- IRQL DISPATCH_LEVEL, :
- IRQL, DISPATCH_LEVEL;
- - IRQL DISPATCH_LEVEL.
- DIRQL. - ( - /, ). - , .
-
- 1. VOID KeInitializeSpinLock(IN PKSPIN_LOCK SpinLock); KSPIN_LOCK. - .
2. VOID KeAcquireSpinLock(IN PKSPIN_LOGK SpinLock, OUT PKIRQL Oldlrql); -. . IRQL DISPATCH_LEVEL. IRQL, ( <= DISPATCH_LEVEL).
3. VOID KeReleaseSpinLock(IN PKSPINJLOCK SpinLock, OUT PKIRQL Newlrql); - IRQL Newlrql. , KeAcquireSpinLock() Oldlrql.
4. VOID KeAcquireLockAtDpcLevel(IN PKSPIN_LOCK SpinLock); - , IRQL DISPATCH_LEVEL. IRQL . , IRQL.
5. VOID KeReleaseLockFromDpcLevel(IN PKSPIN_LOCK SpinLock); - , KeAcquireLockAtDpcLevel(). .
-:
typedef struct _DEVICE_EXTENSION
KSPIN_LOCK spinlock }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
*
NTSTATUS DriverEntry (....)
KelnitializeSpinLock(&extension->spinlock); }
NTSTATUS DispatchReadWrite(...)
{
KIRQL Oldlrql;
KeAcquireSpinLock(&extension->spinlock, &01dlrql); // , // -
KeReleaseSpinLock(&extension->spinlock, Oldlrql); }
2
1
(process specific). , handle , , . .
|
|
-, . ( ) .
-, . DuplicateHandle , .. , .
, , . (, , ) . . , Open(OpenMutex, OpenSemaphore, OpenWaitableTimer, OpenEvent) .
, Create... () , . , . , . , Create NULL. , (handle) . GetLastError() : Create() . |
, . .
10. , . - . |
int main(int argc, char* argv[]) { HANDLE Mutex; Mutex = CreateMutex(NULL,FALSE,"MyMutex"); if (ERROR_ALREADY_EXISTS == GetLastError()) // - ... { MessageBox(0," ","Error",0); CloseHandle(Mutex); exit(0); }... } |
2
, , .[1] , , .
, , - , .
, Concurrent Pascal Solo.
:
,
,
, ,
, (. ). , , , .
. , .
monitor account { int balance:= 0 function withdraw(int amount) { if amount < 0 then error " " else if balance < amount then error " " else balance:= balance - amount } function deposit(int amount) { if amount < 0 then error " " else balance:= balance + amount }}, , . , . , , D, . . , , -, .
|
|
䳿 . , , , .
9. , , . . , ' , .
, , , . , (Hoare) (Brinch Hansen) 1974 . , , , ' .
( - ) , , , . :
; .
.
; - , , .
, '- ' . , .
. , , . , , , . ϳ, , , .
, . :
cwait(c) c. .
csignal(c) , cwait . , ; , .
, cwait / csignal . , , . , , , .
( ) , , , - csignal . , csignal , .
:
, csignal , : , .
, ' , . csignal , . , ' .
|
|
(Lampson, Redell) Mesa ( Modula-3). csignal cnotify(x), .
, , cnotify(x), x, . , , . , , , , .
, - , ' cnotify. , , , , . , . , .
cbroadcast ( ), . , , . - .
- , . , .
. . ( Solaris). , , Java. synchronized , , '. , Java ', , ' .
3
1
- , wait signal init. 0 1. .
: , . , , , , , . , , .
, . ( ).
, .
;
( , ).
, .
semaphore.init(1); 1:semaphore.enter();cout << " : ";for (int i=0; i<n; i++) cout << a[i] << ' ';cout << '\n';semaphore.leave(); 2:semaphore.enter();cout << " Esc.\n";semaphore.leave();: 1 2 3 Esc.4 5 6
, . , , Algol-68. , wait signal, Algol-68 down up .
,
, Modula-2. . ³ Processes . 3.7:
˳ 3.7.
DEFINITION MODULE Processes;
TYPE SIGNAL;
PROCEDURE StartProcess(P:PROC; n:CARDINAL); (* , n *)
PROCEDURE SEND(VAR s:SIGNAL); (* ³ ,
s *)
PROCEDURE WAIT(VAR s:SIGNAL); (* s *)
PROCEDURE Awaited(VAR s:SIGNAL): BOOLEAN; (* TRUE
s *)
PROCEDURE Init(VAR s:SIGNAL); (* ' *)
END Processes.
³ ' Init , Awaited.
C/C++, , , , . , MFC Microsoft CSemaphore CMutex, ' .
UNIX.
UNIX- POSIX (P1003.1c). , , , .
POSIX
3.2. | |
pthread_mutex_init | ' |
pthread_mutex_destroy | ' |
pthread_mutex_lock | ' (. wait) |
pthread_mutex_unlock | ' (. signal) |
sem_init | |
sem_wait | (. wait) |
sem_post | (. signal) |
sem_getvalue |
2
/
/. , - . : , () ( ) ( ) , . , .
. . 3.9:
˳ 3.9.
#include <pthread.h> // POSIX-
#include <semaphore.h> // POSIX-
const int SizeOfBuffer = 64; //
pthread_t PRODUCERID, CONSUMERID; //
sem_t s; //
sem_t occupied; // ʳ
sem_t available; //
char chin, chout; //
char Buffer[SizeOfBuffer]; //
void Produce() { /* chin */ }
void Consume() { /* chout */ }
void Producer() { //
static int NextFree = 0;
while(true){
Produce(); //
sem_wait(&available); // sem_wait(&s); //
Buffer[NextFree]= chin; //
NextFree = (NextFree + 1) % SizeOfBuffer;
sem_post(&s); // ʳ
sem_post(&occupied); //
}
void Consumer() { //
static int NextChar = 0;
while(true){
sem_wait(&occupied); // sem_wait(&s); //
chout = Buffer[NextChar]; //
NextChar = (NextChar + 1) % SizeOfBuffer;
sem_post(&s); // ʳ
sem_post(&available); //
Consume(); //
}
void main() {
/* Ͳֲ˲Ӫ : */
sem_init(&s, 0, 1); //
sem_init(&occupied, 0, 0); // , sem_init(&available, 0, SizeOfBuffer); //
/* Ӫ : */
pthread_create(&PRODUCERID, NULL, Producer, NULL);
pthread_create(&CONSUMERID, NULL, Consumer, NULL);
} // , : NULL
- POSIX. ϳ Linux. ³, . , , .
4
1
3.9.1.
, . ( ). .
˳ 3.1.
boolean flag = false; /* */
/* 1 */ /* 2 */
while(flag); /* ײ*/ while(flag);
flag = true; flag = true;
/* IJ */ /* IJ */
flag = false; flag = false;
/* */ /* */
flag , . . . , . , , - (spinlock).
, (. 3.1.) . 1 flag, . 2, . flag, false, . , , ! , . . (T. Dekker). 1981 . (G.L. Peterson). [2].
3.9.2.
, . (. 3.2.).
˳ 3.2.
/* */;
/* */;
/* IJ */;
/* */;
/* */;
: ( ) (, ).
.
. 3.1 , , ' . - , - , ', , .
. 3.3.
˳ 3.3.
boolean testset(int i){
if(i==0){
i=1;
Return true;
}
Else
Return false;
}
(. . ). testset ' . , Pentium CMPXCHG reg/mem,reg1 ( ), : - reg1, ' reg/mem ( EAX). , -. .
. 3.4 - :
˳ 3.4.
const int n = /* */;
Int bvar;
void P(int i){
while(1){
while(!testset(bvar)); /* ײ */
/* */;
bvar = 0;
/* */;
}
void main(){
bvar = 0;
parbegin(P(1),P(2),...,P(n)); /* */
}
:
- -, .
, .
( ).
:
. .
. , , .
.
. 1
testset , 1 2 . 2 , . 1 , (. . ).
- . , - , . . Windows NT.
Windows NT - , IRQL (Interrupt ReQuest Level ). , IRQL IRQL , 䳺 -. IRQL - , -, IRQL . , IRQL, , - IRQL , .
2
/
/. . (, ) (), , (). ʳ , . . - , , -. ' -.
H. Ballhausen (˳. 3.10.).
˳ 3.10.
var semaphore mutex = 1; //
var semaphore access = m; //
process reader(integer i = 1... m) { // m
do {
Wait(access);
//... ...
Signal(access);
//... ...
}
}
process writer(integer j = 1... n) { // n
integer k;
do {
wait(mutex); //
for k = 1... m do wait(access); //
//
//... ...
for k = 1... m do signal(access);
signal(mutex);
//... ...
}
}
void main(){
// :
parbegin(reader(1),...,reader(m),writer(1),...,writer(n));
}
/ , .
5 1
, ( ), , . , .
, 䳿 , , [2] . 3.1.
䳿
3.1. | 䳿 | ||
. | . | . . | . ( ). . |
. | . | , ( , ). . | . ( ). . ' . |
( ). | '. | , . . | ( ). . |
, . . .
:
(mutual exclusion) - , , , . , , , () (critical section). , - . :
(deadlock). , 1 2 R1 R2 . ( : P1 R1, P2 R2) .
(starvation). 1, 2, 3 . 1 2 , 3 , .
, , .
( ), , .
( ), '. ' . , ' . . , . , , . .
. , - :
.
, () , .
( ).
, - , , .
.
.
:
( ).
.
.
2
Mutex (thread), (process), .
:
Mutex - . , , . Mutex . CreateMutex(), OpenMutex(), ReleaseMutex(). Mutex WaitForSingleObject(). . Mutex . Mutex . , CreateMutex() , . . .
(, mutex) - , , - . , - . , , , , - . , .
( ) , CreateMutex. , . , , . , bInitialOwner FALSE, .
, . :
- , CreateProcess , () CreateMutex lpMutexAttributes.
- DuplicateHandle.
- OpenMutex CreateMutex.
, , .
#include <windows.h>#include <process.h>
#include <stdio.h>
HANDLE hMutex;
int a[ 5 ];
void Thread(void* pParams)
{
int i, num = 0;
while (TRUE)
{
WaitForSingleObject(hMutex, INFINITE);
for (i = 0; i < 5; i++) a[ i ] = num;
ReleaseMutex(hMutex);
num++;
}
}
int main(void)
{
hMutex = CreateMutex(NULL, FALSE, NULL);
_beginthread(Thread, 0, NULL);
while(TRUE)
{
WaitForSingleObject(hMutex, INFINITE);
printf("%d %d %d %d %d\n",
a[ 0 ], a[ 1 ], a[ 2 ],
a[ 3 ], a[ 4 ]);
ReleaseMutex(hMutex);
}
return 0;
}