Wenn es einen Punkt in der Ausführung Ihres Programms gibt, an dem bekannt ist, dass alle Prozesse, die das gemeinsame Speichersegment öffnen müssen, dies bereits getan haben, können Sie die Verknüpfung sicher aufheben. Durch das Aufheben der Verknüpfung wird das Objekt aus dem globalen Namensraum entfernt, aber es bleibt bestehen, solange es mindestens einen Prozess gibt, der seinen Dateideskriptor offen hält. Wenn nach diesem Punkt ein Absturz auftritt, wird der Dateideskriptor automatisch geschlossen und der Referenzzähler wird dekrementiert. Sobald keine offenen Deskriptoren für den nicht verknüpften Shared-Memory-Block mehr übrig sind, wird er gelöscht.
Dies ist im folgenden Szenario nützlich:Ein Prozess erstellt einen gemeinsam genutzten Speicherblock, hebt die Verknüpfung auf und verzweigt sich dann. Das Kind erbt den Dateideskriptor und kann den gemeinsam genutzten Speicherblock verwenden, um mit dem Elternteil zu kommunizieren. Sobald beide Prozesse beendet sind, wird die Sperre automatisch entfernt, da beide Dateideskriptoren geschlossen werden.
Während er nicht verknüpft ist, ist der gemeinsam genutzte Speicherblock für andere Prozesse nicht verfügbar, um ihn zu öffnen. Inzwischen, wenn man shm_open()
verwendet mit demselben Namen wie der nicht verknüpfte Block, würde stattdessen ein neuer und völlig anderer Shared-Memory-Block erstellt.
Ich habe einen Weg gefunden, einen Systembefehl und den Linux-Befehl "fuser" zu verwenden, mit denen die Prozesse aufgelistet werden können, die eine Datei geöffnet haben. Auf diese Weise können Sie überprüfen, ob die Shared-Memory-Datei (befindet sich in /dev/shm") noch verwendet wird, und sie löschen, falls nicht. Beachten Sie, dass die Operationen check / delete / create in einem kritischen Abschnitt zwischen Prozessen eingeschlossen sein müssen Verwenden eines benannten Mutex oder benannten Semaphors oder einer Dateisperre.
std::string shm_file = "/dev/shm/" + service_name + "Shm";
std::string cmd_line = "if [ -f " + shm_file + " ] ; then if ! fuser -s " + shm_file + " ; then rm -f " + shm_file + " ; else exit 2 ; fi else exit 3 ; fi";
int res = system(cmd_line.c_str());
switch (WEXITSTATUS(res)) {
case 0: _logger.warning ("The shared memory file " + shm_file + " was found orphan and is deleted"); break;
case 1: _logger.critical("The shared memory file " + shm_file + " was found orphan and cannot be deleted"); break;
case 2: _logger.trace ("The shared memory file " + shm_file + " is linked to alive processes"); break;
case 3: _logger.trace ("The shared memory file " + shm_file + " is not found"); break;
}
Nein - zumindest unter Linux enthält der Kernel nichts, was dies tun kann. Es liegt an irgendeiner Anwendung, irgendwann shm_unlink() aufzurufen, um ein Shared-Memory-Segment loszuwerden.