uchar * QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions)
offset是映射起始的偏移量,size是映射的内存大小,flags暂时不用
bool QFileDevice::unmap(uchar * address)
回收映射的内存,这里有一个需要注意的是当这个内存映射的文件对象被销毁或者重新打开一个新的文件时,相关的没有回收映射的内存会被自动回收
QSystemSemaphore g_sem("SemRead", 1, QSystemSemaphore::Create);
QtParentTask::QtParentTask(QWidget *parent)
: QWidget(parent),ui(new Ui::QtParentTaskClass)
,m_timer(new QTimer(this))
,m_fp(nullptr)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, &QtParentTask::startChildProcess);
connect(m_timer, &QTimer::timeout, this, &QtParentTask::readChildData);
QDir dir;
QString dirpath = QDir::tempPath() + "\\QtIPC_test";
if (!dir.exists(dirpath))
dir.mkdir(dirpath);
ui->progressBar->setMaximum(100000);
//在系统临时文件夹进行临时文件映射
m_memFile.setFileName(dirpath + "\\data1");
}
QtParentTask::~QtParentTask()
{
delete ui;
}
void QtParentTask::startChildProcess()
{
m_fp = nullptr;
const QString path("QtChildTask.exe");
QProcess childProcess;
connect(&childProcess, static_cast<void (QProcess::*)(QProcess::ProcessError error)>(&QProcess::error),
[this](QProcess::ProcessError error) {
if (error == QProcess::Crashed)
ui->lineEdit->setText("crashed");
});
//读取子进程的标准输出
connect(&childProcess, &QProcess::readyReadStandardOutput, [this, &childProcess]() {
QString txt = QString::fromLocal8Bit(childProcess.readAllStandardOutput());
ui->lineEdit->setText(txt);
});
//读取子进程的标准错误输出
connect(&childProcess, &QProcess::readyReadStandardError, [this, &childProcess]() {
QString txt = QString::fromLocal8Bit(childProcess.readAllStandardError());
ui->lineEdit_err->setText(txt);
});
QEventLoop loop;
connect(&childProcess, static_cast<void (QProcess::*)(int exitCode)>(&QProcess::finished), &loop, &QEventLoop::quit);
connect(&childProcess, static_cast<void (QProcess::*)(int exitCode)>(&QProcess::finished), [this](int exitCode) {
if(0 == exitCode)
ui->lineEdit->setText("childProcess done");
else
ui->lineEdit->setText("childProcess exit error");
//保证读取到最后写入的值
readChildData();
if (m_fp) m_memFile.unmap(m_fp);
});
childProcess.start(path);
m_timer->start(50);
//启动内部循环阻塞到子进程执行完毕
loop.exec();
m_timer->stop();
}
void QtParentTask::readChildData()
{
if(g_sem.acquire())
{//利用信号量进行进程同步
if(m_fp == nullptr)
{
if (m_memFile.open(QIODevice::ReadOnly))
{//这里主要是读,不涉及写,子进程负责写
m_fp = m_memFile.map(0, m_memFile.size());
//关闭文件不会影响映射的内存
m_memFile.close();
}
}
if(m_fp)
{
int val = *((int*)m_fp);
ui->progressBar->setValue(val);
}
g_sem.release();
}
else
QMessageBox::information(this, "error", g_sem.errorString());
}
QSystemSemaphore g_sem("SemRead", 1, QSystemSemaphore::Open);
QString g_memFile = QDir::tempPath() + "\\QtIPC_test\\data1";
uchar* fp = nullptr;
void writeSharedData(int val)
{
if(g_sem.acquire())
{
if (fp)
{
memcpy(fp, &val, sizeof(int));
}
else
std::cerr << file.errorString().toLocal8Bit().constData();
g_sem.release();
}
else
std::cerr << g_sem.errorString().toLocal8Bit().constData();
}
int main(int argc, char *argv[])
{
QFile file(g_memFile);
//得先设置大小否则映射会失败
bool isok = file.resize(1024);
bool isok1 = file.open(QIODevice::ReadWrite);
fp = file.map(0, 1024);
file.close();
for (int i = 0; i <= 100000; i++)
{
std::cout << i << std::endl;
writeSharedData(i);
}
file.unmap(fp);
return 0;
}
示例代码下载:https://download.csdn.net/download/github_39553168/12374335/.