当前位置:   article > 正文

【C++】Windows下共享内存加信号量实现进程间同步通信_信号量 windows

信号量 windows

目录

一,函数清单

1.CreateFileMapping 方法

2.OpenFileMapping 方法

3.MapViewOfFile 方法

4.UnmapViewOfFile 方法

5.CreateSemaphore 方法

6. OpenSemaphore 方法

7.WaitForSingleObject 方法

8.ReleaseSemaphore 方法

9.CloseHandle 方法

10.GetLastError 方法

二,单共享内存单信号量-进程间单向通信

共享内存管理文件实现 

A进程调用接口实现写操作

B进程调用接口实现读操作

三,单共享内存双信号量-进程间单向通信

共享内存管理文件实现

A进程调用接口实现写操作

B进程调用接口实现读操作

四,双共享内存双信号量-进程间双向通信


一,函数清单

1.CreateFileMapping 方法

  1. HANDLE CreateFileMapping(
  2. [in] HANDLE hFile,
  3. [in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  4. [in] DWORD flProtect,
  5. [in] DWORD dwMaximumSizeHigh,
  6. [in] DWORD dwMaximumSizeLow,
  7. [in, optional] LPCWSTR lpName
  8. );

功能

  • 创建或打开命名或未命名的共享内存对象。

参数

  • hFile:创建共享内存则设置为 INVALID_HANDLE_VALUE,并且还必须为 dwMaximumSizeHigh 和 dwMaximumSizeLow 参数中的文件映射对象指定大小
  • lpFileMappingAttributes:共享内存对象的安全属性,通常设置为 NULL,则子进程无法继承句柄,并且共享内存对象获取默认的安全描述符。
  • flProtect:指定共享内存对象的访问方式。通常设置为 PAGE_EXECUTE_READWRITE,表示可进行只读、写入复制、读/写或执行访问。
  • dwMaximumSizeHigh:高位字节大小,通常设置为0。
  • dwMaximumSizeLow:地位字节大小,设置共享内存段的大小。
  • lpName:共享内存对象的标识名称。

返回值

  • 如果函数成功,则返回值是新创建的共享内存对象的句柄。
  • 如果该对象在函数调用之前存在,则函数将返回现有对象的句柄 (其当前大小,而不是指定的大小) , GetLastError 返回 ERROR_ALREADY_EXISTS
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

2.OpenFileMapping 方法

  1. HANDLE OpenFileMapping(
  2. [in] DWORD dwDesiredAccess,
  3. [in] BOOL bInheritHandle,
  4. [in] LPCWSTR lpName
  5. );

功能

  • 打开命名共享内存对象。

参数

  • dwDesiredAccess:对共享内存对象的访问方式。用于共享内存段的保护,通常设置为 FILE_MAP_ALL_ACCESS,可执行所有访问权限。
  • bInheritHandle:如果此参数为 TRUE, 则 CreateProcess 函数创建的进程可以继承句柄;否则,无法继承句柄。
  • lpName:要打开的共享内存对象的标识名称。

返回值

  • 如果函数成功,则返回值是指定共享内存对象的打开句柄。
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

3.MapViewOfFile 方法

  1. LPVOID MapViewOfFile(
  2. [in] HANDLE hFileMappingObject,
  3. [in] DWORD dwDesiredAccess,
  4. [in] DWORD dwFileOffsetHigh,
  5. [in] DWORD dwFileOffsetLow,
  6. [in] SIZE_T dwNumberOfBytesToMap
  7. );

功能

  • 将共享内存映射到调用进程的地址空间。

参数

  •  hFileMappingObject:共享内存对象的句柄。 CreateFileMapping 和 OpenFileMapping 函数返回此句柄。
  • dwDesiredAccess:对共享内存对象的访问方式,通常指定为FILE_MAP_ALL_ACCESS,表示可读可写。
  • dwFileOffsetHigh:高位字节大小,通常设置为0。
  • dwFileOffsetLow:地位字节大小,通常设置为0。
  • dwNumberOfBytesToMap:要映射到共享内存段的字节数。 

返回值

  • 如果函数成功,则返回值为共享内存段的起始地址。
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

4.UnmapViewOfFile 方法

  1. BOOL UnmapViewOfFile(
  2. [in] LPCVOID lpBaseAddress
  3. );

功能

  • 从调用进程的地址空间取消映射共享内存段。

参数

  • lpBaseAddress:指向要取消映射的共享内存指针。此值必须与上一次调用MapViewOfFile 函数返回的值相同。

返回值

  • 如果该函数成功,则返回值为非零值。
  • 如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。

5.CreateSemaphore 方法

  1. HANDLE CreateSemaphore(
  2. [in, optional] LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  3. [in] LONG lInitialCount,
  4. [in] LONG lMaximumCount,
  5. [in, optional] LPCWSTR lpName
  6. );

功能

  • 创建或打开命名或未命名的信号量对象。

参数

  • lpSemaphoreAttributes:信号量安全特征。通常指定为 NULL,但子进程无法继承句柄。
  • lInitialCount:信号量对象的初始可使用资源数目。 此值必须>=0,并且<=lMaximumCount。如果设置为0,信号量为未触发状态。
  • lMaximumCount:信号量对象的最大资源计数。 此值必须大于零。
  • lpName:信号量对象的名称。各进程实现同步会用到该名称。

返回值

  • 如果函数成功,则返回值是信号量对象的句柄。
  • 如果在函数调用之前存在相同命名的信号量对象,则函数将返回现有对象的句柄,GetLastError 返回 ERROR_ALREADY_EXISTS
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

6. OpenSemaphore 方法

  1. HANDLE OpenSemaphore(
  2. [in] DWORD dwDesiredAccess,
  3. [in] BOOL bInheritHandle,
  4. [in] LPCWSTR lpName
  5. );

功能

  • 打开现有的命名信号量对象。

参数

  • dwDesiredAccess:对信号量对象的访问权限,通常指定为 SEMAPHORE_ALL_ACCESS
  • bInheritHandle:如果此值为 TRUE,则此过程创建的进程将继承句柄。 否则,进程不会继承此句柄。
  • lpName:打开已有的信号量名称。

返回值

  • 如果函数成功,则返回值是信号灯对象的句柄。
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

7.WaitForSingleObject 方法

  1. DWORD WaitForSingleObject(
  2. [in] HANDLE hHandle,
  3. [in] DWORD dwMilliseconds
  4. );

功能

  • 阻塞等待指定对象处于信号状态或超时间隔已过。

参数

  • hHandle:创建的信号量对象的句柄。
  • dwMilliseconds:超时间隔(以毫秒为单位)。通常指定为 INFINITE,表示仅当发出对象信号时,该函数才会返回。

返回值

  • 如果函数成功,则返回值指示导致函数返回的事件。可以是下列值之一
返回代码/值描述

WAIT_ABANDONED

指定的对象是一个互斥对象,该对象不是由拥有互斥对象的线程在拥有线程终止之前释放的。 互斥对象所有权授予调用线程,互斥状态设置为非对齐状态。如果互斥体保护持久状态信息,则应检查该信息是否一致性。

WAIT_OBJECT_0

指定对象的状态已发出信号。

WAIT_TIMEOUT

超时间隔已过,对象的状态未对齐。

WAIT_FAILED

函数失败。 要获得更多的错误信息,请调用 GetLastError。

8.ReleaseSemaphore 方法

  1. BOOL ReleaseSemaphore(
  2. [in] HANDLE hSemaphore,
  3. [in] LONG lReleaseCount,
  4. [out, optional] LPLONG lpPreviousCount
  5. );

功能

  • 按指定量增加指定的信号量对象的资源计数。

参数

  • hSemaphore:设置为 CreateSemaphore 或 OpenSemaphore 函数返回的信号量对象句柄。
  • lReleaseCount:信号量对象的当前资源计数将增加的量。该值必须>0且<=最大资源数量,通常设置为1。
  • lpPreviousCount:指向一个变量的指针,用于接收信号量的先前资源计数。如果不需要先前资源计数,此参数可以为 NULL 

返回值

  • 如果该函数成功,则返回值为非零值。
  • 如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。

9.CloseHandle 方法

  1. BOOL CloseHandle(
  2. [in] HANDLE hObject
  3. );

功能

  • 关闭打开的对象句柄。

参数

  • hObject:打开对象的有效句柄。

返回值

  • 如果该函数成功,则返回值为非零值。
  • 如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。

10.GetLastError 方法

_Post_equals_last_error_ DWORD GetLastError();

功能

  • 检索调用线程的最后错误代码值。 最后一个错误代码是按线程维护的。 多个线程不会覆盖彼此的最后错误代码。

返回值

  • 返回值是调用线程的最后错误代码。 

二,单共享内存单信号量-进程间单向通信

场景描述:实现进程间单向通信,只允许一块进程往该共享内存写入数据,另一个进程负责读数据,并使用信号量实现互斥操作,当有一个进程在进行写或读数据时,对该共享内存独占访问,其它进程必须阻塞等待该共享内存的信号量资源释放。

  • 开辟线程对共享内存进行管理。
  • 只有一个信号量,该信号量初始化只有一个可用资源。

共享内存管理文件实现 

头文件

  1. #ifndef SHAREMEMORYMANAGER_H
  2. #define SHAREMEMORYMANAGER_H
  3. #include <QObject>
  4. #include <QThread>
  5. #include <Windows.h>
  6. #include <QDebug>
  7. #define cout qDebug() <<"["<<__FUNCTION__<<"]["<<__LINE__<<"]:"
  8. class ShareMemoryManager : public QObject
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit ShareMemoryManager(int shareMemorySize,const QString &shareMemoryKey
  13. ,const QString &semaphoreKey,QObject *parent = nullptr);
  14. ~ShareMemoryManager();
  15. void startManager(); //开辟线程管理
  16. void quitManager(); //退出线程管理
  17. private:
  18. void initShareMemory(const int &shareMemorySize,const QString &shareMemoryKey);
  19. void initSemaphore(const QString &semaphoreKey);
  20. signals:
  21. void sig_readMessageFromShareMemory(QString message);
  22. public slots:
  23. void slot_writeMessageToShareMemory(const QString &message); //A进程进行写操作调用该接口
  24. void slot_readMessageFromShareMemory(); //B进程进行读操作调用该接口
  25. private:
  26. QThread *m_pThread;
  27. HANDLE m_pShareMemoryHandle; //共享内存对象句柄
  28. LPVOID m_pShareMemoryBuffer; //共享内存映射到本地
  29. HANDLE m_pSemaphoreForShareMem; //共享内存信号量
  30. int m_shareMemorySize; //共享内存段大小
  31. char *m_pReadBuf{nullptr}; //读缓冲区,用于读取共享内存的数据
  32. };
  33. #endif // SHAREMEMORYMANAGER_H

