Galileo Computing < openbook >
Galileo Computing - Bücher zur Programmierung und Softwareentwicklung
Galileo Computing - Bücher zur Programmierung und Softwareentwicklung


'Wie werde ich Unix-Guru' als Buch bestellen
A. Willemer
Wie werde ich UNIX-Guru
I  ANWENDUNG
Know-How für Unix/Linux-User: Einführung, Shell, Befehle, Hilfe, Arbeit mit Dateien, Editoren, Reguläre Ausdrücke, nützliche Tools, Hardware.

II  ADMINISTRATION
Tools, Systemstart, Benutzer verwalten, Hardware konfigurieren, Software installieren, Datensicherung, Tuning, Kernel

III  NETZWERK
Client/Server Systeme, TCP/IP, Routing, IPv6, Internet-Dienste, DHCP, Webserver, Firewalls

IV  DAS X-WINDOW SYSTEM
Die grafische Oberfläche von UNIX einrichten und nutzen

V  PROGRAMMIERUNG VON SHELLSKRIPTEN
Automatisieren von Tasks durch Shell-Skripte.

VI  PERL
Interpreter, Syntax, Variablen, Steuerung, Funktionen, UNIX-Aufrufe, GUIs mit Tk

VII  PROGRAMMIERWERKZEUGE
C-Compiler, Analyse-Tools, CVS, yacc, diff

VIII  UNIX-SYSTEMAUFRUFE
UNIX-Befehle in eigenen Programmen nutzen

IX  LITERATUR
Weiterführende Literatur zu UNIX und LINUX

 
Galileo Computing / <openbook> / "Wie werde ich UNIX-Guru ?"
« Prozessumgebung Prozesse Synchronisation mit Semaphoren »

Unterabschnitte
  • Beispiel

Gemeinsamer Speicher: Shared Memory

Normalerweise sind die Speicherbereiche zweier Prozesse streng getrennt. Der gemeinsame Speicher ermöglicht die Arbeit zweier Prozesse an den gleichen Daten. Neben den hier beschriebenen Prinzipien, sich den Speicher zu teilen, benötigen Sie normalerweise eine Form der Synchronisation, mit der die Prozesse sich darüber austauschen, wann wer auf den Speicher zugreifen darf.

Die Funktion shmget() legt den gemeinsamen Speicher an, bzw. eröffnet ihn.

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);

Der Parameter key ist entweder eine Schlüsselzahl oder IPC_PRIVATE.

Der Parameter shmflg kann die Konstanten IPC_CREAT und IPC_EXCL und neun Berechtigungsbits für den Eigner, die Gruppe und der Welt, aufnehmen. Die Berechtigungen sind von dem Befehl chmod bekannt. Man kombiniert die Werte, indem man sie mit dem senkrechten Strich odert.

Der Rückgabewert ist -1 im Fehlerfall oder die Shared Memory ID, die für die nächsten Aufrufe benötigt wird.

Die Funktion shmat() (shared memory attach) bindet den Speicher ein. Mit shmdt() (shared memory detach) wird die Speicherbindung wieder aufgehoben.

# include <sys/types.h>
# include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

Der Parameter shmid ist die von shmget() ermittelte ID. An den Parameter shmaddr kann eine 0 übergegeben werden, dann sucht sich das System eine passende Stelle. Die shmflg ist 0 oder SHM_RDONLY, wenn der Speicher nur lesend zugegriffen werden soll. Nach shmat() steht der Speicher zur Verfügung und kann wie ein normaler Speicherbereich zugegriffen werden.

Die Fehlermeldung von shmat() ist (leider) -1. Da der Rückgabewert ein Zeiger ist, der nicht mit einer natürlichen Zahl verglichen werden darf, ergeben sich immer Abfragen wie:

myPtr = shmat(shID, 0, 0);
if (myPtr==(char *)-1) 

Mit der Funktion shmctl() werden bestimmte Eigenschaften des gemeinsamen Speichers verwaltet.

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int kommando, struct shmid_ds *buf);

An den Parameter kommando können folgende Konstanten übergeben werden:

[Shared Memory Kontrollkommandos]L|L Konstante & Bedeutung
IPC_STAT & Die Informationen über den Speicher einlesen
IPC_SET & Ändere die Benutzerrechte in mode
IPC_RMID & Markiere das Segment als zerstört

Mit dem Kommandozeilenbefehl ipcs bekommen Sie einen Überblick über die angeforderten Shared Memory Bereiche.

Beispiel

Das Programm one erzeugt einen Shared Memory von 30 Byte und schreibt dort ASCII-Zeichen beginnend mit A hinein.

[Shared Memory one.c]
#include <sys/ipc.h>
#include <sys/shm.h>

#define MAXMYMEM 30

