Memory mapping unter Linux

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

Memory mapping unter Linux

Beitragvon MitjaStachowiak » 8. Sep 2017, 14:11 Memory mapping unter Linux

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 8. Sep 2017, 20:58, insgesamt 1-mal geändert.
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon Mathias » 8. Sep 2017, 20:08 Re: Memory mapping unter Linux

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3189
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon MitjaStachowiak » 8. Sep 2017, 21:07 Re: Memory mapping unter Linux

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:
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon Mathias » 10. Sep 2017, 17:44 Re: Memory mapping unter Linux

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3189
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon MitjaStachowiak » 14. Sep 2017, 11:50 Re: Memory mapping unter Linux

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?
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon Warf » 14. Sep 2017, 14:00 Re: Memory mapping unter Linux

Alles zur Shared Memory bekommst du in der ipc Unit
Schau da mal rein
Warf
 
Beiträge: 615
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon marcov » 14. Sep 2017, 15:29 Re: Memory mapping unter Linux

FPC rtl nutzt (fp)mmap ohne file um Memory zu allozieren. Siehe rtl/unix/sysheap.inc
marcov
 
Beiträge: 999
Registriert: 5. Aug 2008, 08:37
Wohnort: Eindhoven (Niederlande)
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk) | 
CPU-Target: 32/64,PPC(+64), ARM
Nach oben

Beitragvon MitjaStachowiak » 14. Sep 2017, 22:08 Re: Memory mapping unter Linux

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...
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon m.fuchs » 14. Sep 2017, 23:17 Re: Memory mapping unter Linux

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
m.fuchs
 
Beiträge: 1670
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.6, FPC 3.0) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon MitjaStachowiak » 15. Sep 2017, 01:06 Re: Memory mapping unter Linux

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.
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon m.fuchs » 15. Sep 2017, 07:46 Re: Memory mapping unter Linux

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
m.fuchs
 
Beiträge: 1670
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.6, FPC 3.0) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon MitjaStachowiak » 15. Sep 2017, 11:20 Re: Memory mapping unter Linux

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.
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

Beitragvon m.fuchs » 15. Sep 2017, 11:49 Re: Memory mapping unter Linux

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
m.fuchs
 
Beiträge: 1670
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.6, FPC 3.0) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon mse » 15. Sep 2017, 13:37 Re: Memory mapping unter Linux

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 17. Sep 2017, 16:47, insgesamt 1-mal geändert.
mse
 
Beiträge: 1676
Registriert: 16. Okt 2008, 09:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.4.2,git master FPC 3.0,fixes_3_0) | 
CPU-Target: x86,x64,ARM
Nach oben

Beitragvon MitjaStachowiak » 17. Sep 2017, 14:47 Re: Memory mapping unter Linux

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?
MitjaStachowiak
 
Beiträge: 320
Registriert: 15. Mai 2010, 12:46
OS, Lazarus, FPC: Win 7, Lazarus 32/64 (Codetyphon-Edition) | 
CPU-Target: 64 bit
Nach oben

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste

porpoises-institution
accuracy-worried