[C++] Synchronisationsproblem

Herbert2221

Cadet 4th Year
Registriert
Juli 2001
Beiträge
87
Synchronisationsproblem

Hallo.
Hat jemand Ahnung, wie man den Zugriff auf eine Datei von mehreren (nicht verwandten) Prozessen gleichzeitig synchronisiert? (UNIX, gcc)

Wenn ich das ganze als Threads organisiere, dann kann ich ja eine Monitorklasse benutzen. Aber wie geht das mit nicht verwandten Prozessen ??
 
Teil 1

Die Synchronation von nicht verwandten Prozessen geschieht unter UNIX mittels des Semaphorkonzept :

Semaphorkonzept
Implementierung des Konzeptes unter UNIX ( allgemeine Semaphore, d.h. es können auch Werte > 1 annehmen )

Jedes Semaphor wird mit einem Namen versehen. Hierbei ist zu bedenken, daß unter UNIX das Konzept so ausgelegt ist, daß immer ein Satz von Semaphoren angelegt wird. Genaugenommen bekommt also ein solcher Semaphorsatz einen Namen. Die einzelnen Semaphore sind zu einem Array angeordnet und werden durch ihre Platznummer ( von 0 ) an identifiziert. Ein solcher Satz besteht aus einer frei definierbaren Anzahl von Semaphoren. In nachfolgendem Bild ist ein Beispiel dargestellt. Es sind insgesamt 5 Sätze von Semaphoren definiert. Sie bestehen aus 5,1,3,2 bzw. 4 Elementen. Jeder Satz wird durch einen Kopf verwaltet.

Neben dem Namen gibt es mehrere Variablen, die einen solchen Satz und die einzelnen Semaphore beschreiben.

Zu diesen Kenndaten gehören:

der Wert des Semaphors (0, 1 oder größer),
die Prozeßnummer des Prozesses, der das Semaphor zuletzt manipuliert hat,
die Anzahl der Prozesse, die den Wert des Semaphors verändern wollen oder auf einen bestimmten Wert des Semaphors warten,
Zugriffsrechte und Besitzverhältnisse.
Für alle Semaphoren im Satz gibt es eine Variable des Datentyps 'struct sem' und der gesamte Semaphorsatz wird durch eine Variable des Datentyps 'struct semid_ds' beschrieben.

Die genauen Datenstrukturen zur Verwaltung von Semaphoren sehen folgendermaßen aus:

struct sem
{
ushort semval; /* Wert des Semaphors */
short sempid; /* PID des letzten Prozesses */
/* Prozesse die warten bis */
ushort semncnt; /* semval > aktuellen Wert */
/* Prozesse die warten bis */
ushort semzcnt; /* semval = 0 */
};

struct semid_ds
{
struct ipc_perm sem_perm; /* Zugriffsrechte */
struct sem *sem_base; /* Zeiger auf Semaphor */
ushort sem_nsems; /* Anzahl Semaphore im */
/* Satz */
time_t sem_otime; /* Zugriffszeit */
time_t sem_ctime; /* Zugriffszeit */
};

Seine Schalterfunktion bekommt ein Semaphor durch seinen ganz-zahligen Wert. Je nach Wert des Semaphors gilt es als gesetzt oder nicht gesetzt.

In einem Programm muß man mit den drei Systemaufrufen semget(),semop() und semctl() den Zugriff auf das Semaphor erlangen und die entsprechenden Operationen durchführen.

Kurze Erläuterungen für dem Umgang mit Semaphoren:
Ein Semaphorsatz muß vom Programmierer angelegt und mit einem Namen versehen werden. Dies geschieht mit der Funktion semget().

Die eigentliche Arbeit mit dem Semaphor läßt sich auf wenige Schritte reduzieren:

Das Semaphor muß vom Betriebssystem angefordert werden und dem Prozeß verfügbar gemacht werden.Dazu dient wiederum die Funktion semget().
Bei Beginn der "kritischen Region" : Die "kritische Region" ist der Programmabschnitt, in dem der Prozeß exklusiven Zugriff auf ein Betriebsmittel besitzt. Dieser Abschnitt sollte aus Performancegründen möglichst klein gehalten werden.
Eingeleitet wird die "kritische Region" mit der Abfrage des Wertes des Semaphors. Signalisiert das Semaphor 'grünes Licht', d.h. ist das Semaphor nicht gesetzt, so wird es gesetzt. Dadurch bekommt das Programm exklusiven Zugriff auf das Betriebsmittel. Dies geschieht mit dem Systemaufruf semop().
Hat das Programm die notwendigen Operationen mit dem Betriebsmittel ausgeführt, so wird die "kritische Region" verlassen und das Semaphor zurückgesetzt. Dies geschieht wieder mit der Funktion semop().
Was passiert nun, wenn ein Prozeß einen Semaphor-Aufruf startet und die Funktion erkennt, daß das Semaphor gesperrt ist ?
Durch Parametrierung der Funktion semop() können zwei Fälle unterschieden werden:

