Native IPC-Schlüssel

Die Klassen QSharedMemory und QSystemSemaphore identifizieren ihre Ressource mit einem systemweiten Bezeichner, der als "Schlüssel" bekannt ist. Der Low-Level-Schlüsselwert sowie der Schlüsseltyp werden in Qt mit der Klasse QNativeIpcKey gekapselt. Diese Klasse stellt auch die geeigneten Mittel zur Verfügung, um den Schlüssel mit anderen Prozessen auszutauschen, und zwar mittels QNativeIpcKey::toString() und QNativeIpcKey::fromString().

Qt unterstützt derzeit drei verschiedene Backends für diese beiden Klassen, die mit den in der Aufzählung QNativeIpcKey::Type verfügbaren Werten übereinstimmen.

  • POSIX-Echtzeiterweiterungen (IEEE 1003.1b, POSIX.1b)
  • X/Open System Interfaces (XSI) oder System V (SVr4), jetzt auch Teil von POSIX
  • Windows-Primitive

Wie der Name schon sagt, sind die Windows-Primitive nur auf dem Windows-Betriebssystem verfügbar, wo sie das Standard-Backend sind. Die beiden anderen sind in der Regel beide auf Unix-Betriebssystemen verfügbar. Die folgende Tabelle gibt einen Überblick über die typische Verfügbarkeit seit Qt 6.6:

BetriebssystemPOSIXSystem VWindows
Android
INTEGRITY
QNXJa
macOSJaNormalerweise (1)
Andere Apple-BetriebssystemeJa
Andere Unix-SystemeJaJa
WindowsSelten (2)Ja

Hinweis: 1 Sandboxed macOS-Anwendungen, zu denen alle über den Apple App Store vertriebenen Anwendungen gehören, dürfen keine System V-Objekte verwenden.

Hinweis: 2 Einige GCC-kompatible C-Laufzeiten unter Windows bieten POSIX-kompatible Shared-Memory-Unterstützung, aber dies ist selten. Beim Microsoft-Compiler ist sie immer nicht vorhanden.

Um festzustellen, ob ein bestimmter Schlüsseltyp unterstützt wird, sollten Anwendungen QSharedMemory::isKeyTypeSupported() und QSystemSemaphore::isKeyTypeSupported() aufrufen.

QNativeIpcKey bietet auch Unterstützung für die Kompatibilität mit Qt-Anwendungen vor seiner Einführung. Die folgenden Abschnitte beschreiben die Einschränkungen der Backends, den Inhalt der String-Schlüssel selbst und die Kompatibilität.

Plattformübergreifendes sicheres Schlüsselformat

QNativeIpcKey::setNativeKey() und QNativeIpcKey::nativeKey() handhaben den nativen Low-Level-Schlüssel, der mit den nativen APIs verwendet und mit anderen, nicht-Qt-Prozessen geteilt werden kann (siehe unten für die API). Dieses Format ist in der Regel nicht plattformübergreifend, daher bieten sowohl QSharedMemory als auch QSystemSemaphore eine Funktion, um einen plattformübergreifenden Identifizierungsstring in den nativen Schlüssel zu übersetzen: QSharedMemory::platformSafeKey() und QSystemSemaphore::platformSafeKey().

Die Länge des plattformübergreifenden Schlüssels entspricht auf den meisten Plattformen der eines Dateinamens, ist aber auf Apple-Plattformen auf nur 30 nutzbare Bytes beschränkt (achten Sie auf die UTF-8-Kodierung, wenn Sie Zeichen außerhalb des US-ASCII-Bereichs verwenden). Das Format des Schlüssels ähnelt auch dem einer Dateipfadkomponente, d. h. er sollte keine Zeichen enthalten, die in Dateinamen nicht erlaubt sind, insbesondere nicht diejenigen, die Pfadkomponenten trennen (Schrägstrich und umgekehrter Schrägstrich), mit Ausnahme von Sandbox-Anwendungen auf Apple-Betriebssystemen. Die folgenden Beispiele sind gute Beispiele für plattformübergreifende Schlüssel: "myapp", "org.example.myapp", "org.example.myapp-12345". Beachten Sie, dass es dem Aufrufer obliegt, übergroße Schlüssel zu vermeiden und sicherzustellen, dass der Schlüssel auf der jeweiligen Plattform zulässige Zeichen enthält. Qt wird zu lange Schlüssel stillschweigend abschneiden.

