快速确定(Windows)上是否存在PID的方法?

2024-05-13 19:00:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我意识到“快”有点主观,所以我会解释一些上下文。我正在开发一个名为psutil的Python模块,用于以跨平台的方式读取流程信息。其中一个函数是用于确定PID是否在当前进程列表中的pid_exists(pid)函数。

现在,我以一种显而易见的方式来做这件事,使用EnumProcesses()来拉取进程列表,然后遍历列表并查找PID。但是,一些简单的基准测试表明,这比基于UNIX平台(Linux、OS X、FreeBSD)上的pid撸exists函数要慢得多,在这些平台上,我们使用带0信号的kill(pid, 0)来确定pid是否存在。额外的测试显示,几乎所有的时间都在占用枚举进程。

有谁知道比使用枚举进程确定PID是否存在更快的方法吗?我试着OpenProcess()并检查打开不存在的进程时是否有错误,但这比遍历enumprocess列表慢了4倍多,所以这也算出来了。还有其他(更好的)建议吗?

注意:这是一个Python库,旨在避免pywin32扩展等第三方lib依赖项。我需要一个比我们当前代码更快的解决方案,它不依赖于pywin32或标准Python发行版中没有的其他模块。

编辑:为了澄清-我们很清楚阅读过程的形成有着固有的种族条件。如果在数据收集过程中进程消失或遇到其他问题,我们会引发异常。函数的作用不是要替换正确的错误处理。

更新:很明显,我以前的基准测试有缺陷——我用C编写了一些简单的测试应用程序,EnumProcesses总是输出得比较慢,而OpenProcess(如果PID有效但进程已停止,则与GetProcessExitCode一起)实际上要快得多,而不是慢得多。


Tags: 模块函数列表进程过程exists方式基准
3条回答

后来的测试显示OpenProcess和GetExitCodeProcess毕竟比使用enumprocess快得多,结果发现我的基准显然有缺陷。我不确定发生了什么,但我做了一些新的测试,并验证了这是更快的解决方案:

int pid_is_running(DWORD pid)
{
    HANDLE hProcess;
    DWORD exitCode;

    //Special case for PID 0 System Idle Process
    if (pid == 0) {
        return 1;
    }

    //skip testing bogus PIDs
    if (pid < 0) {
        return 0;
    }

    hProcess = handle_from_pid(pid);
    if (NULL == hProcess) {
        //invalid parameter means PID isn't in the system
        if (GetLastError() == ERROR_INVALID_PARAMETER) { 
            return 0;
        }

        //some other error with OpenProcess
        return -1;
    }

    if (GetExitCodeProcess(hProcess, &exitCode)) {
        CloseHandle(hProcess);
        return (exitCode == STILL_ACTIVE);
    }

    //error in GetExitCodeProcess()
    CloseHandle(hProcess);
    return -1;
}

注意,您确实需要使用GetExitCodeProcess(),因为OpenProcess()将在最近死亡的进程上成功,因此您不能假定有效的进程句柄表示该进程正在运行。

还要注意,OpenProcess()对于任何有效PID的3以内的PID都是成功的(请参见Why does OpenProcess succeed even when I add three to the process ID?

OpenProcess可能会告诉您不需要枚举所有内容。我不知道有多快。

编辑:请注意,您还需要GetExitCodeProcess来验证进程的状态,即使您从OpenProcess获得了句柄。

在使用pid_exists函数时存在一个固有的竞争条件:当调用程序使用应答时,进程可能已经消失,或者可能已经创建了一个具有查询id的新进程。我敢说,任何使用此功能的应用程序都存在设计缺陷,因此优化此功能是不值得的。

相关问题 更多 >