源文件

  1. #include "ShareMemoryManager.h"
  2. ShareMemoryManager::ShareMemoryManager(int shareMemorySize, const QString &shareMemoryKey
  3. , const QString &semaphoreKey, QObject *parent):QObject(parent)
  4. {
  5. m_pThread = nullptr;
  6. startManager();
  7. initShareMemory(shareMemorySize,shareMemoryKey);
  8. initSemaphore(semaphoreKey);
  9. }
  10. ShareMemoryManager::~ShareMemoryManager()
  11. {
  12. //释放信号量资源
  13. if (m_pSemaphoreForShareMem != nullptr) {
  14. ReleaseSemaphore(m_pSemaphoreForShareMem,1,NULL);
  15. CloseHandle(m_pSemaphoreForShareMem);
  16. m_pSemaphoreForShareMem = nullptr;
  17. }
  18. //释放共享内存资源:先解除文件映射,再关闭共享内存句柄
  19. if (m_pShareMemoryBuffer != nullptr) {
  20. UnmapViewOfFile(m_pShareMemoryBuffer);
  21. m_pShareMemoryBuffer = nullptr;
  22. }
  23. if (m_pShareMemoryHandle != nullptr) {
  24. CloseHandle(m_pShareMemoryHandle);
  25. m_pShareMemoryHandle = nullptr;
  26. }
  27. //释放读缓冲区指针
  28. if(m_pReadBuf != nullptr){
  29. free(m_pReadBuf);
  30. m_pReadBuf = nullptr;
  31. }
  32. quitManager();
  33. }
  34. void ShareMemoryManager::startManager()
  35. {
  36. if(m_pThread == nullptr){
  37. m_pThread = new QThread;
  38. this->moveToThread(m_pThread);
  39. m_pThread->start();
  40. }
  41. }
  42. void ShareMemoryManager::quitManager()
  43. {
  44. if(m_pThread != nullptr){
  45. m_pThread->requestInterruption();
  46. m_pThread->quit();
  47. m_pThread->wait();
  48. m_pThread->deleteLater();
  49. m_pThread = nullptr;
  50. }
  51. }
  52. void ShareMemoryManager::initShareMemory(const int &shareMemorySize, const QString &shareMemoryKey)
  53. {
  54. m_shareMemorySize = shareMemorySize;
  55. m_pShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,shareMemorySize,shareMemoryKey.toStdWString().c_str());
  56. if (m_pShareMemoryHandle == NULL)
  57. {
  58. cout << "Could not create file mapping B object:" << GetLastError();
  59. return;
  60. }
  61. m_pShareMemoryBuffer = MapViewOfFile(m_pShareMemoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, shareMemorySize);
  62. if (m_pShareMemoryBuffer == NULL)
  63. {
  64. cout << "Could not map view of file B:" << GetLastError();
  65. CloseHandle(m_pShareMemoryHandle);
  66. return;
  67. }
  68. }
  69. void ShareMemoryManager::initSemaphore(const QString &semaphoreKey)
  70. {
  71. m_pSemaphoreForShareMem = CreateSemaphore(NULL, 1, 1, semaphoreKey.toStdWString().c_str());
  72. if (m_pSemaphoreForShareMem == NULL)
  73. {
  74. cout << "CreateSemaphore writeSemName error: %d" << GetLastError();
  75. return;
  76. }
  77. }
  78. void ShareMemoryManager::slot_writeMessageToShareMemory(const QString &message)
  79. {
  80. DWORD semRet = WaitForSingleObject(m_pSemaphoreForShareMem,INFINITE);
  81. if(semRet == WAIT_OBJECT_0){
  82. strcpy_s((char*)m_pShareMemoryBuffer,m_shareMemorySize,message.toStdString().c_str());
  83. ReleaseSemaphore(m_pSemaphoreForShareMem,1,NULL);
  84. }
  85. }
  86. void ShareMemoryManager::slot_readMessageFromShareMemory()
  87. {
  88. if(m_pReadBuf == nullptr){
  89. m_pReadBuf = (char*)malloc(m_shareMemorySize*sizeof(char));
  90. }
  91. memset(m_pReadBuf,0,m_shareMemorySize);
  92. DWORD semRet = WaitForSingleObject(m_pSemaphoreForShareMem,INFINITE);
  93. if (semRet == WAIT_OBJECT_0) {
  94. strcpy_s(m_pReadBuf,m_shareMemorySize,(char*)m_pShareMemoryBuffer);
  95. cout << QString(m_pReadBuf); //打印读出来的数据
  96. emit sig_readMessageFromShareMemory(QString(m_pReadBuf));
  97. ReleaseSemaphore(m_pSemaphoreForShareMem,1,NULL);
  98. }
  99. }

