2010-06-03 4 views
5

पर एकाधिक प्रक्रिया उदाहरणों को रोकना प्रक्रिया के लिए लिनक्स प्लेटफार्म (सी ++ एप्लिकेशन) पर सबसे अच्छा तरीका क्या है इसका उदाहरण जांचने के लिए पहले से नहीं चल रहा है?लिनक्स

उत्तर

5

ऐसा करने का मानक तरीका कहीं भी एक पिडफाइल बनाना है, आमतौर पर आपके प्रोग्राम का ढक्कन होता है।

आपको वहां पिड डालने की आवश्यकता नहीं है, आप बस उस पर एक विशेष लॉक लगा सकते हैं। यदि आप इसे पढ़ने/लिखने के लिए खोलते हैं और इसे LOCK_EX के साथ फ़्लॉक करते हैं LOCK_NB, अगर फ़ाइल पहले ही लॉक हो चुकी है तो यह असफल हो जाएगी। यह दौड़-स्थिति मुक्त है, और यदि प्रोग्राम क्रैश हो जाता है तो लॉक स्वचालित रूप से रिलीज़ हो जाएगा।

आम तौर पर आप इसे प्रति उपयोगकर्ता करना चाहते हैं, इसलिए उपयोगकर्ता की होम निर्देशिका फ़ाइल को रखने के लिए एक अच्छी जगह है।

यदि यह एक डिमन है, तो कहीं/var/run बेहतर है।

4

आप इसे पूरा करने के लिए फ़ाइलों और फ़ाइल ताले का उपयोग कर सकते हैं, लेकिन, सावधान रहें कि यह सही नहीं है और कुख्यात फ़ायरफ़ॉक्स बग की प्रतिलिपि न लें जहां यह कभी-कभी शुरू नहीं हो रहा है, भले ही यह पहले से चलने से इंकार कर दे।

इसके बारे में बुनियादी तर्क है:

Invariant: 
    File xxxxx will exist if and only if the program is running, and the 
    contents of the file will contain the PID of that program. 

On startup: 
    If file xxxxx exists: 
     If there is a process with the PID contained in the file: 
      Assume there is some instance of the program, and exit 
     Else: 
      Assume that the program terminated abnormally, and 
      overwrite file xxxx with the PID of this program 
    Else: 
     Create file xxxx, and save the current PID to that file. 

On termination (typically registered via atexit): 
    Delete file xxxxx 

ऊपर तर्क के अलावा, आप भी एक दूसरे फ़ाइल आप पीआईडी ​​फ़ाइल तक पहुँच सिंक्रनाइज़ करने में बंद का उपयोग करना चाहिए (यानी एक के रूप में कार्य करने के लिए प्रक्रिया-स्तर समेकन के मामले में इसे सुरक्षित बनाने के लिए म्यूटेक्स)।

+0

क्या फ़ाइल के बजाए सॉकेट का उपयोग करना आसान नहीं होगा और एक पूर्वनिर्धारित बंदरगाह से बांधने का प्रयास करें? और, वैसे, मैं सभी पिड सत्यापन के बिना फ़ाइल लॉकिंग का उपयोग क्यों नहीं कर सकता? – jackhab

+0

@ जैक, आप इसे पीआईडी ​​सत्यापन के बिना कर सकते हैं, लेकिन फिर आप यह मानने का जोखिम चलाते हैं कि प्रोग्राम वास्तव में क्रैश हो गया है और फ़ाइल को साफ करने में विफल रहा है (फ़ायरफ़ॉक्स समस्या को सोचें)। इसके अलावा, राकिस एक अच्छा बिंदु लाता है, जो कि लिनक्स पर है, आप यह सत्यापित कर सकते हैं कि पीआईडी ​​'/ proc' में डेटा का उपयोग करके आपके प्रोग्राम से संबंधित है ... यूनिक्स रूपों में अधिक सामान्य रूप से ऐसा करने के प्रोग्रामेटिक तरीके हैं (कम से कम आप "पीएस" का आह्वान कर सकते हैं और इसके आउटपुट को पार्स कर सकते हैं, हालांकि मुझे लगता है कि ऐसे कार्य हो सकते हैं जिन्हें आप सीधे प्रक्रिया की जानकारी प्राप्त करने के लिए बुला सकते हैं)।एक प्रक्रिया के अस्तित्व की जांच के लिए –

+1

, कॉल मार (पिड, 0)। जब प्रक्रिया मौजूद होती है तो यह सफल होता है, अन्यथा विफल रहता है। एक अलग मशीन पर चल रही प्रक्रिया से सावधान रहें! – Arkadiy

1

माइकल के समाधान के लिए एक संबंधित विकल्प एक ज्ञात स्थान (संभवतः/var/run या/tmp) में निर्देशिका बनाना है और पारस्परिक बहिष्करण सुनिश्चित करने के लिए तंत्र के रूप में सिस्टम कॉल की सफलता/विफलता का उपयोग करना है। यह वही पारस्परिक-बहिष्करण चाल है जिसे सीवीएस ने वर्षों से उपयोग किया है क्योंकि निर्देशिका निर्माण अधिकांश (शायद सभी) कमोडिटी ओएस पर परमाणु है। एक पीआईडी ​​फ़ाइल अभी भी उस मामले में उपयोगी है जहां निर्देशिका + पीआईडी ​​बनाने की प्रक्रिया अप्रत्याशित रूप से मर जाती है और इसे साफ करने में विफल रहता है। इसके अतिरिक्त, यह देखने के लिए कि मौजूदा निर्देशिका + पीआईडी ​​मान्य है या नहीं, मैं स्पष्ट रूप से /proc/<PID>/exe सिम्लिंक की जांच करने का सुझाव देता हूं ताकि यह सत्यापित किया जा सके कि यह आपके निष्पादन योग्य को इंगित करता है कि पीआईडी ​​को पुनर्नवीनीकरण नहीं किया गया है।

-1

ऐसा करने के लिए आप POSIX named semaphore का उपयोग कर सकते हैं। फ़ाइल लॉक का उपयोग करने से यह अधिक सुरक्षित है।

+0

सैमफोर को साफ किए बिना क्रैश किए गए प्रोग्राम के साथ यह कैसे व्यवहार करता है? मैन पेज से –

+0

: सेमफोर नामक पॉज़िक्स में कर्नेल दृढ़ता है: अगर sem_unlink() द्वारा नहीं हटाया जाता है, तो सिस्टम बंद होने तक एक सेमफोर मौजूद होगा। क्रैश निश्चित रूप से यहां एक समस्या होगी। – jackhab

0

डेस्कटॉप ऐप के लिए, यह जांचने के लिए शायद अधिक संभव है कि वर्तमान उपयोगकर्ता के लिए कोई उदाहरण प्रारंभ हो गया है, ताकि दो उपयोगकर्ता अपने स्वयं के उदाहरण चल सकें।

आप या तो कुछ पुस्तकालयों (libunique (जीटीके +) या QtSingleApplication (क्यूटी) का उपयोग कर सकते हैं, या इसे स्वयं कर सकते हैं। पहले वर्णित पिड-फाइल के अलावा, आप उपयोगकर्ता की होम निर्देशिका में कहीं भी फीफो या यूनिक्स-डोमेन सॉकेट खोल सकते हैं। इस तरह, आप चल रहे उदाहरण के साथ संवाद कर सकते हैं, उदाहरण के लिए। चल रहे इंस्टेंस की विंडो बढ़ाएं या नई फाइल/यूआरआई/जो कुछ भी खोलने के लिए चल रहे इंस्टेंस को बताएं।