Memory mapping unter Linux

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Hy,
ich versuche verzweifelt, ein memmory mapping unter Linux zu erstellen. Also es gibt wohl zwei verschiedene Techniken dafür: shmget und POSIX' mmap. Das Erstere sieht so aus:

Code: Alles auswählen

 
{$IFDEF Unix}
 inf.isFirstProcess := false;
 mmfHandle := shmget(PInteger(@mmfName[1])^, SizeOf(TMapInfo), 0777);
 if (mmfHandle < 0) then begin
  inf.isFirstProcess := true;
  mmfHandle := shmget(PInteger(@mmfName[1])^, SizeOf(TMapInfo), IPC_CREAT or 0777);
  if (mmfHandle < 0) then begin Err.log(Err.ERROR, 'Cannot create MMF!'); Application.Terminate; end;
 end;
 mmf := shmat(mmfHandle, nil, 0777);
{$ENDIF}
if (inf.isFirstProcess) then fillChar(mmf^, SizeOf(TMapInfo), #0)
 

Funzt aber nur, wenn das Programm als root läuft. Angeblich soll es für normale user gehen, wenn man das 0777 in den flags benutzt (also so wie oben), aber defakto kommt trotzdem ein Fehler und ich muss mein Programm bzw. Lazarus immer über sudo [...] starten. (doof!)

Das Zweitere konnte ich nicht testen. Man braucht für mmap bzw. Fpmmap vorher shm_open aber das entsprechende Fpshm_open gibt es einfach nicht und ich weiß nicht, wie ich die Linux-API an dieser Stelle nativ ansprechen kann :(

Wer weiß Rat?
Zuletzt geändert von MitjaStachowiak am Fr 8. Sep 2017, 21:58, insgesamt 1-mal geändert.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Memory mapping unter Linux

Beitrag von Mathias »

Suche mal unter raspi gpio, bei diesem Wiki, wird auch ein memoryzugriff gemacht, da die gpio auch im ram abgebildet werden.

Vielleicht hilft dies weiter. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Hier http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi?

Die nehmen da aber einfach FpOpen und nicht shm_open, was bedeutet, es wird in eine Datei geschrieben. Ich will ja ohne Datei auskommen, also alleine im Arbeitsspeicher arbeiten... Oder ist das FpOpen irgendwie virtuell und wenn man eine nicht-existierende Datei angibt, ist es im RAM? :shock:

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Memory mapping unter Linux

Beitrag von Mathias »

Dies könnte dir noch weiter helfen http://pronix.linuxdelta.de/C/Linuxprog ... tel9.shtml
Es ist zwar in C++, aber vielleicht könnte man es umschreiben.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Danke. Der nimmt da aber einfach argv[1] als Dateiname. Das sagt mir noch nicht, wo ich die Datei sinnvoller Weise anlege, ob diese existieren muss oder ob bzw. wann der Inhalt von Datei und Speicher synchronisiert werden... Wenn ich nach "mmap without file" suche, werde ich immer auf shm_open verwiesen.

Habe also versucht, shm_open in Lazarus zu verwenden. Das ist in der sys/mman.h wie folgt definiert:

Code: Alles auswählen

extern int shm_open (const char *__name, int __oflag, mode_t __mode);

Ich sehe aber nicht, was extern hier bedeutet. Es muss doch der Name irgend einer library angegeben werden. Welche wäre das?

Die Funktion Fpmmap ist mit external name 'FPC_SYSC_MMAP' deklariert. Was bedeutet das? Wie würde das für shm_open aussehen?

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Memory mapping unter Linux

Beitrag von Warf »

Alles zur Shared Memory bekommst du in der ipc Unit
Schau da mal rein

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Memory mapping unter Linux

Beitrag von marcov »

FPC rtl nutzt (fp)mmap ohne file um Memory zu allozieren. Siehe rtl/unix/sysheap.inc

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Wie oben beschrieben braucht das Mapping aus der ipc-Unit root-Rechte. Ich habe keinen Weg gefunden, dass es ohne root geht.

Der Code aus der Sysheap.inc benutzt

Code: Alles auswählen

Fpmmap(nil,Size,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0);
Das ist interessant, da man ohne den open-Befehl und folglich ohne Datei auskommt. Jedoch gibt es ohne open keine Möglichkeit für den anderen Prozess, dem System zu signalisieren, dass er den selben Speicher will. Daher dürfte das nicht auf MAP_SHARED übertragbar sein...

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von m.fuchs »

Was ist denn der Hintergrund deiner Frage, also was willst du bewerkstelligen? In einem anderen Thread hast du was von Datenaustausch zwischen zwei Programmen geschrieben. Ist das der gleiche Fall, magst du ein wenig mehr dazu erzählen?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Du hast es erfasst :mrgreen:

Also ich habe eine Programmkomponente, die erfahrungsgemäß nicht zuverlässig funktioniert und in einem zweiten Prozess laufen muss. Da ich unter Linux die Gui dieser Komponente nicht in's Hauptprogramm einbetten kann, bin ich dazu übergegangen, dort wirklich nur funktionalen Code abzuarbeiten. Das Programm startet sich selbst ein zweites mal mit entsprechendem Parameter, der bewirkt, dass kein Application.irgendwas aufgerufen wird, sondern nur eine Endlosschleife läuft, die Befehle aus dem MemoryMaping abarbeitet. Im Prinzip funktioniert das schon, jedenfalls unter Windows. Unter Linux bekomme ich dieses MemoryMapping nicht richtig zum laufen.

Ich brauche also ein Äquivalent zu Windows' OpenFileMapping bzw. MapViewOfFile.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von m.fuchs »

Wie wäre es denn mit einem ganz anderen Ansatz anstelle des Memory-Mapping? Zum Beispiel eine kleine REST-API über die der Datenaustausch vollzogen wird. Oder noch besser, die Unzuverlässigkeit der einen Komponente abstellen oder wenigstens absichern.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

Joa. Aber welche Technik nutzt dann die REST-API, um Daten auszutauschen? Es soll ja auch auf Windows und Linux einigermaßen homogen funktionieren. Mit dem Memory Maping tut es das ja, ich habe nur ein paar Fallunterscheidungen beim Einbinden des Mappings. Das funktiuoniert ja auch - ich will nur die root-Rechte loswerden, die der Code im ersten Beitrag braucht, aber trotzdem auch keine physische Datei anlegen bzw. wieder löschen müssen, damit mmap geht.

Außerdem will ich Linux etwas unterstützen, denn es ist schon ein Nachteil dieses Betriebssystems, dass Dinge, die mit der Windows-API selbstverständlich sind, in Linux stundenlanges Lesen von verschiedenstsprachigen Forenbeiträgen erfordern und am Ende ist im jeweilligen Compiler ein bestimmer Befehl (wie shm_open) nicht implementiert. Der muss offenbar über einen Syscall ausgeführt werden, aber ich weiß nicht, wie ich das machen muss.

Für mein aktuelles Projekt wären Root-Rechte als Workaround in Ordnung. Ich will das Problem aber lösen, auch damit andere nicht an der gleichen Stelle hängen bleiben 8)

Den Fehler zu suchen, habe ich aufgegeben. Es ist das altbekannte Bug, dass http_send bei Verwendung von https manchmal (damit meine ich bei jedem 10.000 Request) abschmiert. Umgekehrt greift der Hauptprozess auf diverse Hardware zu und man weiß ja, wie toll manche Treiber von no-name-Sensoren arbeiten. Auch hier ist zu erwarten, dass irgendwann eine Komponente nicht zuverlässig läuft. In diesem Fall könnte der Zweitprozess der Hauptprozess neu starten, damit die Erfassung nicht bis zum nächsten Neustart des Systems hängt. Die robusteste Lösung, die ich bislang gefunden habe, ist, dass Hauptprozess und Zweitprozess jezweils GetTickCounts in das Memory Mapping schreiben. Wenn ein Prozess nichts mehr tut, kann der andere den neu starten. Das ganze in einem Prozess mit mehreren Threads zu implementieren, hat sich als unbrauchbar erwiesen, da das Beenden eines Threads via Systembefehle oft auch zum Absturz des Prozesses fürt.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von m.fuchs »

MitjaStachowiak hat geschrieben:Joa. Aber welche Technik nutzt dann die REST-API, um Daten auszutauschen?

Das gute alte HTTP :D
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Memory mapping unter Linux

Beitrag von mse »

Auf Linux sind shm_open() und shm_unlink() in der librt. mselibc hat die Definitionen:
https://gitlab.com/mseide-msegui/mseide ... mon/kernel
Um dein Problem zu lösen könntest du auch einen robusten guardian Prozess aufsetzen der die Einzelprozesse startet und bei Abstürzen auf das SIGCHLD reagiert. Dazu braucht es noch einen Watchdog der ebenfalls im guardian via pipe implementiert werden könnte.
Zuletzt geändert von mse am So 17. Sep 2017, 17:47, insgesamt 1-mal geändert.

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 394
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Memory mapping unter Linux

Beitrag von MitjaStachowiak »

http zur inter-prozess-kommunikation ist irgendwie nicht der richtiger Weg, finde ich. Es soll hier ja nicht über Netzwerk laufen. Naja, der Upload-Priozess nutzt https und ich habe dort ein quasi stateless protokoll implementiert... Aber anderes Thema :mrgreen:

Die Definition aus der mselibc lässt sich schon mal kompilieren. Allerdings bekomme ich immer -1 als Handle:

Code: Alles auswählen

mmfName : AnsiString = '/MeinProgramm'; // habe es mit und ohne / versucht; auch zum Test mal eine existierende Datei angegeben
mmfHandle := shm_open(PCChar(@mmfName[1]), O_RDWR or O_CREAT, S_IRUSR or S_IWUSR);


Hast du ein Beispiel dazu?
Zuletzt geändert von MitjaStachowiak am Di 9. Jan 2018, 17:56, insgesamt 2-mal geändert.

Antworten