Qt--共享内存监听工具
共享内存概述
共享内存的特点:
1)共享内存是进程共享数据的一种最快的方法。
一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。
2)使用共享内存要注意的是多个进程之间对一个给定存储区域访问的互斥。
若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读写这些数据。
共享内存示意图:
共享内存是进程间通信方式中效率最高的,原因在于进程是直接在物理内存上进行操作地址映射到用户进程,所以只要对其地址进行操作,就是直接对物理地址操作。
使用共享内存实现进程间的通信的监听手段不比网络通信的监听手段多,由于开发调试需要,使用QT开发了一个小工具,启动一个新的进程软件,连接入需要监听的共享内存块,周期性读取内存中的数据并将其以固定格式写入文本文件,效果如下:
源码解析:
mainwindow.h
1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QMainWindow> 5 #include <QFile> 6 #include <QTextStream> 7 #include <QTextCodec> 8 #include <QDataStream> 9 #include <QDateTime> 10 #include <QTimer> 11 #include <QSharedMemory> 12 #include <QDebug> 13 #include <QMessageBox> 14 15 namespace Ui { 16 class MainWindow; 17 } 18 19 class MainWindow : public QMainWindow 20 { 21 Q_OBJECT 22 23 public: 24 explicit MainWindow(QWidget *parent = 0); 25 ~MainWindow(); 26 27 private slots: 28 void on_pushButtonStart_clicked(); 29 30 void on_pushButton_clicked(); 31 32 private: 33 Ui::MainWindow *ui; 34 35 QTimer *mTimer; 36 37 QSharedMemory sharedMemoryWrite; 38 quint16 dataLen; 39 40 void writeToFile(const QByteArray &byteArray, const QString &fileName); 41 void writeToBin(const QByteArray &byteArray, const QString &fileName); 42 void writeToHex(const QByteArray &byteArray, const QString &fileName); 43 QString getCurrentDateTime(); 44 45 public slots: 46 void readMemoryData(); 47 }; 48 49 #endif // MAINWINDOW_H
mainwindow.cpp
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 MainWindow::MainWindow(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui::MainWindow) 7 { 8 ui->setupUi(this); 9 ui->pushButtonStart->setStyleSheet("background-color: green"); 10 ui->pushButton->setStyleSheet("background-color: red"); 11 12 //定时器初始化 13 mTimer = new QTimer(); 14 connect(mTimer,&QTimer::timeout,this,&MainWindow::readMemoryData); 15 16 } 17 18 MainWindow::~MainWindow() 19 { 20 delete ui; 21 } 22 23 //定时器激活按钮点击事件 24 void MainWindow::on_pushButtonStart_clicked() 25 { 26 static bool state = false; 27 state = !state; 28 if(state) 29 { 30 ui->pushButtonStart->setStyleSheet("background-color: red"); 31 ui->pushButtonStart->setText("Stop"); 32 33 //开启读取定时 34 if(mTimer->isActive() == false) 35 { 36 mTimer->start(250); 37 } 38 } 39 else 40 { 41 ui->pushButtonStart->setStyleSheet("background-color: green"); 42 ui->pushButtonStart->setText("Start"); 43 44 //停止读取定时器 45 if(mTimer->isActive() == true) 46 { 47 mTimer->stop(); 48 } 49 } 50 } 51 52 //包含写入时间,写入ASCII格式 53 void MainWindow::writeToFile(const QByteArray &byteArray, const QString &fileName) 54 { 55 QFile file(fileName); 56 //文件打开方式写入和追加 57 if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) 58 { 59 // 处理错误,例如可以抛出异常或者返回错误标志 60 return; 61 } 62 //初始化流 63 QTextStream out(&file); 64 //设置中文格式,避免乱码 65 QTextCodec *tc = QTextCodec::codecForName("GBK"); 66 //QByteArray转换为QString 67 QString str = tc->toUnicode(byteArray); 68 //写入时间 69 out << getCurrentDateTime() << " " <<str; 70 //换行用于区分不同周期数据 71 out << "\n"; 72 //文件关闭 73 file.close(); 74 } 75 76 //十六进制转字符串写入文件 77 void MainWindow::writeToHex(const QByteArray &byteArray, const QString &fileName) 78 { 79 QFile file(fileName); 80 //文件打开方式写入和追加 81 if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) 82 { 83 // 处理错误,例如可以抛出异常或者返回错误标志 84 return; 85 } 86 //初始化流 87 QTextStream out(&file); 88 //设置中文格式,避免乱码 89 QTextCodec *tc = QTextCodec::codecForName("GBK"); 90 //QByteArray格式转换为十六进制 91 QString str = tc->toUnicode(byteArray.toHex()); 92 //QRegularExpression(“(…)”)表示匹配两个字符,replace()函数将匹配到的字符用"\1 “替换 93 out << str.replace(QRegularExpression("(..)"), "\\1 "); 94 //换行用于区分不同周期数据 95 out << "\n"; 96 //文件关闭 97 file.close(); 98 } 99 100 //获取当前时间 101 QString MainWindow::getCurrentDateTime() 102 { 103 // 获取当前日期和时间 104 QDateTime currentDateTime = QDateTime::currentDateTime(); 105 // 将日期和时间格式化为字符串 106 // 例如: "2023-03-28 15:04:05" 107 QString dateTimeString = currentDateTime.toString("yyyy-MM-dd hh:mm:ss:zzz"); 108 109 return dateTimeString; 110 } 111 112 //读取内存定时器 113 void MainWindow::readMemoryData() 114 { 115 QByteArray dataRead; 116 //初始化dataRead缓存的大小 117 dataRead.resize(dataLen); 118 119 //锁闭内存 120 sharedMemoryWrite.lock(); 121 //拷贝内存中的数据到dataRead缓存中 122 memcpy(dataRead.data(),(char*)sharedMemoryWrite.data(),dataRead.length()); 123 //释放内存 124 sharedMemoryWrite.unlock(); 125 126 //记录内存中数据到文件 127 QByteArray byteArray = ":"; 128 //设置记录文件名称 129 QString fileName = "output.txt"; 130 //将当前时间数据写入到文件中 131 writeToFile(byteArray, fileName); 132 //将拷贝出来的内存数据写入到文件中 133 writeToHex(dataRead, fileName); 134 } 135 136 //连接共享内存事件 137 void MainWindow::on_pushButton_clicked() 138 { 139 static bool state = false; 140 141 if(state) 142 { 143 //共享内存分离 144 sharedMemoryWrite.detach(); 145 ui->pushButton->setStyleSheet("background-color: red"); 146 ui->pushButton->setText("DisConnect"); 147 state = !state; 148 } 149 else 150 { 151 sharedMemoryWrite.setKey(ui->lineEdit->text()); 152 sharedMemoryWrite.detach();//分离 153 bool flag = sharedMemoryWrite.attach();//连接 154 if(!flag) 155 { 156 //内存不存在 157 qDebug()<<ui->lineEdit->text()<<" is not alive"; 158 //设置中文格式,避免乱码 159 QTextCodec *tc = QTextCodec::codecForName("GBK"); 160 //转换成中文GBK格式 161 QString str = tc->toUnicode("内存不存在,\n请确认内存名称"); 162 //弹窗告警 163 QMessageBox::warning(this,"Warning",str); 164 return; 165 } 166 dataLen = sharedMemoryWrite.size(); 167 qDebug()<<"Connect "<<ui->lineEdit->text(); 168 169 ui->pushButton->setStyleSheet("background-color: green"); 170 ui->pushButton->setText("Connect"); 171 state = !state; 172 } 173 174 }
源码下载:
链接: https://pan.baidu.com/s/19-0WgDwdJpGB0A3L87-cBw 提取码: q9cc 复制这段内容后打开百度网盘手机App,操作更方便哦