Qt 进程守护程序

Qt 进程守护程序

简单粗暴的监控,方法可整合到其他代码。

一、windows环境下
1、进程查询函数
processCount函数用于查询系统所有运行的进程中该进程运行的数量,比如启动了5个A进程,该函数查询返回的结果就为5。
windows下使用了API接口查询进程信息,该函数纯C++无Qt库相关代码,注释对代码进行了详细解释。

int processCount(const char*  processName)
{
    int countProcess = 0;
    //CreateToolhelp32Snapshot 获取系统中正在运行的进程信息,线程信息等
    HANDLE toolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (((int)toolHelp32Snapshot) != -1)
    {
        PROCESSENTRY32 processEntry32;
        processEntry32.dwSize = sizeof(processEntry32);
        if(Process32First(toolHelp32Snapshot, &processEntry32))      //判断进程获取首进程是否存在
        {
            do
            {
                int iLen = 2 * wcslen(processEntry32.szExeFile);    //wcslen - 计算宽字符串的长度
                char* currentProcessName = new char[iLen + 1];
                wcstombs(currentProcessName, processEntry32.szExeFile, iLen + 1);    //将宽字符转换成多字符
                if (strcmp(processName, currentProcessName) == 0)      //对比进程名
                    countProcess++;
                delete []currentProcessName;
            }while (Process32Next(toolHelp32Snapshot, &processEntry32));     //进程获取函数,获取下一个进程名
        }
        //关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。
        CloseHandle(toolHelp32Snapshot);
    }
    return countProcess;
}

2、进程守护代码
进程守护其实就是使用一个进程去定时查询另外一个被守护的进程是否存在,不存在则需要启动该进程。代码如下,运行时,首先需要获取被守护的进程APP,使用读取配置文件的方式,如果配置文件不存在(首次启动该代码),则需要选择被守护的进程,然后将选择的APP路劲存入配置文件,供下次启动读取使用。

#include <QApplication>
#include <QFileDialog>
#include <QSettings>
#include <windows.h>
#include <QDebug>
#include <QDateTime>
 
int main(int argc, char *argv[])
{
    QSettings sets("sys.ini", QSettings::IniFormat);
    QString targetExePath = sets.value(KEY_EXE_PATH).toString();
    if ("" == targetExePath)
    {
        //首次需要选择 被守护的进程
        QString exepath = QFileDialog::getOpenFileName(nullptr, "选择程序", "D:/", "Exe files (*.exe)");
        if ("" != exepath)
            sets.setValue(KEY_EXE_PATH, exepath);       //写入配置文件
    }
    while (1)        //死循环,不断查询判断
    {
        //targetExePath = sets.value(KEY_EXE_PATH).toString();
        QString exeName = targetExePath.split('/').last();
 
        QDateTime strtTime = QDateTime::currentDateTime();
        int countProcess = processCount(exeName.toStdString().c_str());   // 查询该进程运行数量
        qDebug()<<"use times for Query process:"<<strtTime.msecsTo(QDateTime::currentDateTime())<<"(ms)   countProcess:"<<countProcess;
        if (countProcess == 0)
            system(targetExePath.toStdString().c_str());        //关闭状态 重启进程,注意:这里实际运行会阻塞在这里,一直等到被守护的线程结束。
       Sleep(3000);
    }
}

二、linux环境下
1、进程查询函数

原理: 使用 popen函数 + pidof命令 查询对应进程的pid,该方法的缺点就是不能像windows那样读取所有进程名从而获取该进程运行的数量。所以,如果一个程序加载多个进程(同程序进程名相同,pid不同),使用该方法只能获取最后一个启动的进程pid。

popen属于标准I/O函数库中函数,使用该函数启动另外一个进程去执行一个shell命令行。
这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。
popen函数还创建一个管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。

实现函数如下,函数参数输入进程名,返回进程的pid,如果返回0,则表示进程不存在或未运行。

void Widget::watchdog()
{
    //守护进程
    QTimer* updateTimer = new QTimer(this);
    connect(updateTimer, SIGNAL(timeout()), this, SLOT(checkApp()));
    updateTimer->start(300);
}
void Widget::checkApp()
{
    if (getProcessPidByName("AppName") == 0) {
        system("cd /sdcard");
        system("./AppName &");
        qDebug() << "";
        qDebug() << "  _  __                        _____  _                                 ";
        qDebug() << " | |/ /                       / ____|| |                                ";
        qDebug() << " | ' /   __ _  _ __    __ _  | |     | |__   _   _   __ _  _ __    __ _ ";
        qDebug() << " |  <   / _` || '_ \\  / _` | | |     | '_ \\ | | | | / _` || '_ \\  / _` |";
        qDebug() << " | . \\ | (_| || | | || (_| | | |____ | | | || |_| || (_| || | | || (_| |";
        qDebug() << " |_|\\_\\ \\__,_||_| |_| \\__, |  \\_____||_| |_| \\__,_| \\__,_||_| |_| \\__, |";
        qDebug() << "                      __/  |                                      __/  |";
        qDebug() << "                     |____/                                      |____/ ";
        qDebug() << "";
    }
}
int Widget::getProcessPidByName(const char* proc_name)
{
    FILE* fp;
    char buf[100];
    char cmd[200] = { '\0' };
    int pid = -1;
    sprintf(cmd, "pidof %s", proc_name);
    if ((fp = popen(cmd, "r")) != NULL) {
        if (fgets(buf, 255, fp) != NULL)
            pid = atoi(buf);
    }
    pclose(fp);
    return pid;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值