2009-02-26 25 views
8

मुझे एहसास है कि "तेज़" थोड़ा सा व्यक्तिपरक है इसलिए मैं कुछ संदर्भ के साथ समझाऊंगा। मैं क्रॉस-प्लेटफार्म तरीके से प्रक्रिया की जानकारी पढ़ने के लिए psutil नामक एक पायथन मॉड्यूल पर काम कर रहा हूं। यह निर्धारित करने के लिए कि कोई पीआईडी ​​वर्तमान प्रक्रिया सूची में है या नहीं, कार्यों में से एक pid_exists(pid) फ़ंक्शन है।यह निर्धारित करने का तेज़ तरीका है कि एक पीआईडी ​​(विंडोज) पर मौजूद है या नहीं?

अभी प्रक्रिया प्रक्रिया खींचने के लिए EnumProcesses() का उपयोग करके, मैं सूची के माध्यम से बातचीत कर रहा हूं और पीआईडी ​​की तलाश में यह स्पष्ट तरीका कर रहा हूं। हालांकि, कुछ सरल बेंचमार्किंग से पता चलता है कि यह यूनिक्स-आधारित प्लेटफ़ॉर्म (लिनक्स, ओएस एक्स, फ्रीबीएसडी) पर pid_exists फ़ंक्शन से नाटकीय रूप से धीमा है, जहां हम kill(pid, 0) का उपयोग 0 सिग्नल के साथ कर रहे हैं यह निर्धारित करने के लिए कि कोई पीआईडी ​​मौजूद है या नहीं। अतिरिक्त परीक्षण से पता चलता है कि यह एनमप्रोसेसेस है जो लगभग हर समय उठा रहा है।

कोई भी पीआईडी ​​मौजूद है या नहीं, यह निर्धारित करने के लिए EnumProcesses का उपयोग करने से किसी को भी तेज़ तरीका पता है? मैंने OpenProcess() की कोशिश की और बिना किसी प्रक्रिया की प्रक्रिया को खोलने में त्रुटि की जांच की, लेकिन यह EnumProcesses सूची के माध्यम से पुनरावृत्ति से 4x धीमी हो गई, इसलिए यह भी बाहर है। कोई अन्य (बेहतर) सुझाव?

नोट: यह एक पायथन लाइब्रेरी है जिसका उद्देश्य तृतीय-पक्ष lib निर्भरताओं जैसे pywin32 एक्सटेंशन से बचने के लिए है। मुझे एक ऐसे समाधान की आवश्यकता है जो हमारे वर्तमान कोड से तेज़ है, और यह मानक पायथन वितरण में मौजूद नहीं है pywin32 या अन्य मॉड्यूल पर निर्भर नहीं है।

EDIT: स्पष्टीकरण के लिए - हम अच्छी तरह से जानते हैं कि पढ़ने की प्रक्रिया में अंतर्निहित दौड़ की स्थिति है। डेटा संग्रह के दौरान प्रक्रिया समाप्त होने पर हम अपवाद उठाते हैं या हम अन्य समस्याओं में भाग लेते हैं। Pid_exists() फ़ंक्शन उचित त्रुटि हैंडलिंग को प्रतिस्थापित करने का इरादा नहीं है।

अद्यतन: जाहिरा तौर पर मेरे पहले बेंचमार्क त्रुटिपूर्ण थे - मैं सी में कुछ साधारण परीक्षण ऐप्स और EnumProcesses लगातार बाहर आता है धीमी और OpenProcess (मामले में GetProcessExitCode साथ संयोजन के रूप में पीआईडी ​​मान्य है, लेकिन प्रक्रिया बंद कर दिया है) वास्तव में है लिखा था बहुत तेज धीमी नहीं है।

उत्तर

8

OpenProcess आपको बताएगा कि आप सभी को बताएंगे। मुझे नहीं पता कि कितनी तेज़ है।

संपादित: ध्यान दें कि आप भी GetExitCodeProcess जरूरत है, भले ही आप OpenProcess से एक संभाल पाने की प्रक्रिया के राज्य सत्यापित करने के लिए।

+0

मेरे पिछले परीक्षण के बावजूद बाहर निकलता है यह सब के बाद जाने का बेहतर तरीका है। रुचि रखते हैं तो विवरण के लिए मेरा जवाब देखें। – Jay

4

pid_exists फ़ंक्शन के उपयोग में एक अंतर्निहित दौड़ स्थिति है: जब तक कॉलिंग प्रोग्राम उत्तर का उपयोग करने के लिए हो जाता है, तब तक प्रक्रिया पहले ही गायब हो सकती है, या पूछे गए आईडी के साथ एक नई प्रक्रिया बनाई जा सकती है। मैं कहूंगा कि इस फ़ंक्शन का उपयोग करने वाले किसी भी एप्लिकेशन को डिज़ाइन द्वारा त्रुटिपूर्ण किया गया है और इस फ़ंक्शन को अनुकूलित करने के लिए यह प्रयास के लायक नहीं है।

+0

हां, हमारी लाइब्रेरी समेत किसी भी पीएस जैसे एप्लिकेशन में अंतर्निहित दौड़ की स्थिति है। हालांकि, इस फ़ंक्शन में अभी भी वैध उपयोग के मामले हैं। ध्यान दें कि डेटा संग्रह प्रक्रिया के दौरान किसी भी समय अगर हम प्रक्रिया गायब हो जाते हैं तो हम अपवाद भी उठा रहे हैं। – Jay

3

यह पता चला है कि मेरे मानक स्पष्ट रूप से त्रुटिपूर्ण थे, क्योंकि बाद में परीक्षण से पता चलता है कि OpenProcess और GetExitCodeProcess EnumProcesses का उपयोग करने से कहीं अधिक तेज़ हैं। मुझे यकीन है कि क्या हुआ नहीं हूँ, लेकिन मैं कुछ नए परीक्षण किया था और सत्यापित यह तेजी से समाधान है:

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() PIDs है कि किसी भी वैध पीआईडी ​​के 3 के भीतर हैं के लिए सफल होता है (Why does OpenProcess succeed even when I add three to the process ID? देखें)

+0

उस अंतिम नोट के लिए धन्यवाद, मैं डेस्क पर अपने सिर को टक्कर दे रहा था कि क्यों एक पूरी तरह से मौजूद पीआईडी ​​सच नहीं हो रहा था। –

3

मैं जे के अंतिम समारोह इस तरह से कोड चाहते हैं।

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 को बदलने) का मौका देता है।

+0

हम इस मामले में इंतजार नहीं करना चाहते हैं (अन्य फ़ंक्शन कॉल का पता लगाएगा कि प्रक्रिया ने खुद को बंद कर दिया है और पायथन के लिए अपवाद बढ़ाया है)। लेकिन, आप प्रक्रिया हैंडल को बंद करने के बारे में सही हैं ... हमारा "वास्तविक" कोड हैंडल बंद करता है लेकिन मैं इसे पोस्ट किए गए नमूने में करना भूल गया। – Jay

संबंधित मुद्दे

 संबंधित मुद्दे