--> der Prozeß wartet, bis das Semaphor zurückgesetzt und das Betriebsmittel frei ist,
--> der Prozeß bricht den Zugriff auf das Betriebsmittel ab und führt andere Aktivitäten aus.

Nachdem nun der Umgang mit Semaphoren kurz geschildert wurde, werden nun die einzelnen Arbeitsschritte nochmals ausführlich erklärt :

Das Anlegen eines Semaphorsatzes mit der Funktion semget()

int semget(key, nsem, flag)
key_t key;
int nsem;
int flag;

key Name des Semaphors (Betriebssystemebene)
nsem Anzahl der Semaphore im Satz
flag Zugriffsrechte und andere Parameter

Rueckgabewert:
Fehler -1
sonst programminterner Name

Die Funktion wird mit drei Parametern aufgerufen.

Der erste Parameter ist der frei zu vergebende Name des Semaphor-satzes vom Datentyp " key_t " ( in der Regel ein int oder ein short, siehe ipc.h ). Die Anzahl der Semaphore im Satz wird im zweiten Parameter festgelegt. Im dritten Parameter ( der Variablen flag ) werden die Zugriffsrechte auf den Semaphorsatz definiert. Diese werden als oktale Zahl ( in C durch eine führende '0' gekennzeichnet ). Außerdem muß hier angegeben werden, daß ein Semaphor neu angelegt werden soll. Der Parameter flag kann als Bitmuster interpretiert werden, das Informationen über die Zugriffsrechte enthält. Um semget() anzuweisen, ein Semaphor neu anzulegen, muß eim weiteres Bit über die symbolische Konstante IPC_CREAT gesetzt werden. Für den Aufruf von semget() werden die Zugriffsrechte und IPC_CREAT durch den Operator | verbunden ( bitweise ODER-Verknüpfung ).

Beispiel für einen semget()-Aufruf:

sem_id = semget(5, 1, 0644 | IPC_CREAT);

Dieser Funktionsaufruf legt aufgrund des Flags IPC_CREAT einen Semaphorsatz mit dem Namen 5 neu an. Der Satz besteht aus einem Semaphor und besitzt die Zugriffsrecht 0644. Bei diesem neuen Semaphorsatz wird vom Betriebssystem eine Identifikation zugeteilt, die die Funktion semget() als Returnwert an das Programm zurückliefert. Dieser Wert bildet den "programminternen" Namen des Semaphors. Über ihn ist es jetzt im Programm bekannt und kann im weiteren Programmverlauf von den Funktionen semop() und semctl() angesprochen werden. Existiert ein Semaphor bereits, so wird IPC_CREAT ignoriert und das Semaphor dem Prozeß verfügbar gemacht.

Die Konstante IPC_EXCL erzwingt im Verbund mit der Konstanten IPC_CREAT einen Fehler, wenn das Semaphor bereits besteht.

Das Anfordern eines Semaphorsatzes mit der Funktion semget()
Ist ein Semaphor angelegt, so kann es in anderen Programmen mit der Funktion semget() verfügbar gemacht werden.

Gehen wir davon aus, daß ein Semaphor mit dem Namen 5 (dem 1. Parameter) bereits gibt. Im folgendem Beispiel macht semget() das Semaphor mit dem Namen 5 dem aktuellen Programm verfügbar.

semget(5, 1, 0644);

Der zweite Parameter gibt die Anzahl der Semaphore im Satz mit dem Namen 5 an. Er dient hier der Prüfung. Der letzte Parameter von semget() bestimmt die Zugriffsrechte. Wird die Funktion erfolgreich ausgeführt, so liefert sie eine Identifikation des Semaphors als Returnwert an das Programm. Kann die Funktion semget() das gewünschte Semaphor nicht anlegen oder nicht anfordern, so kommt es zu einem Fehler. Ein Fehler wird im Returnwert angezeigt, indem semget() eine -1 zurückliefert. Gleichzeitig wird die Variable errno beschrieben, die genaueren Aufschluß über die Art des Fehlers gibt. Ein Fehlerfall liegt vor, wenn eine der folgenden Bedingungen erfüllt ist:

