ein Kapitel zurück                                           ein Kapitel weiter

Mit der Funktion.......

#include <sys/types.h>
#include <sys/mman.h>

int munmap(caddr_t adresse, size_t laenge);  

... heben sie das Memory Mapped I/O für den spezifisierten Bereich adresse mit laenge Bytes auf. Alle Daten die sie in dem mapped-Speicherbereich verändert haben werden nicht automatisch in die dazugehörige Datei geschrieben. Damit die Daten der zugeordneten Datei im mapped-Speicherbereich aktualisiert werden benötigen wir die Funktion.........

#include <sys/types.h>
#include <sys/mman.h>

int msync(caddr_t adresse, size_t laenge, int flags);  

Die Funktion gibt bei Erfolg 0 und bei Fehler -1 zurück. Folgende Konstanten könne dabei für flag angegeben werden...

  • MS_SYNC - geänderter mapped-Speicherbereich vor Rückkehr der Funktion mysnc synchronisieren
  • MS_ASYNC - geänderter mapped-Speicherbereich baldmöglichst synchronisieren
  • MS_INVALIDATE - dem Systemkern die Entscheidung lassen wann und ob synchronisiert wird

Die Funktion msync benötigen wir wenn Änderungen im mapped-Speicherbereich sofort in die dazugehörenden Datei (auf der Festplatte) geschrieben werden sollen.

Wir wollen ein Programm schreiben womit Daten von der Standarteingabe lesen und die Eingabe in eine Datei schreiben die sie als erstes Argument in der Kommandozeile übergeben. Die Datei auf die wir schreiben bilden wir in unserem Hauptspeicher ab....

/*Download:map4.c*/
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <fcntl.h> #include <time.h> #include <signal.h> #include <string.h> #define USAGE "usage: %s <tmpfile>\n" #ifndef MAPFILE #define MAPFILE 0 /*für nicht BSD-Systeme*/ #endif #define MAPSIZE 64 extern int errno; static volatile sig_atomic_t sflag; static sigset_t signal_neu, signal_alt, signal_leer; char *mapped; void sigfunc1(int); void sigfunc2(int); void signale_mmap(void) { if(signal(SIGSEGV, sigfunc1) == SIG_ERR) { fprintf(stderr, "Konnte signalhandler für SIGSEGV nicht einrichten\n"); exit(0); } if(signal(SIGBUS, sigfunc2) == SIG_ERR) { fprintf(stderr, "Konnte signalhandler für SIGBUS nicht einrichten\n"); exit(0); } /*Wir entfernen alle Signale aus der Signalmenge*/ sigemptyset(&signal_leer); sigemptyset(&signal_neu); /*Wir fürgen die zwei Signal SIGSEGV und SIGBUS zur Signalmenge hinzu*/ sigaddset(&signal_neu, SIGSEGV); sigaddset(&signal_neu, SIGBUS); /*Jetzt setzen wir signal_neu und sichern die noch */ /*aktuelle Signalmaske in signal_alt*/ if(sigprocmask(SIG_BLOCK, &signal_neu, &signal_alt) < 0) exit(0); } void sigfunc1(int sig) { printf("SIGSEGV: Versuch auf einen unerlaubten Speicherbereich zu schreiben\n"); exit(0); } void sigfunc2(int sig) { printf("SIGBUS: Der Speicherbereich ist nicht mehr gültig\n"); exit(0); } int main(int argc, char *argv[]) { int fd; int n,lines=1; char string[MAPSIZE]; if(argc!=2) { fprintf(stderr,USAGE,*argv); exit(1); } signale_mmap() ; if((fd=open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0777))<0) { perror("open"); exit(1); } /*Größe der Datei festlegen*/ lseek(fd, 2*MAPSIZE-1, SEEK_SET); write(fd,"",1); /*mapped-Speicherberreich festlegen*/ if((mapped=(char*)mmap(0,2*MAPSIZE,PROT_WRITE|PROT_READ,MAPFILE|MAP_SHARED,fd,0)) ==(caddr_t )-1) { perror("mmap: "); exit(1); } close(fd); while(1) { n=read(STDIN_FILENO,string,2*MAPSIZE); mapped+=n; /*aktuelle Position im Speicherbereich*/ memcpy(mapped, string, n); msync(mapped,2*MAPSIZE,MS_SYNC); } exit(0); }