int main(int argc, char **argv)
{
int shID;
char *myPtr;
int i;

/* Shared Memory erzeugen */
    shID = shmget(2404, MAXMYMEM, IPC_CREAT | 0666);
    if (shID >= 0) {
        /* nun holen wir den Speicher */
        myPtr = shmat(shID, 0, 0);
        if (myPtr==(char *)-1) {
            perror("shmat");
        } else {
            /* Speicher ist zugreifbar: füllen! */
            for (i=0; i<MAXMYMEM; i++) {
                myPtr[i] = 'A'+i;
            }
            getchar(); /* Warte mal auf eine Taste */
            /* gebe den Speicher auf */
            shmdt(myPtr);
        }
    } else { /* shmget lief schief */
        perror("shmget");
    }
}

Das Programm two unterscheidet sich wenig von one. Da Programm one den Speicher erzeugt, braucht two das nicht zu tun. two wird einfach den Inhalt des Speichers auslesen und auf dem Bildschirm ausgeben und damit demonstrieren, dass es sich um denselben Speicher handelt.

[Shared Memory two.c]
#include <sys/ipc.h>
#include <sys/shm.h>
#define MAXMYMEM 30

int main(int argc, char **argv)
{
int shID;
char *myPtr;
int i;

/* Existierenden Shared Memory zugreifen */
    shID = shmget(2404, MAXMYMEM, 0666);
    if (shID >= 0) {
        myPtr = shmat(shID, 0, 0);
        if (myPtr==(char *)-1) {
            perror("shmat");
        } else {
            for (i=0; i<MAXMYMEM; i++) {
                putchar(myPtr[i]);
            }
            puts("n");
            shmdt(myPtr);
        }
    } else { /* shmget lief schief */
        perror("shmget");
    }
}

Die Programme brauchen keineswegs parallel zu laufen. Man kann one auch durchlaufen lassen und sieht dann mit dem Befehl ipcs, dass der Shared Memory noch da ist. Um den Speicher zu entsorgen, muss er zerstört werden. Dazu dient das kleine Programm destroy:

[Shared Memory destroy.c]
#include <sys/ipc.h>
#include <sys/shm.h>
#define MAXMYMEM 30

int main(int argc, char **argv)
{
int shID;
char *myPtr;
int i;

/* Shared Memory erzeugen */
    shID = shmget(2404, MAXMYMEM, 0666);
    if (shID >= 0) {
        /* zerstöre den Shared Memory */
        shmctl(shID, IPC_RMID, 0);
    } else { /* shmctl lief schief */
        perror("shmctl");
    }
}

Ein interessantes Experiment zeigt das parallele Starten von one und destroy. Sie starten one auf einem Terminal. Dieses legt den Shared Memory an und bindet ihn ein. Dann wartet das Programm. Nun starten Sie destroy auf der anderen Konsole. Der Aufruf zum Zerstören des Speichers hat stattgefunden. Aber ein Blick auf die Ausgabe von ipcs zeigt, dass der Speicher noch da ist. Erst wenn one mit einem Tastendruck weiterläuft und seinen Speicher wieder mit shmdt() freigegeben hat, zeigt auch ipcs das Verschwinden des Shared Memory.

Bei dem Beispiel wird die Synchronisation der Programme durch den zeitlich unterschiedlichen Start erreicht. Bei einem parallelen Start von one und two wäre es aber denkbar, dass one noch gar nicht damit fertig wäre, die Daten in den Speicher zu schreiben, während two bereits mit dem Auslesen beginnt. Um dies zu verhindern, wird ein weiteres Konzept benötigt, das gewährleisten kann, dass der kritische Bereich nur von einem Programm gleichzeitig bearbeitet wird.

Der Shared Memory bleibt solange erhalten, bis ein Programm in explizit entfernt (s. o.), bis zum nächsten Shutdown oder bis er mit dem Befehl ipcrm explizit gelöscht wird.

gaston> ipcs

--- Shared Memory Segments ----
key        shmid      owner    perms    Bytes    nattch   Status
0x00000964 425987     arnold   666      30       0

--- Semaphore Arrays ----
key        semid      owner    perms      nsems      Status

--- Message Queues ----
key        msqid      owner    perms      used-bytes   messages

gaston> ipcrm shm 425987
resource(s) deleted
gaston>



« Prozessumgebung | Prozesse | Synchronisation mit Semaphoren »
 
 Zum Katalog
Zum Katalog
Wie werde ich UNIX-Guru?
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 UNIX/Linux

PHP 4-Workshop

Einstieg in Python

Perl fürs Web

MySQL 4

GNOME 2.0
 Empfehlung

Einstieg in XML
 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo
Der Service für registrierte Leser:
Zu MyGalileo
Info



Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.
[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de