문제

나는 "빠른"것이 약간 주관적이라는 것을 알고 있으므로 어떤 맥락으로 설명 할 것입니다. 나는 호출 된 파이썬 모듈을 작업하고 있습니다 psutil 크로스 플랫폼 방식으로 프로세스 정보를 읽는 것. 함수 중 하나는 a pid_exists(pid) PID가 현재 프로세스 목록에 있는지 결정하는 기능.

지금 나는 이것을 사용하여 이것을 사용하고 있습니다. 열거적인 () 프로세스 목록을 가져 오려면 목록을 통해 상호 작용하고 PID를 찾고 있습니다. 그러나 일부 간단한 벤치마킹은 이것이 우리가 사용하는 UNIX 기반 플랫폼 (Linux, OS X, FreeBSD)의 PID_Exists 기능보다 크게 느립니다. kill(pid, 0) PID가 존재하는지 확인하기 위해 0 신호를 사용합니다. 추가 테스트에 따르면 거의 항상 열거하는 열거 프로세스임을 보여줍니다.

PID가 존재하는지 판단하기 위해 열렬한 프로세스를 사용하는 것보다 빠른 방법을 알고 있습니까? 나는 시도했다 OpenProcess () 그리고 존재하지 않는 프로세스를 여는 오류를 확인하지만, 이는 열렬한 프로세스 목록을 통해 반복하는 것보다 4 배 이상 느린 것으로 판명되었습니다. 다른 (더 나은) 제안이 있습니까?

노트: 이것은 pywin32 확장과 같은 타사 LIB 종속성을 피하기위한 파이썬 라이브러리입니다. 현재 코드보다 빠른 솔루션이 필요하며 표준 파이썬 분포에 존재하지 않는 Pywin32 또는 기타 모듈에 의존하지 않습니다.

편집하다: 명확히하기 위해 - 우리는 읽기 과정 iformation에 내재 된 인종 조건이 있다는 것을 잘 알고 있습니다. 데이터 수집 과정에서 프로세스가 사라지거나 다른 문제가 발생하면 예외가 제외됩니다. pid_exists () 함수는 올바른 오류 처리를 대체하기위한 것이 아닙니다.

업데이트: 명백히 내 초기 벤치 마크가 결함이 있었다 - 나는 C로 간단한 테스트 앱을 작성했으며 열거 된 프로세스는 일관되게 느리게 나오고 개방형 프로세스 (PID가 유효하지만 프로세스가 중지 된 경우 getProcessExItcode와 함께)가 일관되게 나옵니다. 더 빠르게 느리지 않습니다.

도움이 되었습니까?

해결책

개방 처리 모든 것을 열거하는 것을 말할 수 있습니다. 얼마나 빨리 모르겠습니다.

편집하다: 당신도 필요합니다 GetExitCodeProcess 손잡이를 얻더라도 프로세스의 상태를 확인하려면 OpenProcess.

다른 팁

PID_Exists 기능을 사용하는 데 고유 한 레이스 조건이 있습니다. 호출 프로그램이 답을 사용하거나 프로세스가 이미 사라 졌거나 쿼리 된 ID가있는 새로운 프로세스가 생성되었을 수 있습니다. 이 기능을 사용하는 응용 프로그램은 설계에 의해 결함이 있으며이 기능을 최적화하는 것은 노력의 가치가 없다고 감히 말할 것입니다.

나중에 테스트가 OpenProcess를 드러내고 GetExItcodeProcess가 결국 열렬한 프로세스를 사용하는 것보다 훨씬 빠릅니다. 무슨 일이 있었는지 잘 모르겠지만 새로운 테스트를했고 이것이 더 빠른 해결책임을 확인했습니다.

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에 대한 성공 (참조 프로세스 ID에 3을 추가하더라도 OpenProcess가 성공합니까?)

나는 Jay의 마지막 기능을 이런 식으로 코딩합니다.

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;
    }
    DWORD dwRetval = WaitForSingleObject(hProcess, 0);
    CloseHandle(hProcess); // otherwise you'll be losing handles

    switch(dwRetval) {
    case WAIT_OBJECT_0;
        return 0;
    case WAIT_TIMEOUT;
        return 1;
    default:
        return -1;
    }
}

주요 차이점은 프로세스 핸들 (이 기능의 클라이언트가 오랫동안 실행중인 경우 중요)과 프로세스 종료 감지 전략을 닫는 것입니다. WaitforsingleObject는 프로세스가 끝날 때까지 잠시 기다릴 수있는 기회를 제공합니다 (0을 함수 매개 변수 값으로 변경).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top