Apple-Sandbox-Beschränkungen: Wenn die Anwendung innerhalb einer Sandbox in einem Apple-Betriebssystem läuft, muss der Schlüssel in einem ganz bestimmten Format vorliegen: <application group identifier>/<custom identifier>. Sandboxing ist für alle Anwendungen, die über den Apple App Store vertrieben werden, obligatorisch. Weitere Informationen finden Sie in der Dokumentation von Apple hier und hier, einschließlich der Frage, wie Sie die Gruppenkennung der Anwendung erhalten.

Natives Schlüsselformat

In diesem Abschnitt wird das Format der nativen Schlüssel der unterstützten Backends beschrieben.

POSIX-Echtzeit

Native Schlüssel ähneln Dateinamen und können jedes Zeichen enthalten, das auch Dateinamen enthalten, außer einem Schrägstrich. POSIX verlangt, dass das erste Zeichen im Schlüsselnamen ein Schrägstrich ist, und lässt unbestimmt, ob weitere Schrägstriche erlaubt sind. Auf den meisten Betriebssystemen ist die Länge des Schlüssels dieselbe wie die eines Dateinamens, aber auf Apple-Betriebssystemen ist sie auf 32 Zeichen begrenzt (dies schließt den ersten Schrägstrich und die abschließende Null ein, so dass nur 30 nutzbare Zeichen möglich sind).

Die folgenden sind gute Beispiele für native POSIX-Schlüssel: "/myapp", "/org.example.myapp", "/org.example.myapp-12345".

QSharedMemory::platformSafeKey() und QSystemSemaphore::platformSafeKey() stellen einfach den Schrägstrich voran. Auf Apple-Betriebssystemen wird das Ergebnis außerdem auf die verfügbare Größe gekürzt.

Windows

Windows-Schlüsseltypen sind NT-Kernelobjektnamen und können bis zu MAX_PATH (260) Zeichen lang sein. Sie sehen wie relative Pfade aus (d. h. sie beginnen nicht mit einem umgekehrten Schrägstrich oder einem Laufwerksbuchstaben), aber im Gegensatz zu Dateinamen unter Windows wird bei ihnen die Groß- und Kleinschreibung beachtet.

Die folgenden sind gute Beispiele für native Windows-Schlüssel: "myapp", "org.example.myapp", "org.example.myapp-12345".

QSharedMemory::platformSafeKey() und QSystemSemaphore::platformSafeKey() fügen ein Präfix ein, um Shared-Memory- bzw. System-Semaphore-Schlüssel zu disambiguieren.

X/Open System Interfaces (XSI) / System V

System-V-Schlüssel haben die Form eines Dateinamens im System und unterliegen daher genau denselben Einschränkungen wie Dateipfade. Sowohl QSharedMemory als auch QSystemSemaphore erstellen diese Datei, wenn sie bei der Erstellung des Objekts nicht vorhanden ist. Wenn die automatische Entfernung deaktiviert ist, kann die Datei auch von QSharedMemory und QSystemSemaphore gemeinsam genutzt werden, ohne dass es zu Konflikten kommt, und sie kann eine beliebige vorhandene Datei sein (z. B. kann es die ausführbare Datei des Prozesses selbst sein, siehe QCoreApplication::applicationFilePath()). Der Pfad sollte ein absoluter sein, um Fehler durch unterschiedliche aktuelle Verzeichnisse zu vermeiden.

QSharedMemory::platformSafeKey() und QSystemSemaphore::platformSafeKey() geben immer einen absoluten Pfad zurück. Wenn die Eingabe bereits absolut war, geben sie ihre Eingabe unverändert zurück. Andernfalls wird ein geeigneter Pfad vorangestellt, in dem die Anwendung normalerweise die Erlaubnis hat, Dateien zu erstellen.