Der benannte Semaphorsatz existiert noch nicht (gilt nicht, wenn IPC_CREAT angegeben ist)
Der Semaphorsatz existiert, hat aber weniger Elemente als gefordert.
Der Semaphorsatz existiert, aber die geforderten Zugriffsrechte (hier 0644 ) stimmen nicht mit den beim Anlegen vergebenen überein und sind auch keine Untermenge von diesen.
Besitzt ein Semaphor zum Beispiel die Zugriffsrechte 0666, so ist der obige Aufruf erfolgreich. Sind die Zugriffsrechte aber auf 0622 gesetzt, kommt es zu einem Fehler.

Die Zugriffsrechte für Semaphore sind analog zu den Zugriffs-rechten auf Dateien zu sehen, es gibt aber nur Lese- und Schreibrecht.

Es kann zu weiteren Fehlern kommen, wenn die Parameter beim Aufruf von semget() auf systemweite Grenzen für Semaphore stoßen ( z.B. maximal zulässige Anzahl von Semaphoren überschritten ). Diese Systemparameter werden bei der Systemgenerierung festgelegt und sind in der Datei /etc/master abgelegt.

Den Zugriff auf ein Semaphor mit der Funktion semget() organisieren
Aufgabe eines Semaphors ist es, immer nur der erlaubten Anzahl von Prozesse den Zugriff auf ein Betriebsmittel zu gestatten. Die Steuerung geschieht über den Wert des Semaphors. Alle beteiligten Prozesse müssen daher den Wert des Semaphors abfragen. Ist das Betriebsmittel frei ( Semaphor ist dann nicht gesetzt ), dann wird das Semaphor gesetzt und das Betriebsmittel für andere Prozesse gesperrt. Dies geschieht mit der Funktion semop(), die eine zentrale Stellung bei der Anwendung von Semaphoren einnimmt.

In der Abfolge von Prüfen des Wertes und Setzen der Semaphore liegt ja die Besonderheit des Semaphorkonzeptes. Als Systemaufruf implementiert sind nun beide Aktivitäten zu einer Einheit zusam-mengefaßt ( atomar ) und können durch keinen Interrupt unter-brochen werden. Dies macht Semaphore ziemlich sicher und ist ein gewichtiger Vorteil gegenüber anderen Synchronisationsmethoden, wie z. B. die " lock-Datei ". Hier sind die beiden Aktionen, " Existenz der Datei prüfen " und anschließend " Datei anlegen " getrennte und unabhängige Operationen. Störungen bei ihrer Ausführung können zu Inkonsistenzen Zuständen führen.

Im folgendem Beispiel besteht der Einfachheit halber der Satz aus genau einem Semaphor. Das Semaphor ist gesetzt, wenn es den Wert 0 angenommen hat. Ist der Wert 1, so ist das Semaphor nicht gesetzt.
 
Teil 2

Programmtechnisch ist jedes Semaphor durch eine Variable vom Typ 'struct sem' repräsentiert. Der Wert der Komponente semval ist der Wert des Semaphors.

Wir unterscheiden hier zwei Operationen mit Semaphoren:

Ein Betriebsmittel sperren (exclusiven Zugriff erlangen) bedeutet, den Wert des Semaphors auf 0 zu setzen.
Ein Betriebsmittel freigeben, indem das Semaphor zurück- gesetzt wird. Der Wert semval wird dabei von 0 auf einen positiven Wert gesetzt.
Diese Operationen werden zu Beginn und am Ende der " kritischen Region " ausgeführt. Aus der nachfolgenden Definition der Funktion semop() kann man erkennen, daß semop() mit drei Parametern aufgerufen wird:

dem internen Namen des Semaphors (Returnwert der Funktion semget()),
einer Datenstruktur ( struct sembuf ) zur Manipulation des Semaphors,
der Anzahl der zu manipulierenden Semaphore.
Die Funktion semop() erlaubt oder sperrt den Zugriff
int semop(sema_id, operand, flag)
int sema_id;
struct sembuf *operand;
unsigned flag;

sema_id programminterner Name des Semaphors *operand bezeichnet einen Pointer auf ein Array flag gibt die Anzahl der Semaphore im Satz an
Rueckgabewert:
Fehler -1
sonst 0

struct sembuf
{
short sem_num; /* Nummer des Semaphors im Satz */
int sem_op; /* Operator */
ushort sem_flg; /* Flag */
}

Anmerkung zu DEC Ultrix:
Unter Ultrix ist ist der zweite Parameter nicht (struct sembuf*), sondern (struct sembuf**). Das ist ein Fehler im entsprechenden Header, denn zu übergeben ist (struct sembuf*). Außerdem ist fehlt in den Ultrix Headern die Union semun. Wer sein Programm noch unter anderen Unix-Derivaten (z. B. Linux oder Solaris) übersetzen möchte, wird u. a. auf diese Probleme stoßen. Der folgende Programmauszug kann helfen, diese zu umgehen:

#ifdef __DECCXX

union semun
{
int val;
struct semid_ds *buf;
ushort *array;
};

#define CAST_FOR_DEC (sembuf**)

#else

#define CAST_FOR_DEC

#endif /* __DECCXX */

...

void foo()
{
sembuf op;

...

semop(semID, CAST_FOR_DEC &op, 1);

...
}

__DECCXX is ein Präprozessormakro, das vom C++ von DEC (cxx) vorgegeben ist. Wenn der Präprozessor feststellt, daß diese Makro definiert ist, werden alle Quellcodezeilen und Präprozessoranweisungen übernommen bzw. ausgeführt.

Über die Wahl der Werte des zweiten Parameters kann der Programmierer die Arbeitsweise der Funktion semop() steuern. Der Parameter ist eine Variable vom Typ "Pointer auf Array von struct sembuf Komponenten".

Die Variable enthält drei Komponenten:

sem_num gibt an, welches Semaphor aus dem ausgewählten Satz benutzt werden soll,
sem_op steuert, ob das Semaphor gesetzt oder zurückgesetzt werden soll. sem_op ist eine Zahl, deren Wert auf den Wert des Semaphors addiert wird.
sem_flg gibt an, wie der Prozeß reagiert, wenn das betreffende Semaphor bereits gesetzt ist:
0 --> der Prozeß wartet bis das Semaphor zurückgesetzt wird,
IPC_NOWAIT --> der Aufruf von semop() wird mit einem Fehler abgebrochen und das Programm läuft weiter.
Soll z. B. ein Semaphor mit dem Wert 1 auf 0 gesetzt werden, so muß sem_op den Wert -1 haben. Soll das Semaphor am Ende der kritischen Region zurückgesetzt werden, muß sem_op gleich 1 sein.

So ergeben sich einige Aktivitäten, die in einem Programm durchgeführt werden müssen, bevor die Funktion semop() genutzt werden kann.

struct sembuf feld[1]; /* Array definiert */
struct sembuf *pointer_feld; /* Pointer definiert */
pointer_feld = feld; /* Pointer setzen */

In diesem Beispiel besteht der Semaphorsatz nur aus einem Semaphor und daher besteht das Array feld aus nur einer Komponte vom Typ struct sembuf. Im nächsten Schritt werden die Komponenten der Struktur belegt. Danach kann die Funktion semop() ausgeführt werden.

pointer_feld->sem_num = 0;
pointer_feld->sem_op = -1;
pointer_feld->sem_flg = 0;

return_value = semop(sem_id, pointer_feld, 1);

Wird die Funktion semop() mit obigen Werten aufgerufen, passiert folgendes : semop() prüft, ob der Wert des ersten Semaphors ( Nummer 0 ) größer oder gleich dem Absolutbetrag des Operators von pointer_feld -> sem_op ( hier Wert des Semaphors >= 1 ) ist. Wenn dies erfüllt ist, wird vom Wert des Semaphors der Wert von sem_op subtrahiert, das Semaphor damit auf 0 gesetzt. Wird die Funktion semop() mit sem_op = -1 aufgerufen und ist das Semaphor gesetzt, so wartet der Prozeß solange, bis der sperrende Prozeß das Semaphor freigibt. Alle Prozesse, die auf die Freigabe warten, konkurrieren nun um das Betriebsmittel. Wird dagegen die Komponente sem_flg der Variablen feld auf den Wert IPC_NOWAIT gesetzt ( pointer_feld -> sem_flg = IPC_NOWAIT; ), so wird der Aufruf der Funktion semop() mit einem Fehler abgebrochen und das Programm läuft weiter.

