Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Linux, Systemprogrammierung C C++ C/C++ ANSI C Linux Linuxsystemprogrammierung Memory Mapped I/O mmap Linuxsystemprogrammieren Memory Mapped I/O mmap 9. Fortgeschrittene Ein/Ausgabe

9.3. Memory Mapped I/O - Weiter Funktionen           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Mit der Funktion ...

int mprotect(const void *addresse, size_t len, int protect);

...können Sie den Schutz für den mapped-Speicherbereich adresse mit der Größe len Bytes verändern. Für protect können Sie eine der vier Konstanten PROT_READ, PROT_WRITE, PROT_EXEC oder PROT_NONE angeben.

Um zu vermeiden, dass bei Mangel an Hauptspeicher, Speicherbereiche auf die Festplatte ausgelagert wird (zu erkennen mit dem Befehl ps x in der Sparte STAT mit der Abkürzung SW für Swap), kann man bestimmte Bereiche im RAM sperren. Das macht speziell bei Zeitkritischen Aufgaben Sinn. Leider sind die nun folgenden Funktionen nur als root durchführbar.

Um einen bestimmten Speicherbereich zu sperren haben wir die Funktion ...

int mlock(caddr_t adresse, size_t laenge);

Das Gegenstück zur Funktion mlock(), um den Speicherbereich wieder freizugeben ist ...

int munlock(caddr_t adresse, size_t laenge);

Wenn Sie den gesamten Adressraums des Prozesses Sperren wollen, können Sie die Funktion ...

int mlockall(int flags);

...verwenden. Als flags können Sie dabei folgende Konstanten verwenden ...

Das Gegenstück zum Aufheben der Sperre lautet ...

int munlockall(void);

Alle Funktionen liefern bei Erfolg 0 zurück und bei Fehler -1.

9.4. Memory Mapped I/O - /dev/zero und /dev/mem           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

/dev/zero
Einen besonderen Status bei den Memory Mapped I/O, besitzt die Datei /dev/zero. Mit der Datei /dev/zero ist es möglich zwischen zwei Verwandten Prozessen zu kommunizieren. Der Vorteil an dieser Methode ...

if((fd=open("/dev/zero", O_RDWR)) < 0)
  {/*Fehler........*/};
memoin=mmap(0,8192......);

...ist der, dass keine neue Datei mit dem Memory Mapped Aufruf mmap() erstellt werden muss.

Folgendes geschieht bei diesem Aufruf und ist zu beachten ...

/dev/mem
Ich möchte Ihnen hierzu eine Methode zeigen, mit der Sie auf einen bestimmten Speicherbereich Ihres Hauptspeichers (RAM) Memory Mapped I/O anwenden können.

Ich übernehme für diese Methode keine Verantwortung wenn Ihr Betriebsystem nicht mehr startet, Datenverluste entstehen oder sonst irgendeine negativ Auswirkende Form von Laufzeitverhalten, die sich daraus resultieren könnte!!!

Die Dateien /dev/mem und /dev/kmem bilden den Arbeitsspeicher des Rechners ab. Beide Devices sind zeichenorientiert. Auf diese Devices greifen nur spezielle Programme wie free oder ps zu. Das direkte Lesen und Schreiben im Arbeitsspeicher des Rechners muss den Benutzern immer verboten sein.

Soviel zu /dev/mem. Jetzt müssen Sie Linux, besser gesagt Lilo erst mal Konfigurieren. Öffnen Sie die Datei ...

lilo.config

...was dann in etwa so aussehen könnte...

..........
image = /vmlinuz
root = /dev/hda6
label = linux
..............

Darin tragen Sie jetzt zusätzlich ein ...

..........
image = /vmlinuz
append = "mem=63m"
root = /dev/hda6
label = linux
..............

Ich gehe jetzt mal davon aus, Ihr System ist mit 64MB Arbeitspeicher ausgerüstet. Mit dem Eintrag ...

append = "mem=63m"

...stehen Ihnen nun für Linux 63MB Arbeitsspeicher zur Verfügung. Somit haben Sie automatisch 1MB des Arbeitspeichers für das Memory Mapped reserviert. Starten Sie Ihren Rechner neu, damit die neue Konfiguration aktiviert wird.

Jetzt will ich Ihnen nur noch schnell anhand eines simplen Beispiels zeigen, wie Sie auf das 63. Megabyte des Arbeitspeichers (RAM) zugreifen können ...

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>

/*Damit definieren wir die Startadresse im Arbeitspeicher
  63 steht für die Startadresse des 63. MB im Arbeitspeicher*/
#define RAM_ADDRESS (63*0x100000)
/*Wir reservieren 16386 Bytes von dem einen MB*/
#define ALLOCA 16384

int main()
{
  char *mem_ptr;
  int fd, i;
  if ((fd=open("/dev/mem", O_RDWR)) < 0)
   {
     fprintf(stderr, "Fehler beim öffnen von /dev/mem\n");
     exit(1);
   }
  mem_ptr = (char *)mmap(0, ALLOCA, PROT_READ | PROT_WRITE,
                                    MAP_FILE | MAP_SHARED, f, ADDRESS);

  for (i=0; i < ALLOCA; i++)
     mem_ptr[i]=i; /*Wir befüllen den Speicherbereich mit Zahlen*/

/* Wir lesen die Zahlen aus dem Hauptspeicher wieder aus */
  for (i=0; i < ALLOCA; i++)
     printf("%d\n",mem_ptr[i]);
/*Wir geben den Speicherplatz wieder frei*/
  munmap(mem_pointer, ALLOCA);
  return 0;
}

Normalerweise dürften Sie das Programm nur als root ausführen können. Ich will es jetzt dabei belassen, denn alles andere was tiefer ins Detail geht gehört schon zum Kernel Hacking. Ein Gebiet wo ich mich übrigens nicht sehr gut auskenne ...

Weiter mit 10. Semigrafik (curses.h)