A进程调用接口实现写操作

头文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include "ShareMemoryManager.h"
  5. namespace Ui {
  6. class MainWindow;
  7. }
  8. class MainWindow : public QMainWindow
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit MainWindow(QWidget *parent = nullptr);
  13. ~MainWindow();
  14. signals:
  15. void sig_sendMessage(const QString &data);
  16. private slots:
  17. void on_pushButton_clicked();
  18. private:
  19. Ui::MainWindow *ui;
  20. ShareMemoryManager *m_pSMM;
  21. };
  22. #endif // MAINWINDOW_H

源文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. MainWindow::MainWindow(QWidget *parent) :
  4. QMainWindow(parent),
  5. ui(new Ui::MainWindow)
  6. {
  7. ui->setupUi(this);
  8. m_pSMM = new ShareMemoryManager(250,"shareMemory","Semaphore");
  9. connect(this,SIGNAL(sig_sendMessage(QString)),m_pSMM,SLOT(slot_writeMessageToShareMemory(QString)),Qt::ConnectionType::QueuedConnection);
  10. }
  11. MainWindow::~MainWindow()
  12. {
  13. if(m_pSMM != nullptr){
  14. m_pSMM->deleteLater();
  15. m_pSMM = nullptr;
  16. }
  17. delete ui;
  18. }
  19. void MainWindow::on_pushButton_clicked()
  20. {
  21. QString data = ui->lineEdit->text();
  22. emit sig_sendMessage(data);
  23. }

