The QSharedMemory and QSystemSemaphore 類使用稱為 Key 的係統範圍標識符,標識其資源。Qt 封裝低級 Key 值及 Key 類型是使用 QNativeIpcKey 類。該類還提供與其它進程交換 Key 的適當手段,通過 QNativeIpcKey::toString () 和 QNativeIpcKey::fromString ().
Qt 目前支持這 2 類的 3 個截然不同後端,匹配值可用於 QNativeIpcKey::Type 枚舉。
顧名思義,Windows 原語隻可用於 Windows 操作係統,在哪裏它們是默認後端。其它 2 個通常可用於 Unix 操作係統。下錶提供從 Qt 6.6 起的典型可用概述:
| 操作係統 | POSIX | 係統 V | Windows |
|---|---|---|---|
| Android | |||
| INTEGRITY | |||
| QNX | Yes | ||
| macOS | Yes | 通常 (1) | |
| 其它 Apple OS | Yes | ||
| 其它 Unix 係統 | Yes | Yes | |
| Windows | 不常 (2) | Yes |
注意: 1 沙盒 macOS 應用程序,包括憑藉 Apple App Store 分發的所有應用程序,不可以使用係統 V 對象。
注意: 2 Windows 中的某些 GCC 兼容 C 運行時提供瞭兼容 POSIX (便攜式操作係統接口) 的共享內存支持,但這很罕見。采用微軟編譯器,始終缺席。
要確定是否支持給定鍵類型,應用程序應該調用 QSharedMemory::isKeyTypeSupported() 和 QSystemSemaphore::isKeyTypeSupported()。
QNativeIpcKey 還提供瞭 Qt 應用程序兼容性支持,在引入之前。以下章節將詳細介紹後端的局限性、字符串鍵本身的內容、及兼容性。
QNativeIpcKey::setNativeKey () 和 QNativeIpcKey::nativeKey () handle the low-level native key, which may be used with the native APIs and shared with other, non-Qt processes (see below for the API). This format is not usually cross-platform, so both QSharedMemory and QSystemSemaphore provide a function to translate a cross-platform identifier string to the native key: QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey().
The length of the cross-platform key on most platforms is the same as that of a file name, but is severely limited on Apple platforms to only 30 usable bytes (be mindful of UTF-8 encoding if using characters outside the US-ASCII range). The format of the key is also similar to that of a file path component, meaning it should not contain any characters not allowed in file names, in particular those that separate path components (slash and backslash), with the exception of sandboxed applications on Apple operating systems. The following are good examples of cross-platform keys: "myapp", "org.example.myapp", "org.example.myapp-12345". Note that it is up to the caller to prevent oversized keys, and to ensure that the key contains legal characters on the respective platform. Qt will silently truncate keys that are too long.
Apple 沙盒局限性:
if the application is running inside of a sandbox in an Apple operating system, the key must be in a very specific format:
<application group identifier>/<custom identifier>
. Sandboxing is implied for all applications distributed through the Apple App Store. See Apple's documentation
here
and
here
for more information, including how to obtain the application's group identifier.
本節將詳細介紹支持後端的本機鍵格式。
Native keys resemble file names and may contain any character that file names do, except for a slash. POSIX requires the first character in the key name to be a slash and leaves undetermined whether any additional slashes are permitted. On most operating systems, the key length is the same as a file name, but it is limited to 32 characters on Apple operating systems (this includes the first slash and the terminating null, so only 30 usable characters are possible).
The following are good examples of native POSIX keys: "/myapp", "/org.example.myapp", "/org.example.myapp-12345".
QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey() simply prepend the slash. On Apple operating systems, they also truncate the result to the available size.
Windows 鍵類型是 NT
內核對象名
且可能達到
MAX_PATH
(260) 個長度字符。它們看起來像相對路徑 (也就是說,它們不以 / 反斜杠或驅動器字母開頭),但不像 Windows 文件名,它們區分大小寫。
以下是 Windows 本地鍵的很好範例:myapp、org.example.myapp、org.example.myapp-12345。
QSharedMemory::platformSafeKey() 和 QSystemSemaphore::platformSafeKey() 插入前綴以分彆消除共享內存和係統信號量的歧義。
System V keys take the form of the name of a file in the system, and thus have the exact same limitations as file paths do. Both QSharedMemory and QSystemSemaphore will create this file if it does not exist when creating the object. If auto-removal is disabled, it may also be shared between QSharedMemory and QSystemSemaphore without conflict and can be any extant file (for example, it can be the process executable itself, see QCoreApplication::applicationFilePath ()). The path should be an absolute one to avoid mistakes due to different current directories.
QSharedMemory::platformSafeKey() and QSystemSemaphore::platformSafeKey() always return an absolute path. If the input was already absolute, they will return their input unchanged. Otherwise, they will prepend a suitable path where the application usually has permission to create files in.
Shared memory and system semaphore objects need to be created before use, which is accomplished with QSharedMemory::create () 或通過傳遞 QSystemSemaphore::Create 給構造函數,分彆。
On Unix systems, the Qt classes that created the object will be responsible for cleaning up the object in question. Therefore, if the application with that C++ object exits uncleanly (a crash, qFatal (), etc.), the object may be left behind. If that happens, applications may fail to create the object again and should instead attach to an existing one. For example, for QSharedMemory :
if (!shm.create(4096) && shm.error() == QSharedMemory::AlreadyExists) shm.attach();
Re-attaching to a QSystemSemaphore is probably unwise, as the token counter in it is probably in an unknown state and therefore may lead to deadlocks.
POSIX Realtime object ownership is patterned after files, in the sense that they exist independent of any process using them or not. Qt is unable to determine if the object is still in use, so auto-removal will remove it even then, which will make attaching to the same object impossible but otherwise not affecting existing attachments.
Prior to Qt 6.6, Qt never cleaned up POSIX Realtime objects, except on QNX.
There are two resources managed by the Qt classes: the file the key refers to and the object itself. QSharedMemory manages the object cooperatively: the last attachment is responsible for removing the object itself and then removing the key file. QSystemSemaphore will remove the object if and only if it was passed QSystemSemaphore::Create ; additionally, if it created the key file, it will remove that too.
從 Qt 6.6 起,要求不清理任一類是可能的。
操作係統擁有對象,並清理對象在關閉其最後一個句柄後。
The
QNativeIpcKey
類是在 Qt 6.6 引入的。在此版本之前,
QSharedMemory
and
QSystemSemaphore
backends were determined at the time of Qt's own build. For Windows systems, it was always the Windows backend. For Unix systems, it defaulted to the System V backend if the configuration script determined it was available. If it was not available, it fell back to the POSIX one. The POSIX backend could be explicitly selected using the
-feature-ipc_posix
option to the Qt configure script; if it was enabled, the
QT_POSIX_IPC
macro would be defined.
Qt 6.6 retains the configure script option but it no longer controls the availability of the backends. Instead, it changes what QNativeIpcKey::legacyDefaultTypeForOs () will return. Applications that need to retain compatibility must use this key type exclusively to guarantee interoperability.
The API in both QSharedMemory and QSystemSemaphore had the concept of a cross-platform key, which is now deprecated in favor of using QSharedMemory::legacyNativeKey() and QSystemSemaphore::legacyNativeKey(). Those two functions produce the same native key as the deprecated functions did in prior versions. If the old code was for example:
QSharedMemory shm("org.example.myapplication"); QSystemSemaphore sem("org.example.myapplication");
It can be updated to be:
QSharedMemory shm(QSharedMemory::legacyNativeKey("org.example.myapplication")); QSystemSemaphore sem(QSystemSemaphore::legacyNativeKey("org.example.myapplication"));
If the two applications exchanged native keys, there is no need to update code such as:
QSharedMemory shm; shm.setNativeKey(key);
Though if the older application did accept a native key, the new one may opt to use
platformSafeKey()
with a second argument of
QNativeIpcKey::legacyDefaultTypeForOs
().
從不使用現有文件對於 QSharedMemory keys, as the old Qt application may attempt to remove it. Instead, let QSharedMemory create it.
與非 Qt 應用程序互操作是可能的,但有一些局限性:
與非 Qt 應用程序的通信,必須始終透過本機鍵。
QSharedMemory 始終把整段映射到內存。非 Qt 應用程序可以選擇隻把其子集映射到內存,沒有不良影響。
POSIX 共享內存的打開可以使用 shm_open() 和 POSIX 係統信號量的打開可以使用 sem_open() .
這 2 函數接受
name
參數,也就是結果對於
QNativeIpcKey::nativeKey
(),編碼文件名使用
QFile::encodeName
() /
QFile::decodeName
().
Windows 共享內存對象可以打開使用 CreateFileMappingW and Windows system semaphore objects can be opened using CreateSemaphoreW . Despite the name of both functions starting with "Create", they are able to attach to existing objects.
The
lpName
parameter to those functions is the result of
QNativeIpcKey::nativeKey
(), without transformation.
If the foreign application uses the non-Unicode version of those functions (ending in "A"), the name can be converted to and from 8-bit using QString .
係統 V 共享內存的獲得可以使用 shmget() and System V system semaphores can be obtained using semget() .
The
key
parameter to either of those functions is the result of the
ftok()
function when passed the file name obtained from
QNativeIpcKey::nativeKey
() with an
id
of 81 or 0x51 (the ASCII capital letter 'Q').
System V semaphore objects may contain multiple semaphores, but
QSystemSemaphore
only uses the first one (number 0 for
sem_num
).
Both
QSharedMemory
and
QSystemSemaphore
default to removing the object using the
IPC_RMID
operation to
shmctl()
and
semctl()
respectively if they are the last attachment.