Unix Portability: Semaphore

Download Report

Transcript Unix Portability: Semaphore

UNIX Portability
Semaphore
Guenter Fauser
HP Bad Homburg
Semaphore
Begriffsdefinition
Ein Semaphor ist eine Datenstruktur mit zwei
speziellen Nutzungsoperationen.
Semaphore werden bei der Programmierung zur
Prozesssynchronisation eingesetzt, also zur
Lösung von Aufgaben, bei denen die parallele
Ausführung mehrerer Prozesse/Threads eine
zeitliche Abstimmung der Ausführungen erfordert.
[Ref. Wikipedia.org]
2
12 July 2016
Semaphore
Namensherkunft
•
Namensherkunft
•
Ursprünglich bezeichnet das Wort Semaphor
einen Signalmast mit beweglichen Flügeln, wie er
zur Nachrichtenübertragung in früheren
Jahrhunderten eingesetzt wurde, später auch
Verkehrsampel. Auch bei der Eisenbahn wurden
die Formsignale als Semaphore bezeichnet.
3
12 July 2016
Semaphore
Lösung von Dijkstra
•
Semaphore als Mechanismus für die
Prozesssynchronisation wurden von Edsger W. Dijkstra
konzipiert und 1965 in seinem Artikel „Cooperating
sequential processes“ vorgestellt.
• Ein Semaphor ist eine Datenstruktur mit einer
Initialisierungsoperation und zwei Nutzungsoperationen.
• Die Datenstruktur besteht aus einem Zähler und einer
Warteschlange für die Aufnahme blockierter Prozesse:
struct Semaphor {
int zaehler;
Queue queue;
}
4
12 July 2016
/* Warteschlange */
Semaphore
Lösung von Dijkstra
• Zähler wie Warteschlange sind geschützt und können nur über die
Semaphoroperationen verändert werden.
• Die Wirkung der Nutzungsoperation kann wie folgt zusammenfassend
beschrieben werden:
• Semaphore regeln durch Zählen Wechselwirkungssituationen von
Prozessen
• Semaphore realisieren ein passives Warten der Prozesse, wenn eine
Weiterausführung nicht gestattet werden kann
• Mit der Initialisierungsoperation wird der Zähler auf einen nicht
negativen Wert und die Warteschlange i. d. R. auf leer gesetzt.
void init (Semaphor s, int v) {
s.zaehler = v;
s.queue.empty ();
}
5
12 July 2016
Semaphore
Lösung von Dijkstra
•
Die Nutzungsoperationen wurden von Dijkstra mit
P und V bezeichnet. Dies sind Initialen
niederländischer Wörter bzw. Kofferwörter für
prolaag und verhoog.
•
Programmierschnittstellen verwenden deutlichere
Bezeichnungen wie wait, acquire oder down für
die P-Operation und signal, release oder up für
die V-Operation.
6
12 July 2016
Semaphore
Lösung von Dijkstra
•
7
Semaphore, deren Zähler aufgrund der
Initialisierung und der Verwendung 1 als größten
positiven Wert annehmen können, werden
oftmals auch binäre Semaphore bezeichnet.
Semaphore, deren Zähler größere positive Werte
annehmen können, werden dann zählende
Semaphore („Counted Semaphor“) genannt.
12 July 2016
Semaphore
Lösung von Dijkstra (acquire lock)
•
Bei einem Aufruf der P-Operation wird der Zähler
dekrementiert. Ist der Zähler danach größer
gleich 0, so setzt der Prozess seine Aktionen fort.
Ist der Zähler jedoch kleiner als Null, kehrt der
Kontrollfluss nicht aus der Operation zurück. Der
aufrufende Prozess wird blockiert und in die
Warteschlange des Semaphor eingereiht.
void P (Semaphor s) {
s.zaehler = s.zaehler - 1;
if (s.zaehler < 0)
block (s.queue);
}
8
12 July 2016
/* Blockieren des Prozesses*/
Semaphore
Lösung von Dijkstra (release lock)
•
Bei einem Aufruf der V-Operation wird der Zähler
inkrementiert. Ist der Zähler danach größer gleich
0, so wird ein Prozess aus der Warteschlange
entfernt. Dieser Prozess setzt dann seine
Aktionen mit denen fort, die dem blockierenden
P-Aufruf folgen.
void V (Semaphor s) {
s.zaehler = s.zaehler + 1;
if (s.zaehler >= 0)
ready (s.queue);
}
9
12 July 2016
/* Entblockieren eines Prozesses aus der Warteschlange */
Semaphore
Lösung von Dijkstra
•
Beide Operationen müssen unteilbare Aktionen
(„atomic instruction“) sein.
•
Dadurch ist garantiert, dass nach dem Aufruf
einer Semaphor Operation kein anderer Prozess
auf den Semaphor durch einen Operationsaufruf
modifizierend zugreifen kann, bevor die zuerst
aufgerufene Semaphoroperation nicht vollständig
ausgeführt worden ist.
10
12 July 2016
Semaphore
Lösung von Dijkstra
•
•
•
11
Semaphore beheben den Nachteil des aktiven Wartens
anderer Synchronisationslösungen wie spezielle
Maschinenbefehle oder Spinlocks, da ein Prozess passiv
wartend wird bis der Blockadegrund entfallen ist.
Die Definition lässt offen, welcher blockierte Prozess im
Rahmen der Ausführung der V-Operation der
Warteschlange entnommen wird. Ein Semaphor, der eine
echte Warteschlange nach dem Windhundprinzip (engl.
„first come, first served“) garantiert, wird manchmal als
starker Semaphor bezeichnet.
Ein schwacher Semaphor garantiert hingegen nicht die
chronologisch richtige Abarbeitung der Warteschlange. So
wird z. B. beim Echtzeitbetrieb das Entblockieren von
Prozessen an deren Priorität statt an deren
Blockierungszeitpunkt gebunden.
12 July 2016
Semaphore
Mutex und Atomic Instructions
•
•
Neben dem Begriff Semaphor werden in diesem
Zusammenhang noch die weitere Begriffe Mutex und
„atomic instructions“ verwendet.
Diese Begriffe lassen sich nach ihrer
Verarbeitungsgeschwindigkeit einordnen
Semaphore
Slow
Mutex
Atomic Instructions
Fast
Ein Mutex (“mutually exclusive access”) wird oft auch
als binare Semaphor bezeichnet
12
12 July 2016
Semaphore
Hierarchie von Semaphors
•
Um die Wahrscheinlichkeit von “deadlocks” zu verringern,
müssen Semaphore oft in einer Hierarchie zusammen
gefasst werden.
Prozess 1
13
12 July 2016
Prozess 2
Request Resource A
Request Resource B
Request Resource B
Request Resource A
UNIX Portability
Semaphores und OVMS Lock Manager
•
Locks und Mutex‘es werden häufig und in vielen
Programmen gebraucht. Die Nutzung des
OpenVMS “Distributed Lock Managers” ist jedoch
sehr verschieden von den, in Unix Systemen
gebräuchlichen IPC Semaphore.
•
Ein Ausweg ist oft die Verwendung von Mutex’es
aus der Posix Thread library.
•
Eine Implementierung der UNIX System V IPC
Semaphore auf OpenVMS erleichtert die
Portierung von UNIX Programmen nach
OpenVMS in vielen Fällen erheblich.
14
12 July 2016
UNIX Portability
OVMS Distributed Lock Manager
•
Der OpenVMS Distributed Lock Manager implementiert
ein mehrstufiges locking System mit sechs fest definierten
„lock value“ Stufen.
NL
CR
CW
PR
PW
EX
15
12 July 2016
Bedeutung
Null Lock
Concurrent Read
Concurrent Write
Protected Read
Protected Write
Exclusive
UNIX Portability
OpenVMS distributed Lock Manager
Requested Mode of Currently Granted Locks
Lock
NL
CR
CW
PR
PW
EX
NL
Yes
Yes
Yes
Yes
Yes
Yes
CR
Yes
Yes
Yes
Yes
Yes
No
CW
Yes
Yes
Yes
No
No
No
PR
Yes
Yes
No
Yes
No
No
PW
Yes
Yes
No
No
No
No
EX
Yes
No
No
No
No
No
16
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
•
•
•
•
17
Ein eher komplexes System steht mit den System V IPC
Semaphore zur Verfügung. Es ist am einfachsten als eine
Verwaltung von Ressourcen zu beschreiben.
Anfänglich wird ein maximaler Wert von Ressourcen als
Semaphor Wert vorgegeben.
Jeder Prozess kann von diesem Semaphor Wert
Ressourcen abrufen, wodurch der Semaphor Wert
entsprechend reduziert wird.
Verlangt ein Prozess mehr Ressourcen als derzeit zur
Verfügung stehen, wird dieser Prozess in einen passiven
Wartezustand versetzt und muss warten, bis ein anderer
Prozess genügend Ressourcen and den Semaphor
zurück gibt.
Der Wert der Semaphor kann Null, aber nicht negativ
werden.
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
“Counted Semaphore“ in UNIX System V sind
implementiert als ein „Global shared section“ zu
dem jeder Prozess im System Zugriff hat.
System V Kernel
User
User
Program
Program
User
Program
18
12 July 2016
IPC
IPC
API
API
IPC
API
IPC
shared
memory
segment
UNIX Portability
UNIX System V IPC Semaphore
•
•
The semget() function
semget – get/create set of semaphore
•
#include <sys/sem.h>
•
int semget(key_t key, int nsems, int semflg);
•
Semaphore are organized in up to 10
Semaphores Sets identified by key, each set can
containing up to 25 independent Semaphore.
•
nsems is used to specify the number of
Semaphore to be created in a Set.
19
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
•
•
•
•
20
int semget(key_t key, int nsems, int semflg);
key is an arbitrary number in the 16 bit range and
used to identify the Semaphore Set to be used or
created.
semflg is set either to IPC_PRIVATE or
IPC_CREATE
If set to IPC_PRIVATE and key already exists, a
connection to the existing Semaphore Set is
made, otherwise a new Semaphore Set is
created for the given key.
If set to IPC_CREATE, and key does not exists, a
Semaphore Set is created for the given key.
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
•
•
•
•
•
•
•
•
•
•
•
21
int main(int argc, char *argv[])
{
int sm_key;
if((sm_key = semget(12345, 10, IPC_CREATE | 077)) < 0)
{
perror("semget() has failed");
exit(0);
}
In this example, semget() creates a Semaphore Set containing 10
independent Semaphore for the key value “12345” under the
assumption, that the key value “12345” is not already in
use.
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
•
•
•
22
The semop() function.
#include "ipc.h“
int semop(int semid, struct sembuf *sops, size_t nsops);
The semop() function is used to perform atomically a user-defined
array of semaphore operations on the set of semaphores associated
with the semaphore identifier specified by the argument semid.
12 July 2016
Member
Type
Member
Name
Description
short
short
sem_nu
m
sem_op
short
sem_flg
Semaphore
Number
Semaphore
operation
Operation
flag
UNIX Portability
UNIX System V IPC Semaphors
•
The sembuf data structure item sem_op is used
to specify the Semaphore operation.
•
sem_op < 0 Allocate the abs. value of sem_op
resources from Semaphore. If the resource count
of the Semaphore is less the requested number
of resources, block the process.
•
sem_op > 0 Add the value of sem_op to the
Semaphore resource count and unblock
processes.
•
sem_op = 0 Block until the Semaphore resource
count becomes zero.
23
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
The semctl() function.
•
#include <sys/sem.h>
•
int semctl(int semid, int semnum, int cmd, ...);
•
The semctl() function provides a variety of
semaphore control operations as specified by
cmd. The fourth argument is optional and
depends upon the operation requested.
24
12 July 2016
UNIX Portability
UNIX System V IPC Semaphore
•
The semctl() functions
GETVAL
SETVAL
GETPID
GETCNT
GETZCNT
GETALL
SETALL
IPC_STAT
IPC_SET
IPC_RMID
25
12 July 2016
Return the Semaphore value
Set the Semaphore value
Return the last op. Semaphore PID
Return number of blocked processes
Return number of zero blocked processes
Return the value of all Semaphores in Set
Set the value of all Semaphores in Set
Return the semid_ds data structure
Set the semid_ds data structure
Remove the Semaphore Set from system.
UNIX Portability
The Beer brewery example
if resource count == 0
(semop() function 0)
Glassware
producer
of
beer bottles
Brewery
add resource
Producer
Resource count
consumes
returns
returns
consumes
Consumer
3
Wait
26
12 July 2016
Wait
consumes
Consumer
2
returns
Consumer
1
Wait
UNIX Portability
OVMS IPC Semaphore Components
•
IPC$SHARE.C
•
IPC$SHARE.H
•
IPC$SHARE.OPT
•
IPC.H
•
IPCLIB.C
27
12 July 2016
UNIX Portability
OVMS IPC Semaphores Build instructions
•
$Compile IPC$SHARE
•
$Compile IPCLIB
•
$LINK/share=IPC$SHARE.EXE IPC$SHARE,IPC$SHARE.OPT
28
12 July 2016
UNIX Portability
The Beer brewery Build instructions
•
•
•
•
•
•
29
$Compile BOTTLE_CONSUMER
$COMPILE BOTTLE_PRODUCER_A (Deadlock Example)
$COMPILE BOTTLE_PRODUCER_B (Working Example)
$LINK BOTTLE_PRODUCER_A,IPCLIB,IPC$SHARE/SHARE
$LINK BOTTLE_PRODUCER_B,IPCLIB,IPC$SHARE/SHARE
$LINK BOTTLE_CONSUMER,IPCLIB,IPC$SHARE/SHARE
12 July 2016
UNIX Portability
Bibliography
W.Richard Stevens Advanced Programming in the UNIX
Environment
David R. Butenhof
Programming with POSIX Threads
Allen B. Downey
The Little Book of Semaphores
http://greenteapress.com/semaphores
http://h71000.www7.hp.com/doc/
30
12 July 2016
Unix Portability
Semaphore
?
UNIX Portability
Fun with Semaphore
•
Problem der essenden Philosophen
•
Das Problem der essenden Philosophen (dining
philosopher problem) macht die Grundannahme, dass
Philosophen abwechseln denken und Spaghetti essen.
Das ist (ausser für Philosophen) an sich noch kein
Problem, es sei denn, es ist zu wenig Besteck vorhanden:
32
12 July 2016
UNIX Portability
Fun with Semaphores
•
•
Damit ein Philosoph essen kann, muss er zwei Gabeln
nehmen. Da nur soviel Gabeln vorhanden sind wie
Philosophen, können nicht alle Philosophen gleichzeitig
essen. Gesucht ist nun ein Algorithmus, der es erlaubt,
dass möglichst viele Philosophen gleichzeitig essen und
kein Philosoph benachteiligt wird.
Jeder Philosoph führt nacheinander und wiederholt die
Schritte
denken (think),
Gabeln nehmen (take forks),
essen (eat) und
Gabeln wieder hinlegen (put forks)
aus.
33
12 July 2016
UNIX Portability
Fun with Semaphore
•
Ein einfacher Algorithmus, der den oben genannten
Anforderungen genügt, repräsentiert jede Gabel durch
einen Semaphor mit Initial- und Maximalwert 1. Jeder
Philosoph führt während des Schritts takeForks ein
acquire für seine beiden Gabel-Semaphoren aus und
beim Schritt putForks ein release für die beiden
Semaphore. Damit kein Deadlock entsteht, nummeriert
man die Gabeln und stellt sicher, dass alle Philosophen
immer zuerst ein acquire auf dem Gabel-Semaphor
ausführt, der mit der niedrigeren Zahl beschriftet ist.
Literatur: Andrew S. Tanenbaum: Modern Operating
Systems; Kapitel 2.3.1
34
12 July 2016