Sie können ja mal das Programm ohne msync testen. Wenn sie sich dann die Datei ansehen in der sie geschrieben haben werden sie merken das das Programm auch ohne msync funktioniert. Das liegt an dem Flag MAP_SHARED. Mit diesem Flag wird garantiert das automatisch Aktualisiert wird.

Wollen wir uns nun ein Programm ansehen womit wir Synchronisiert mit dem Elternprozess in den mapped-Speicherbereich schreiben um gleich darauf mit dem Kindprozess zu lesen was unser Elternprozess in den Hauptspeicher geschrieben hat geschrieben hat.....

/*Download:map5.c*/
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <fcntl.h> #include <time.h> #include <signal.h> #include <string.h> #define USAGE "usage: %s <tmpfile>\n" #define MAPSIZE 1024 extern int errno; static volatile sig_atomic_t sflag; static sigset_t signal_neu, signal_alt, signal_leer; void sigfunc1(int); void sigfunc2(int); void signale_mmap(void) { if(signal(SIGSEGV, sigfunc1) == SIG_ERR) { fprintf(stderr, "Konnte signalhandler für SIGSEGV nicht einrichten\n"); exit(0); } if(signal(SIGBUS, sigfunc2) == SIG_ERR) { fprintf(stderr, "Konnte signalhandler für SIGBUS nicht einrichten\n"); exit(0); } /*Wir entfernen alle Signale aus der Signalmenge*/ sigemptyset(&signal_leer); sigemptyset(&signal_neu); /*Wir fügen die zwei Signal SIGSEGV und SIGBUS zur Signalmenge hinzu*/ sigaddset(&signal_neu, SIGSEGV); sigaddset(&signal_neu, SIGBUS); /*Jetzt setzen wir signal_neu und sichern die noch */ /*aktuelle Signalmaske in signal_alt*/ if(sigprocmask(SIG_BLOCK, &signal_neu, &signal_alt) < 0) exit(0); } void sigfunc1(int sig) { printf("SIGSEGV: Versuch auf einen unerlaubten Speicherbereich zu schreiben\n"); exit(0); } void sigfunc2(int sig) { printf("SIGBUS: Der Speicherbereich ist nicht mehr gültig\n"); exit(0); } int main(int argc, char *argv[]) { int fd; pid_t pid; time_t now; char buf[MAPSIZE]; char *mapped, *omap; char *timestring; if(argc!=2) { fprintf(stderr,USAGE,*argv); exit(1); } signale_mmap() ; if((fd=open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0777))<0) { perror("open"); exit(1); } pid=fork(); if(pid==-1) { perror("fork"); exit(1); } if(pid==0) { /* father, writing*/ if((mapped=(char*)mmap(NULL,2*MAPSIZE,PROT_WRITE,MAP_SHARED,fd,0)) ==(void*)-1) { perror("mmap: "); exit(1); } omap=mapped; lseek(fd, MAPSIZE, SEEK_CUR); write(fd,"hallo",6); while(1) { now=time(NULL); timestring=ctime(&now); strcpy(mapped, timestring); mapped+=strlen(timestring); msync(omap,2*MAPSIZE,MS_SYNC); puts("Eltern schreiben in Hauptspeicher\n"); sleep(1); } exit(0); } else { /* child, reading */ if((mapped=(char*)mmap(NULL,2*MAPSIZE,PROT_READ,MAP_SHARED,fd,0))==(void*)-1) { perror("mmap: "); exit(1); } while(1) { sleep(1); strcpy(buf, mapped); mapped+=strlen(buf); printf("Kind ließt aus dem Hauptspeicher : %s\n",buf); } exit(0); } exit(0); /*Hier kommen wir niemals an*/ }

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf