前言
有些代码量大功能复杂的大型程序,需要长时间运行,而运行环境复杂,无法保证程序能一直稳定运行,这时就需要守护进程来保证程序异常退出后能再次启动恢复异常退出前的运行状态。
需求分析
- 守护进程需要启动、停止业务进程
- 守护进程需要监控业务进程的运行状态【正常退出、异常退出】
- 业务进程需要获取守护进程的运行状态
知识点
- 父进程-->子进程:使用QProcess类,可以启动、停止、监听子进程状态
- 子进程-->父进程:使用进程间通讯,QLocalServer、QLocalSocket
代码实现
父进程
父进程创建
DaemonProc::DaemonProc(QWidget *parent)
: QWidget(parent)
, ui(new Ui::DaemonProcClass())
, m_proc(QSharedPointer<QProcess>(new QProcess()))
, m_localServer(new QLocalServer(this))
{
ui->setupUi(this);
initForm();
}
启动子进程
if (m_proc)
{
m_proc->start("childproc.exe", QStringList());
}
停止子进程
if (m_proc)
{
m_proc->terminate();
}
监听子进程状态
//子进程退出监控
connect(m_proc.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &DaemonProc::onProcFinished, Qt::UniqueConnection);
...
//对子进程状态做处理
void DaemonProc::onProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (QProcess::CrashExit == exitStatus)
{
qWarning("CrashExit to restart");
startChildProc();
}
else
{
qInfo("NormalExit to exit");
qApp->exit();
}
}
进程间通讯
m_localSocketName = "LOCAL_SOCKET_NAME";
//开启QLocalServer服务
m_localServer->listen(m_localSocketName);
子进程
通过父子进程间的socket连接状态来判断父进程是否在运行
m_localSocketName = "LOCAL_SOCKET_NAME";
m_localSocket = QSharedPointer<QLocalSocket>(new QLocalSocket(this));
connect(m_localSocket.get(), &QLocalSocket::disconnected, this, [this]() {
QTimer::singleShot(500, [this]() {
this->close();
});
});
connect(m_localSocket.get(), &QLocalSocket::errorOccurred, this, [this](QLocalSocket::LocalSocketError err) {
QTimer::singleShot(500, [this]() {
this->close();
});
});
m_localSocket->connectToServer(m_localSocketName);