ui布局

B进程调用接口实现读操作

头文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include "ShareMemoryManager.h"
  5. namespace Ui {
  6. class MainWindow;
  7. }
  8. class MainWindow : public QMainWindow
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit MainWindow(QWidget *parent = nullptr);
  13. ~MainWindow();
  14. private slots:
  15. void slot_readMessageToShow(QString message); //显示从共享内存读取的数据
  16. private:
  17. Ui::MainWindow *ui;
  18. ShareMemoryManager *m_pSMM;
  19. };
  20. #endif // MAINWINDOW_H

源文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. MainWindow::MainWindow(QWidget *parent) :
  4. QMainWindow(parent),
  5. ui(new Ui::MainWindow)
  6. {
  7. ui->setupUi(this);
  8. m_pSMM = new ShareMemoryManager(250,"shareMemory","Semaphore");
  9. connect(ui->pushButton,SIGNAL(clicked()),m_pSMM,SLOT(slot_readMessageFromShareMemory()),Qt::ConnectionType::QueuedConnection);
  10. connect(m_pSMM,SIGNAL(sig_readMessageFromShareMemory(QString)),this,SLOT(slot_readMessageToShow(QString)),Qt::ConnectionType::QueuedConnection);
  11. }
  12. MainWindow::~MainWindow()
  13. {
  14. if(m_pSMM != nullptr){
  15. m_pSMM->deleteLater();
  16. m_pSMM = nullptr;
  17. }
  18. delete ui;
  19. }
  20. void MainWindow::slot_readMessageToShow(QString message)
  21. {
  22. ui->plainTextEdit->appendPlainText(message);
  23. }