Allgemein gilt:

Ist sem_op < 0, so soll das Semaphor gesperrt werden. Ist der Wert des Semaphors größer oder gleich dem absoluten Wert von sem_op, so gilt das Semaphor als frei. Der Absolutwert von sem_op wird dann vom Wert des Semaphors abgezogen. Ist der Wert des Semaphors aber kleiner als der Absolutbetrag, so gilt das Semaphor als gesperrt und semop() wird solange suspendiert, bis die Ressource wieder freigegeben ist. Ist aber als Flag IPC_NOWAIT gesetzt, so beendet sich die Funktion mit einem Fehler als Returnwert und das Programm kann weiterarbeiten.

Befindet sich der Prozeß in der kritischen Region kann, er auf das Betriebsmittel zugreifen. Diese Phase ist, wie bereits erwähnt, möglichst kurz zu halten. Am Ende seiner Arbeit, innerhalb der kritischen Region, muß der Prozeß das entsrechende Betriebsmittel wieder freigeben. Dazu wird die Funktion semop() erneut aufgerufen. Als Operator wird nun eine 1 übergeben. Diese 1 wird auf den Wert des Semaphors addiert. Das Semaphor hat nun wieder den Wert 1 und andere Prozesse können nun um das betreffende Betriebsmittel konkurrieren.

pointer_feld->sem_op = 1;
return_value = semop(sem_id, pointer_feld, 1);

Allgemein wird mit sem_op > 0 das Semaphor freigegeben. Dazu wird der Wert von sem_op zum Wert des Semaphors addiert.

Das Kontrollieren und Steuern der Semaphore mit der Funktion semctl()
Ein Semaphor wird durch die Datenstrukturen struct sem und struct semid_ds beschrieben. Die Werte dieser Variablen bilden den Status des Semaphors.

Mit der Funktion semctl() kann der Status eines Semaphors kontrolliert werden.

int semctl(sema_id, nummer, command, puffer)
int sema_id;
int nummer;
int command;
union semun
{
int val;
struct semid_ds *buf;
ushort array;
} puffer;

sema_id ist der programminterne Name des Semaphors und wird von semget() als Rueckgabewert geliefert. nummer ist die Nummer des Semaphors im Satz. command ist ein Kontrollkommando und kann einen der folgenden Werte annehmen:

SETVAL setzt Wert des Semaphors
GETVAL liefert Wert des Semaphors
GETPID liefert PID des letzten Prozesses, der auf das Semaphor zugriff.
GETNCNT liefert Anzahl der Prozesse
GETZCNT liefert Anzahl der Prozesse, die auf den Wert 0 warten.
GETALL liefert Werte aller Semaphore im Satz.
SETALL setzt Werte aller Semaphore im Satz.
IPC_STAT liefert Status eines Semaphors
IPC_SET setzt Status eines Semaphors
IPC_RMID löscht Semaphor

puffer ist eine Datenfläche (Variable)

Rückgabewert:
>= 0 : bei Erfolg, abhängig von command:
GETVAL -> Wert von semval;
GETPID -> Wert von sempid;
GETNCNT -> Wert von semncnt;
GETZCNT -> Wert von semzcnt;
-1 : Fehler,
-> ungültige Semaphor-ID;
-> command ungültig;
-> Zugriffsrechte unzureichend;

Die Funktion semctl() wird mit vier Parameter aufgerufen. Der erste Parameter identifiziert das Semaphor. Der zweite Parameter gibt die Nummer des zu bearbeitenden Semaphors an.Das erste Semaphor in einem Satz hat die Nummer 0. Der dritte Parameter enthält ein Kontrollkommando, das die Funktion und Wirkungsweise der Funktion semctl() steuert.

Es gibt zwei Klassen von Kommandos (Operationen):

Status des Semaphors abfragen ( lesen ). Werte des Semaphors werden abgefragt und im vierten Parameter gespeichert oder als Returnwert an das Programm geliefert.
Status der Semaphore ändern ( schreiben ). Werte aus dem vierten Parameter werden gelesen und in die Variable des Semaphors geschrieben.
Der vierte Parameter ist als Variable vom Typ 'union' definiert. Abhängig vom Operator im dritten Parameter wird diese Variable als Integer, Pointer oder Array interpretiert.