Eigentümerschaft

Shared-Memory- und System-Semaphore-Objekte müssen vor der Verwendung erstellt werden, was mit QSharedMemory::create() oder durch Übergabe von QSystemSemaphore::Create an den Konstruktor erreicht wird.

Auf Unix-Systemen sind die Qt-Klassen, die das Objekt erstellt haben, für das Aufräumen des fraglichen Objekts verantwortlich. Wenn die Anwendung mit diesem C++-Objekt unsauber beendet wird (durch einen Absturz, qFatal(), etc.), kann das Objekt daher zurückbleiben. In diesem Fall kann es vorkommen, dass Anwendungen das Objekt nicht erneut erstellen können und stattdessen an ein vorhandenes Objekt anhängen sollten. Zum Beispiel für QSharedMemory:

if (!shm.create(4096) && shm.error() == QSharedMemory::AlreadyExists)
    shm.attach();

Ein erneutes Anhängen an QSystemSemaphore ist wahrscheinlich unklug, da sich der Tokenzähler in diesem Objekt wahrscheinlich in einem unbekannten Zustand befindet und daher zu Deadlocks führen kann.

POSIX-Echtzeit

Der Besitz von POSIX Realtime-Objekten ist nach dem Muster von Dateien aufgebaut, in dem Sinne, dass sie unabhängig von jedem Prozess existieren, der sie benutzt oder nicht. Qt ist nicht in der Lage festzustellen, ob das Objekt noch in Gebrauch ist, daher wird es beim automatischen Entfernen auch dann entfernt, was das Anhängen an dasselbe Objekt unmöglich macht, aber ansonsten keine Auswirkungen auf bestehende Anhänge hat.

Vor Qt 6.6 hat Qt nie POSIX Realtime-Objekte aufgeräumt, außer unter QNX.

X/Open System Interfaces (XSI) / System V

Es gibt zwei Ressourcen, die von den Qt-Klassen verwaltet werden: die Datei, auf die der Schlüssel verweist, und das Objekt selbst. QSharedMemory verwaltet das Objekt kooperativ: das letzte Attachment ist für das Entfernen des Objekts selbst und dann für das Entfernen der Schlüsseldatei verantwortlich. QSystemSemaphore entfernt das Objekt nur, wenn es QSystemSemaphore::Create übergeben wurde; wenn es die Schlüsseldatei erstellt hat, wird es diese ebenfalls entfernen.

Seit Qt 6.6 ist es möglich, eine der beiden Klassen zu bitten, nicht aufzuräumen.

Windows

Das Betriebssystem ist Eigentümer des Objekts und bereinigt es, nachdem das letzte Handle auf das Objekt geschlossen wurde.

Interoperabilität mit alten Qt-Anwendungen

Die Klasse QNativeIpcKey wurde in Qt 6.6 eingeführt. Vor dieser Version wurden die Backends QSharedMemory und QSystemSemaphore zum Zeitpunkt des eigenen Builds von Qt festgelegt. Für Windows-Systeme war es immer das Windows-Backend. Bei Unix-Systemen wurde standardmäßig das System-V-Backend verwendet, wenn das Konfigurationsskript feststellte, dass es verfügbar war. Wenn es nicht verfügbar war, wurde auf das POSIX-Backend zurückgegriffen. Das POSIX-Backend konnte explizit mit der Option -feature-ipc_posix für das Qt configure-Skript ausgewählt werden; wenn es aktiviert war, wurde das Makro QT_POSIX_IPC definiert.

Qt 6.6 behält die Option des configure-Skripts bei, steuert aber nicht mehr die Verfügbarkeit der Backends. Stattdessen ändert es, was QNativeIpcKey::legacyDefaultTypeForOs() zurückgibt. Anwendungen, die die Kompatibilität beibehalten wollen, müssen ausschließlich diesen Schlüsseltyp verwenden, um die Interoperabilität zu gewährleisten.