ui布局

 

三,单共享内存双信号量-进程间单向通信

场景描述:实现进程间单向通信,只允许一块进程往该共享内存写入数据,另一个进程负责读数据,并使用信号量实现互斥操作,A进程进行写操作完后会释放一个读信号量资源通知B进程进行读操作,A进程并阻塞在写信号量上。B进程进行读操作会消耗一个读信号量资源并释放一个写信号量资源,通知A进程进行下一轮写操作。

  • 开辟线程对共享内存进行管理。
  • 定义读写两个信号量,信号量初始化可用资源数都为0(所以在先调用WaitForSingleObject后调用ReleaseSemaphore会阻塞进程)。

共享内存管理文件实现

头文件

  1. #ifndef SHAREMEMORYMANAGER_H
  2. #define SHAREMEMORYMANAGER_H
  3. #include <QObject>
  4. #include <QThread>
  5. #include <Windows.h>
  6. #include <QDebug>
  7. #define cout qDebug() <<"["<<__FUNCTION__<<"]["<<__LINE__<<"]:"
  8. class ShareMemoryManager : public QObject
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit ShareMemoryManager(int shareMemorySize,const QString &shareMemoryKey
  13. ,const QString &readSemaphoreKey,const QString &writeSemaphoreKey
  14. ,QObject *parent = nullptr);
  15. ~ShareMemoryManager();
  16. void startManager(); //开辟线程管理
  17. void quitManager(); //退出线程管理
  18. private:
  19. void initShareMemory(const int &shareMemorySize,const QString &shareMemoryKey);
  20. void initSemaphore(const QString &readSemaphoreKey,const QString &writeSemaphoreKey);
  21. signals:
  22. void sig_readMessageFromShareMemory(QString message);
  23. public slots:
  24. void slot_writeMessageToShareMemory(const QString &message); //A进程进行写操作调用该接口
  25. void slot_readMessageFromShareMemory(); //B进程进行读操作调用该接口
  26. private:
  27. QThread *m_pThread;
  28. HANDLE m_pShareMemoryHandle; //共享内存对象句柄
  29. LPVOID m_pShareMemoryBuffer; //共享内存映射到本地
  30. HANDLE m_pReadSemaphoreForShareMem; //共享内存读信号量
  31. HANDLE m_pWriteSemaphoreForShareMem; //共享内存写信号量
  32. int m_shareMemorySize; //共享内存段大小
  33. char *m_pReadBuf{nullptr}; //读缓冲区,用于读取共享内存的数据
  34. };
  35. #endif // SHAREMEMORYMANAGER_H