Folgende Operationen sind möglich:

Werte verwalten
Der Wert des Semaphors wird mit SETVAL gesetzt. Der Wert wird aus dem vierten Parameter gelesen und wird als Integer inter- pretiert. Mit GETVAL wird der Wert des Semaphors gelesen und als Return- wert von semctl() zurückgeliefert.
Beispiel:
Eine Variable puffer wird definiert und auf den Wert 3 gesetzt. Die Funktion semctl() wird mit dem Operator SETVAL aufgerufen und setzt das Semaphor sema_id auf den Wert 3 ( sema_id ist der Returnwert eines semget()-Aufrufes ).
union semun puffer; /* Definition der Variablen puffer */
puffer.val = 3; /* Speicherfläche wird als */
/* Integer interpretiert */

semctl(sema_id, 0, SETVAL, puffer);

Status abfragen
Hierzu dienen die Kommandos IPC_STAT und IPC_SET. Der vierte Parameter wird als Pointer auf eine Variable vom Datentyp semid_ds interpretiert. Die aktuellen Werte des Semaphors werden in die Variablen geschrieben (IPC_STAT) oder durch die Werte der Variablen ersetzt (IPC_SET).
Achtung: Diese Variable muß definiert werden, der Pointer allein reicht nicht! Sind mehrere Semaphore in einem Satz zusammengefaßt, so wird der vierte Parameter als Array interpretiert (GETALL oder SETALL)
Zugriffsrechte ändern
 
Zuletzt bearbeitet:
Danke, für die gute Antwort. Beschäftigst Du Dich schon länger damit ? :)

Ich hab noch ein paar Fragen:

1.)Wenn ich mehrere Prozesse habe, die versuchen ein Semaphor zu bekommen, dann sollten die ja möglichst versuchen, das selbe zu bekommen. Also meinetwegen Nr. 5. Wenn das jetzt schon besetzt ist, was dann ? Immerhin werden die ja systemweit genutzt. Ist es da überhaupt sinnvoll so eines zu verwenden?

2.)Das mit den Sätzen von Semaphoren hab ich nicht verstanden. Fordere ich nun vom BS ein Semaphor oder einen ganzen Satz an? Ich hab jetzt verstanden, dass man gleich einen ganzen Satz anfordert. Wozu ist das gut und welches aus diesem Satz sollte man benutzen ?

3.)int semop(sema_id, operand, flag)
dieser operand soll nun auf ein Array von struct sembuf zeigen. Also, kann ich gleich mehrere Semaphore setzen, oder wie ist das zu verstehen ?

4.)Das mit dem semop versteh ich noch nicht so ganz. Normalerweise gibt es bei Semaphoren ja .p und .v . Wie ist das hier? kann man hier direkt den internen Wert eintragen?
 
Hab alles verstanden

klingt irgendwie kompliziert.
 
Entschuldige Herbert, aber ich finde nicht genügend Zeit mich in diese Problematik ausreichend (halbes ist nichts ganzes, sag ich immer) reinzufuchsen.
Bin eher auf der User-Seite im MDA-Bereich von aeronautisch-astrophysikalischer Grundlagenforschung tätig und hier aufgrund einer Erkrankung zurzeit stark ins Hintertreffen geraten
.
Aber ich kann dir das SysPgm-Netz der Uni/FH Karlsruhe ans Herz legen, die scheinen hier einen umfangreichen Bestand zu haben.
Da bist du sicherlich besser aufgehoben als hier in unserem "Hobby-Programmierforum". (entschuldige Steffen ;) )

Aber zu der Frage, ob das Semaphor besetzt ist oder frei - es gibt doch nicht nur binäre Semaphore, sondern die ganze Umsetzung baut doch auf ein allgm. Semaphor auf, welches fast unendlich viele Zustände aufweisen kann.
Es ist ein Zähler, der bei Erwerb eines Semaphors (locked) um eins erniedrigt und bei Freigabe (unlocked) um eins erhöht wird. Hat das Semaphor den Wert Null, so muß ein Prozeß, der es erwerben will, auf einen anderen Prozeß warten, der es hochzählt (es kann niemals negativ werden).
 
Danke, Hamlet. Ich werde mich mal umschauen. ...Und mich weiter durch die man-Seiten arbeiten. :)
 
Zurück
Oben