1. 什么是 QSharedMemory?
QSharedMemory
?是 Qt 中用于進程間共享內存的類。它允許多個進程共享一塊內存區域,從而避免數據傳輸時的 IO 操作,提高通信速度。通過共享內存,多個進程可以直接讀寫這塊內存,而無需經過文件或網絡傳遞。
QSharedMemory 的核心特點
-
唯一鍵(Key)標識:
-
每塊共享內存通過唯一的鍵(字符串)標識。
-
不同進程通過相同的鍵連接到共享內存。
-
-
線程安全性:
-
提供鎖機制(
lock()
?和?unlock()
)以保護共享內存的讀寫。
-
-
跨平臺支持:
-
Qt 的跨平臺特性使?
QSharedMemory
?可以在不同操作系統上無縫使用。
-
2. QSharedMemory 的常用場景
-
實時數據共享:
-
如傳感器數據、實時日志等需要在多個進程間快速傳遞。
-
-
高性能需求:
-
在頻繁更新的大量數據(如圖像處理、緩存共享)中,通過共享內存減少通信開銷。
-
-
進程間消息傳遞:
-
兩個或多個應用程序之間的簡單數據交換。
-
3. QSharedMemory 的工作流程
共享內存的基本使用可以分為以下幾個步驟:
-
創建共享內存:
-
第一個進程通過?
create(size)
?創建一塊共享內存。 -
分配的大小由數據的存儲需求決定。
-
-
附加到共享內存:
-
其他進程通過?
attach()
?方法連接到已有的共享內存。
-
-
數據讀寫:
-
通過?
lock()
?和?unlock()
?保證線程安全,獲取內存指針后讀寫數據。
-
-
釋放共享內存:
-
調用?
detach()
?斷開與共享內存的連接。
-
4. QSharedMemory 常用函數詳解
以下是?QSharedMemory
?類的常用函數及其作用:
函數名 | 作用 |
---|---|
構造函數 | 創建? |
create(size) | 創建指定大小的共享內存,如果共享內存已存在則返回失敗。 |
attach() | 附加到已有的共享內存,連接成功后可以訪問內存內容。 |
detach() | 斷開與共享內存的連接,并釋放資源(只有最后一個進程斷開時共享內存才會被銷毀)。 |
lock() | 鎖定共享內存,防止其他進程或線程同時訪問數據(用于數據同步)。 |
unlock() | 解鎖共享內存,允許其他進程訪問數據。 |
data() ?/? | 獲取共享內存的指針,用于讀寫數據( |
isAttached() | 檢查當前進程是否已經連接到共享內存。 |
error() ?/? | 獲取最近一次操作的錯誤代碼和描述,便于調試。 |
5. 使用示例:QSharedMemory 實現進程間通信
以下是一個完整的例子,展示如何通過?QSharedMemory
?實現進程間的讀寫通信。
程序1:寫入共享內存
程序1負責創建共享內存并向其中寫入數據。
#include?<QCoreApplication>
#include?<QSharedMemory>
#include?<QDebug>
#include?<QTimer>
#include?<QDateTime>#define?tc(a) QString::fromLocal8Bit(a)int?main(int?argc,?char?*argv[])
{QCoreApplication?a(argc, argv);QSharedMemory?sharedMemory("MySharedMemoryKey");// 創建共享內存,大小為 1024 字節if?(!sharedMemory.create(1024)) {qDebug() << tc("無法創建共享內存:") << sharedMemory.errorString();return-1;}qDebug() << tc("共享內存已創建");// 定時寫入動態數據QTimer timer;QObject::connect(&timer, &QTimer::timeout, [&]() {if?(sharedMemory.lock()) {char?*to =?static_cast<char?*>(sharedMemory.data());QString message = tc("程序1動態消息#") + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");QByteArray byteArray = message.toLocal8Bit();memcpy(to, byteArray.data(), byteArray.size() +?1);?// 寫入動態數據sharedMemory.unlock();qDebug() << tc("成功寫入共享內存:") << message;}?else?{qDebug() << tc("無法鎖定共享內存進行寫入:") << sharedMemory.errorString();}});timer.start(1000);?// 每秒更新一次return?a.exec();
}
程序2:讀取共享內存
程序2連接到共享內存,讀取數據并解析時間戳。
#include?<QCoreApplication>
#include?<QSharedMemory>
#include?<QDebug>
#include?<QTimer>
#include?<QDateTime>#define?tc(a) QString::fromLocal8Bit(a)int?main(int?argc,?char?*argv[])
{QCoreApplication?a(argc, argv);QSharedMemory?sharedMemory("MySharedMemoryKey");// 連接到已有的共享內存if?(!sharedMemory.attach()) {qDebug() << tc("無法連接到共享內存:") << sharedMemory.errorString();return-1;}qDebug() << tc("成功連接到共享內存");// 定時讀取數據QTimer timer;QObject::connect(&timer, &QTimer::timeout, [&]() {if?(sharedMemory.lock()) {constchar?*from =?static_cast<constchar?*>(sharedMemory.constData());QString data = QString::fromLocal8Bit(from);sharedMemory.unlock();// 解析時間戳QString timeStampString = data.split("#").at(1);QDateTime messageTime = QDateTime::fromString(timeStampString,?"yyyy-MM-dd hh:mm:ss.zzz");// 當前時間QDateTime currentTime = QDateTime::currentDateTime();qDebug() << tc("從共享內存讀取到的數據:") << data;// 如果時間戳解析成功,計算時間差if?(messageTime.isValid()) {qint64 timeDifference = messageTime.msecsTo(currentTime);?// 時間差(毫秒)qDebug() << tc("接收到的時間:") << messageTime.toString("yyyy-MM-dd hh:mm:ss.zzz");qDebug() << tc("當前時間:") << currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz");qDebug() << tc("時間差(毫秒):") << timeDifference;}?else?{qDebug() << tc("無法解析時間戳!");}}?else?{qDebug() << tc("無法鎖定共享內存進行讀取:") << sharedMemory.errorString();}});timer.start(1000);?// 每秒讀取一次return?a.exec();
}
6. 注意事項
-
共享內存大小:
-
創建共享內存時,指定的大小必須足夠大以存儲所有數據。
-
-
鎖機制:
-
在操作共享內存前,必須調用?
lock()
?進行鎖定,以避免數據競爭。 -
使用完成后,必須調用?
unlock()
?解鎖。
-
-
錯誤處理:
-
使用?
error()
?和?errorString()
?檢查共享內存的狀態。
-
-
進程退出:
-
調用?
detach()
?確保釋放共享內存資源。
-
7. 總結
QSharedMemory
?是一種高效的進程間通信方式,適用于需要快速傳遞數據的場景。通過本文的講解,您應該能夠掌握?QSharedMemory
?的核心功能及其應用。無論是共享日志、實時數據,還是跨進程消息傳遞,QSharedMemory
?都是一個值得考慮的解決方案。