源文件

  1. #include "ShareMemoryManager.h"
  2. ShareMemoryManager::ShareMemoryManager(int shareMemorySize, const QString &shareMemoryKey
  3. , const QString &readSemaphoreKey, const QString &writeSemaphoreKey, QObject *parent):QObject(parent)
  4. {
  5. m_pThread = nullptr;
  6. startManager();
  7. initShareMemory(shareMemorySize,shareMemoryKey);
  8. initSemaphore(readSemaphoreKey,writeSemaphoreKey);
  9. }
  10. ShareMemoryManager::~ShareMemoryManager()
  11. {
  12. //释放信号量资源
  13. if (m_pReadSemaphoreForShareMem != nullptr) {
  14. ReleaseSemaphore(m_pReadSemaphoreForShareMem,1,NULL);
  15. CloseHandle(m_pReadSemaphoreForShareMem);
  16. m_pReadSemaphoreForShareMem = nullptr;
  17. }
  18. if (m_pWriteSemaphoreForShareMem != nullptr) {
  19. ReleaseSemaphore(m_pWriteSemaphoreForShareMem,1,NULL);
  20. CloseHandle(m_pWriteSemaphoreForShareMem);
  21. m_pWriteSemaphoreForShareMem = nullptr;
  22. }
  23. //释放共享内存资源:先解除文件映射,再关闭共享内存句柄
  24. if (m_pShareMemoryBuffer != nullptr) {
  25. UnmapViewOfFile(m_pShareMemoryBuffer);
  26. m_pShareMemoryBuffer = nullptr;
  27. }
  28. if (m_pShareMemoryHandle != nullptr) {
  29. CloseHandle(m_pShareMemoryHandle);
  30. m_pShareMemoryHandle = nullptr;
  31. }
  32. //释放读缓冲区指针
  33. if(m_pReadBuf != nullptr){
  34. free(m_pReadBuf);
  35. m_pReadBuf = nullptr;
  36. }
  37. quitManager();
  38. }
  39. void ShareMemoryManager::startManager()
  40. {
  41. if(m_pThread == nullptr){
  42. m_pThread = new QThread;
  43. this->moveToThread(m_pThread);
  44. m_pThread->start();
  45. }
  46. }
  47. void ShareMemoryManager::quitManager()
  48. {
  49. if(m_pThread != nullptr){
  50. m_pThread->requestInterruption();
  51. m_pThread->quit();
  52. m_pThread->wait();
  53. m_pThread->deleteLater();
  54. m_pThread = nullptr;
  55. }
  56. }
  57. void ShareMemoryManager::initShareMemory(const int &shareMemorySize, const QString &shareMemoryKey)
  58. {
  59. m_shareMemorySize = shareMemorySize;
  60. m_pShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,shareMemorySize,shareMemoryKey.toStdWString().c_str());
  61. if (m_pShareMemoryHandle == NULL)
  62. {
  63. cout << "Could not create file mapping B object:" << GetLastError();
  64. return;
  65. }
  66. m_pShareMemoryBuffer = MapViewOfFile(m_pShareMemoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, shareMemorySize);
  67. if (m_pShareMemoryBuffer == NULL)
  68. {
  69. cout << "Could not map view of file B:" << GetLastError();
  70. CloseHandle(m_pShareMemoryHandle);
  71. return;
  72. }
  73. }
  74. void ShareMemoryManager::initSemaphore(const QString &readSemaphoreKey, const QString &writeSemaphoreKey)
  75. {
  76. m_pReadSemaphoreForShareMem = CreateSemaphore(NULL, 0, 1, readSemaphoreKey.toStdWString().c_str());
  77. if (m_pReadSemaphoreForShareMem == NULL)
  78. {
  79. cout << "CreateSemaphore readSemName error: %d" << GetLastError();
  80. return;
  81. }
  82. m_pWriteSemaphoreForShareMem = CreateSemaphore(NULL, 0, 1, writeSemaphoreKey.toStdWString().c_str());
  83. if (m_pWriteSemaphoreForShareMem == NULL)
  84. {
  85. cout << "CreateSemaphore writeSemName error: %d" << GetLastError();
  86. return;
  87. }
  88. }
  89. void ShareMemoryManager::slot_writeMessageToShareMemory(const QString &message)
  90. {
  91. strcpy_s((char*)m_pShareMemoryBuffer,m_shareMemorySize,message.toStdString().c_str());
  92. //释放共享内存的可读信号,通知其它进程可以读取内容
  93. ReleaseSemaphore(m_pReadSemaphoreForShareMem,1,NULL);
  94. //阻塞等待其它进程释放共享内存的可读信号,然后写进程进行下一轮写操作
  95. WaitForSingleObject(m_pWriteSemaphoreForShareMem,INFINITE);
  96. }
  97. void ShareMemoryManager::slot_readMessageFromShareMemory()
  98. {
  99. if(m_pReadBuf == nullptr){
  100. m_pReadBuf = (char*)malloc(m_shareMemorySize*sizeof(char));
  101. }
  102. memset(m_pReadBuf,0,m_shareMemorySize);
  103. //阻塞等待写进程释放共享内存的可读信号
  104. DWORD semRet = WaitForSingleObject(m_pReadSemaphoreForShareMem,INFINITE);
  105. if (semRet == WAIT_OBJECT_0) {
  106. strcpy_s(m_pReadBuf,m_shareMemorySize,(char*)m_pShareMemoryBuffer);
  107. sig_readMessageFromShareMemory(QString(m_pReadBuf));
  108. //释放共享内存的写信号,通知写进程进行写操作
  109. ReleaseSemaphore(m_pWriteSemaphoreForShareMem,1,NULL);
  110. }
  111. }