Die API in QSharedMemory und QSystemSemaphore hatte das Konzept eines plattformübergreifenden Schlüssels, das nun zugunsten der Verwendung von QSharedMemory::legacyNativeKey() und QSystemSemaphore::legacyNativeKey() veraltet ist. Diese beiden Funktionen erzeugen den gleichen nativen Schlüssel wie die veralteten Funktionen in früheren Versionen. Wenn der alte Code zum Beispiel war:

QSharedMemory shm("org.example.myapplication");
QSystemSemaphore sem("org.example.myapplication");

Es kann aktualisiert werden, um zu sein:

QSharedMemory shm(QSharedMemory::legacyNativeKey("org.example.myapplication"));
QSystemSemaphore sem(QSystemSemaphore::legacyNativeKey("org.example.myapplication"));

Wenn die beiden Anwendungen native Schlüssel ausgetauscht haben, ist es nicht notwendig, den Code zu aktualisieren:

QSharedMemory shm;
shm.setNativeKey(key);

Wenn die ältere Anwendung jedoch einen nativen Schlüssel akzeptiert hat, kann die neue Anwendung platformSafeKey() mit einem zweiten Argument von QNativeIpcKey::legacyDefaultTypeForOs() verwenden.

X/Open System Interfaces (XSI) / System V

Verwenden Sie niemals bestehende Dateien für QSharedMemory Schlüssel, da die alte Qt-Anwendung versuchen könnte, diese zu entfernen. Lassen Sie sie stattdessen von QSharedMemory erstellen.

Interoperabilität mit Nicht-Qt-Anwendungen

Die Interoperabilität mit Nicht-Qt-Anwendungen ist möglich, allerdings mit einigen Einschränkungen:

  • Die Erstellung von Shared-Memory-Segmenten darf nicht rennen
  • QSharedMemory Unterstützung für das Sperren des Segments ist nicht verfügbar

Die Kommunikation mit Nicht-Qt-Anwendungen muss immer über den nativen Schlüssel erfolgen.

QSharedMemory bildet immer das gesamte Segment im Speicher ab. Die Nicht-Qt-Anwendung kann sich dafür entscheiden, nur eine Teilmenge des Segments in den Speicher zu übertragen, ohne dass dies negative Auswirkungen hat.

POSIX-Echtzeit

POSIX Shared Memory kann mit shm_open() geöffnet werden und POSIX System Semaphoren können mit sem_open() geöffnet werden.

Beide Funktionen nehmen einen Parameter name an, der das Ergebnis von QNativeIpcKey::nativeKey() ist, kodiert für Dateinamen mit QFile::encodeName() / QFile::decodeName().

Windows

Windows Shared-Memory-Objekte können mit CreateFileMappingW und Windows System Semaphore-Objekte mit CreateSemaphoreW geöffnet werden. Obwohl der Name beider Funktionen mit "Create" beginnt, sind sie in der Lage, sich an bestehende Objekte anzuhängen.

Der Parameter lpName für diese Funktionen ist das Ergebnis von QNativeIpcKey::nativeKey(), ohne Transformation.

Wenn die Fremdanwendung die Nicht-Unicode-Version dieser Funktionen (mit der Endung "A") verwendet, kann der Name mit QString in 8-Bit umgewandelt werden.

X/Open System Interfaces (XSI) / System V

System V Shared Memory kann mit shmget() und System V System Semaphoren können mit semget() abgefragt werden.

Der Parameter key für eine dieser Funktionen ist das Ergebnis der Funktion ftok(), wenn der von QNativeIpcKey::nativeKey() erhaltene Dateiname mit einem id von 81 oder 0x51 (dem ASCII-Großbuchstaben 'Q') übergeben wird.

System V Semaphor-Objekte können mehrere Semaphoren enthalten, aber QSystemSemaphore verwendet nur die erste (Nummer 0 für sem_num).

Sowohl QSharedMemory als auch QSystemSemaphore entfernen das Objekt standardmäßig mit der Operation IPC_RMID auf shmctl() bzw. semctl(), wenn sie die letzte Anlage sind.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.