我一直在使用我发现的修改过的类来检查同一进程的另一个实例是否已经在运行,问题是检查进程的方法会添加同一进程的另一个实例。
当我的应用程序启动时,会创建一个新的进程ID,并且可以看到:
ps -A | grep "AppName"
有了这个,我得到一个返回的条目,然后我使用以下方法检查应用程序的另一个实例:
QString strCMD = "ps -A | grep \"" + mcstrAppName + "\"";
QProcess objProc;
objProc.start("bash", QStringList() << "-c" << strCMD);
if ( objProc.waitForStarted() != true || objProc.waitForFinished() != true ) {
mcpobjApp->exit(cleanExit(-1, "Unable to determine if another instance is running!"));
return;
}
一旦开始&#39;方法被调用同一个应用程序的另一个实例出现在进程表中,再次验证:
ps -A | grep "AppName"
现在出现两个条目,每个条目都有不同的PID。我也试过了:
QString strOptions = "-A | grep \"" + mcstrAppName + "\"";
QProcess objProc;
objProc.start("ps", QStringList() << strOptions);
结果与进程表中的两个条目相同。
有没有办法在不添加其他实例的情况下检查进程表中的另一个实例?
答案 0 :(得分:0)
我建议使用pid文件。这是linux上守护进程的标准程序。
int createPidFile(const char *pidFile, int flags)
{
int fd;
char buf[BUF_SIZE];
fd = open(pidFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
errExit("Could not open PID file %s", pidFile);
if (flags & CPF_CLOEXEC)
{
/* Set the close-on-exec file descriptor flag */
flags = fcntl(fd, F_GETFD); /* Fetch flags */
if (flags == -1)
errExit("Could not get flags for PID file %s", pidFile);
flags |= FD_CLOEXEC; /* Turn on FD_CLOEXEC */
if (fcntl(fd, F_SETFD, flags) == -1) /* Update flags */
errExit("Could not set flags for PID file %s", pidFile);
}
return fd;
}
来源 Linux编程接口
这会创建一个文件并将其锁定,以便其他进程无法打开它。它在退出时将其标记为关闭,因此当进程通过正常或异常终止退出时,文件将关闭。如果您的程序实例已在运行,则此功能将失败,您可以退出。
修改强> pid文件应该在临时分区中。具体位置取决于您的发行版,只需查看您的系统,其他守护进程创建其pid文件。
答案 1 :(得分:0)
我相信你正试图验证只有&#34;一个&#34;您的应用程序的实例可以一次执行。
要实现这一目标,您需要QtSingleApplication之类的内容。
另一种选择,即SingleApplication。
答案 2 :(得分:0)
我使用的实际解决方案,我自己写的,原型:clsSingleInstance.h:
class clsSingleInstance : public QObject {
Q_OBJECT
public:
explicit clsSingleInstance(const QString& strAppName, QApplication* pobjApp);
public slots:
void check();
private:
const int mcintDelay = 3000;
const QString mcstrAppName;
qint64 mint64PID;
QApplication const* mcpobjApp;
QTimer* mptmrCheck;
Q_DISABLE_COPY(clsSingleInstance);
};
实施,clsSingleInstance.cpp:
#include "clsSingleInstance.h"
/**
* @brief clsSingleInstance::clsSingleInstance
* @param strAppName : The application name as it will appear in the process list
* @param pobjApp : Pointer to the applicaiton instance
*/
clsSingleInstance::clsSingleInstance(const QString& strAppName
,QApplication* pobjApp)
:QObject(pobjApp)
,mcstrAppName(strAppName)
,mcpobjApp(pobjApp) {
//Save the process ID
mint64PID = mcpobjApp->applicationPid();
//Run check now to determine if another instance is running
check();
//Set-up timer to check for another instance regularly
mptmrCheck = new QTimer(this);
if ( mptmrCheck != NULL ) {
connect(mptmrCheck, SIGNAL(timeout()), this, SLOT(check()));
mptmrCheck->start(mcintDelay);
}
}
/**
* @brief clsSingleInstance::check
* Checks application instances running
*/
void clsSingleInstance::check() {
const QString cstrCheckFile = clsMainWin::mcszConfigPath
+ mcstrAppName + ".pid";
QFile objPID(cstrCheckFile);
if ( objPID.exists() == true ) {
//Check the file date / time stamp
QDateTime dtCreated = QFileInfo(cstrCheckFile).created()
,dtNow = QDateTime::currentDateTime();
qint64 int64Created = dtCreated.toMSecsSinceEpoch()
,int64Now = dtNow.toMSecsSinceEpoch()
,int64Diff = int64Now - int64Created;
//Is the file current and being updated?
if ( int64Diff < (mcintDelay * 2) ) {
//PID file is live, read it
if ( objPID.open(QIODevice::ReadOnly) == true ) {
//PID file exists, it should only contain a single ID
QByteArray arybytContent = objPID.readAll();
QString strContent = arybytContent.trimmed();
objPID.close();
if ( strContent.toLongLong() != mint64PID ) {
qInfo("Another instance already present...");
exit(EXIT_FAILURE);
}
}
}
}
//Create / update PID file
if ( objPID.open(QIODevice::WriteOnly) == true ) {
QString strPID = QString::number(mint64PID);
objPID.write(strPID.toLatin1());
objPID.close();
}
}