A进程调用接口实现写操作

头文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include "ShareMemoryManager.h"
  5. namespace Ui {
  6. class MainWindow;
  7. }
  8. class MainWindow : public QMainWindow
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit MainWindow(QWidget *parent = nullptr);
  13. ~MainWindow();
  14. signals:
  15. void sig_sendMessage(const QString &data);
  16. private slots:
  17. void on_pushButton_clicked();
  18. private:
  19. Ui::MainWindow *ui;
  20. ShareMemoryManager *m_pSMM;
  21. };
  22. #endif // MAINWINDOW_H

源文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. MainWindow::MainWindow(QWidget *parent) :
  4. QMainWindow(parent),
  5. ui(new Ui::MainWindow)
  6. {
  7. ui->setupUi(this);
  8. m_pSMM = new ShareMemoryManager(250,"shareMemory","readSemaphore","writeSemaphore");
  9. connect(this,SIGNAL(sig_sendMessage(QString)),m_pSMM,SLOT(slot_writeMessageToShareMemory(QString)),Qt::ConnectionType::QueuedConnection);
  10. }
  11. MainWindow::~MainWindow()
  12. {
  13. if(m_pSMM != nullptr){
  14. m_pSMM->deleteLater();
  15. m_pSMM = nullptr;
  16. }
  17. delete ui;
  18. }
  19. void MainWindow::on_pushButton_clicked()
  20. {
  21. QString data = ui->lineEdit->text();
  22. emit sig_sendMessage(data);
  23. }

UI文件同单共享内存单信号量

B进程调用接口实现读操作

头文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include "ShareMemoryManager.h"
  5. namespace Ui {
  6. class MainWindow;
  7. }
  8. class MainWindow : public QMainWindow
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit MainWindow(QWidget *parent = nullptr);
  13. ~MainWindow();
  14. private slots:
  15. void slot_readMessageToShow(QString message); //显示从共享内存读取的数据
  16. private:
  17. Ui::MainWindow *ui;
  18. ShareMemoryManager *m_pSMM;
  19. };
  20. #endif // MAINWINDOW_H

源文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. MainWindow::MainWindow(QWidget *parent) :
  4. QMainWindow(parent),
  5. ui(new Ui::MainWindow)
  6. {
  7. ui->setupUi(this);
  8. m_pSMM = new ShareMemoryManager(250,"shareMemory","readSemaphore","writeSemaphore");
  9. connect(ui->pushButton,SIGNAL(clicked()),m_pSMM,SLOT(slot_readMessageFromShareMemory()));
  10. connect(m_pSMM,SIGNAL(sig_readMessageFromShareMemory(QString)),this,SLOT(slot_readMessageToShow(QString)));
  11. }
  12. MainWindow::~MainWindow()
  13. {
  14. if(m_pSMM != nullptr){
  15. m_pSMM->deleteLater();
  16. m_pSMM = nullptr;
  17. }
  18. delete ui;
  19. }
  20. void MainWindow::slot_readMessageToShow(QString message)
  21. {
  22. ui->plainTextEdit->appendPlainText(message);
  23. }

UI文件同单共享内存单信号量

四,双共享内存双信号量-进程间双向通信

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/888893
推荐阅读
相关标签
  

闽ICP备14008679号