1,本文目的
近期做嵌入式linux网关通信采集项目时,有如下需求:
-> 要采集不同类型的设备,可能会遇到N种协议,考虑每种协议单独进程管理
-> 单独的联网上报进程
-> 单独的远程升级进程
此时出现了一个问题,如果在设备运行过程中,其中一个或多个进程异常关闭,可能会导致设备工作异常。解决思路参网上照进程守护进行监听进程并对异常关闭进程做重启工作,思路如下:
启动守护进程 -> 按照配置列表启动子进程 -> 定时查询进程PID -> 重启异常关闭子进程
但是之前工作中遇到过,进程异常不工作但是PID依然还在的情况,于是想到了进程间通信,类似于心跳。
通过查询网上的案例,各有优缺点,有的作为父进程启动子进程进行管理与通信,有的需要扫描共享内存……不再讨论以上这些方法,本文只讨论QLocalServer、QLocalSocket实现方式参照QT例程的“Fortune”如下图,进行记录实现方法。

2,代码实现
代码分两部分,服务器端和客户端。我的思路是,每个协议进程作为服务器端进行监听,进程守护作为客户端定时连接接受数据。
服务器端代码:
prog1.pro
QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle
DESTDIR = /home/went/test/bin
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
server.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
server.h
main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
server w;
return a.exec();
}
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include <QString>
#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>
class server : public QObject
{
Q_OBJECT
public:
explicit server(QObject *parent = nullptr);
~server();
private slots:
void sendData();
private:
QLocalServer *prog1Server;
QStringList fortunes;
};
#endif // SERVER_H
server.cpp
#include "server.h"
//#include <stdlib.h>
//#include <qlocalserver.h>
//#include <qlocalsocket.h>
server::server(QObject *parent) : QObject(parent)
{
prog1Server = new QLocalServer;
prog1Server->removeServer("prog1");
if (!prog1Server->listen("prog1")) {
qDebug() << QString("Unable to start the server: %1.").arg(prog1Server->errorString()) << endl;
return;
}
connect(prog1Server, &QLocalServer::newConnection, this, &server::sendData);
qDebug() << "prog1 is openned !" << endl;
}
server::~server() {
if(prog1Server != nullptr) {
prog1Server->close();
delete prog1Server;
}
}
void server::sendData() {
QLocalSocket *clientConnection = prog1Server->nextPendingConnection();
connect(clientConnection, &QLocalSocket::disconnected,
clientConnection, &QLocalSocket::deleteLater);
clientConnection->write("ok");
qDebug() << "reply ok !" << endl;
clientConnection->waitForBytesWritten();
clientConnection->disconnectFromServer();
}
客户端代码:
deamon.pro
QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle
DESTDIR = /home/went/test/bin
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
client.cpp \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
client.h
main.cpp
#include <QCoreApplication>
#include <QDebug>
#include <QProcess>
#include <client.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
client w;
return a.exec();
}
client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include <QLocalSocket>
#include <QThread>
class client : public QObject
{
Q_OBJECT
public:
explicit client(QObject *parent = nullptr);
private slots:
void requestNewFortune();
void readFortune();
void displayError(QLocalSocket::LocalSocketError socketError);
private:
QLocalSocket *socket;
};
#endif // CLIENT_H
client.cpp
#include "client.h"
client::client(QObject *parent) : QObject(parent),
socket(new QLocalSocket(this))
{
system("./prog1 &");
QThread::sleep(5);
qDebug() << "start" << endl;
connect(socket, &QLocalSocket::readyRead, this, &client::readFortune);
connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
this, &client::displayError);
requestNewFortune();
}
void client::requestNewFortune()
{
socket->abort();
socket->connectToServer("prog1");
}
void client::readFortune()
{
QString data;
data = socket->readAll();
qDebug() << "client received: " << data << endl;
}
void client::displayError(QLocalSocket::LocalSocketError socketError)
{
if (socketError != QLocalSocket::PeerClosedError) {
qDebug() << "something error: " << socketError << endl;
}
}
3,运行说明
客户端程序在构建函数里加入了启动服务器端指令(限Linux),将编译后的可执行程序放在同一个文件夹下,只需要执行客户端程序即可完成测试。测试结果如下图:

QT实现进程守护的代码与运行说明
449

被折叠的 条评论
为什么被折叠?



