2009-09-25 12 views
74

लिनक्स में, डिस्क की ब्लॉक को पढ़ने की आवश्यकता होने पर प्रक्रिया की स्थिति का क्या होता है? क्या यह अवरुद्ध है? यदि हां, तो निष्पादित करने के लिए एक और प्रक्रिया कैसे चुनी जाती है?लिनक्स प्रक्रिया राज्य

उत्तर

70

फ़ाइल डिस्क्रिप्टर रिटर्न से read() या write() के लिए प्रतीक्षा करते समय, प्रक्रिया को विशेष प्रकार की नींद में रखा जाएगा, जिसे "डी" या "डिस्क स्लीप" के नाम से जाना जाता है। यह विशेष है, क्योंकि ऐसी स्थिति में प्रक्रिया को मार या बाधित नहीं किया जा सकता है। Ioctl() से वापसी के लिए प्रतीक्षा की जाने वाली प्रक्रिया को भी इस तरह सोया जाएगा।

इसका अपवाद तब होता है जब O_NONBLOCK मोड में एक फ़ाइल (जैसे टर्मिनल या अन्य वर्ण डिवाइस) खोला जाता है, जब यह माना जाता है कि डिवाइस (जैसे मॉडेम) को आरंभ करने के लिए समय की आवश्यकता होगी। हालांकि, आपने अपने प्रश्न में ब्लॉक डिवाइस इंगित किए हैं। इसके अलावा, मैंने कभी भी ioctl() की कोशिश नहीं की है जो गैर अवरोधन मोड में खोले गए एफडी पर अवरुद्ध होने की संभावना है (कम से कम जानबूझकर नहीं)।

कैसे किसी अन्य प्रक्रिया से चुना जाता है अनुसूचक आप उपयोग कर रहे हैं, साथ ही क्या अन्य प्रक्रियाओं है कि अनुसूचक के भीतर उनके वजन को संशोधित करने के लिए किया हो सकता है के रूप में पर पूरी तरह से निर्भर करता है। कुछ निश्चित परिस्थितियों में

कुछ उपयोगकर्ता अंतरिक्ष कार्यक्रमों, हमेशा के लिए इस राज्य में रहने के लिए जाने जाते हैं जब तक रिबूट। ये आम तौर पर अन्य "लाश" के साथ समूहित होते हैं, लेकिन यह शब्द सही नहीं होगा क्योंकि वे तकनीकी रूप से निष्क्रिय नहीं हैं।

+1

"आईओक्टएल() से वापसी के लिए प्रतीक्षा की जाने वाली प्रक्रिया को भी इस तरह सोया जाएगा"। मैंने अपनी आईएससीटीएल को अवरुद्ध करने पर इंतजार कर मेरी यूजर स्पेस प्रक्रिया को मार दिया है, इसलिए यह सच नहीं है। जब तक कि मैं – Hamzahfrq

+0

की गलतफहमी नहीं कर रहा हूं, इस तरह के परीक्षण के लिए यह बेहद मुश्किल होगा। अनियंत्रित प्रक्रियाओं को मार नहीं सकता है; यदि आप इसे मारने में सक्षम थे, तो यह केवल अवरुद्ध था (कर्नेल ioctl के किसी भी हिस्से के बीच में नहीं था, और आपके द्वारा पारित स्थान पर उपयोगकर्ता स्थान पर किसी भी संबंधित प्रतिक्रिया की प्रतिलिपि बनाई गई थी (या कम से कम नहीं थी प्रतिलिपि के बीच))। 200 9 से लिनक्स ने _a lot_ भी बदल दिया है जब यह लिखा गया था; यह घटना बहुत कम देखने योग्य है क्योंकि यह एक बार था। विस्तृत प्रतिक्रिया के लिए –

1

अपनी प्रक्रिया मान लिया जाये कि किसी एकल थ्रेड है, और आप अवरुद्ध I/O, अपनी प्रक्रिया आई/ओ को पूरा करने के लिए इंतज़ार कर रहे अवरुद्ध कर देगा का उपयोग कर रहे हैं। कर्नेल एकमात्र प्रक्रिया को प्राथमिकता, प्राथमिकता, अंतिम रन टाइम इत्यादि के आधार पर चलाने के लिए चुन देगा। यदि कोई अन्य रनने योग्य प्रक्रिया नहीं है, तो कर्नेल कोई नहीं चलाएगा; इसके बजाए, यह हार्डवेयर को बताएगा कि मशीन निष्क्रिय है (जिसके परिणामस्वरूप कम बिजली की खपत होगी)।

प्रक्रियाएं जो I/O को पूरा करने की प्रतीक्षा कर रही हैं आम तौर पर राज्य डी में दिखाई देती हैं, उदाहरण के लिए, ps और top

+0

मैंने कुल मेमोरी के लगभग 10% का उपयोग करके कई प्रक्रियाएं लॉन्च कीं। मैंने देखा कि उनमें से कई डी राज्य में हैं। क्या यह इस विशेष मशीन पर धीमी आईओ के कारण है? मान लें कि मेरे पास 9 प्रक्रियाएं हैं, वे आईओ के लिए प्रतिस्पर्धा कर सकते हैं और उनमें से कई डी राज्य में हैं। –

+0

@ केमिनज़ौ सीपीयू की गति की तुलना में, I/O बहुत धीमी है-यहां तक ​​कि तेज़ I/O है। एक एकल I/O भारी प्रक्रिया चुंबकीय डिस्क, यहां तक ​​कि एक एसएसडी भी व्यस्त हो सकती है। 10 आई/ओ भारी प्रक्रियाएं काफी व्यस्त हो सकती हैं। – derobert

0

हां, आईओ के लिए इंतजार कर रहे कार्यों को अवरुद्ध कर दिया गया है, और अन्य कार्यों को निष्पादित किया गया है। अगला कार्य चुनना Linux scheduler द्वारा किया जाता है।

0

आम तौर पर प्रक्रिया अवरुद्ध हो जाएगी। यदि रीड ऑपरेशन गैर-अवरुद्ध के रूप में चिह्नित फ़ाइल डिस्क्रिप्टर पर है या यदि प्रक्रिया एसिंक्रोनस आईओ का उपयोग कर रही है तो यह अवरुद्ध नहीं होगी। इसके अलावा यदि प्रक्रिया में अन्य धागे हैं जो अवरुद्ध नहीं हैं तो वे चलना जारी रख सकते हैं।

निर्णय जो के रूप में प्रक्रिया अगले चलाता है कर्नेल में scheduler पर निर्भर है।

6

आई/ओ प्रदर्शन करने वाली एक प्रक्रिया डी स्थिति (अनइंटरप्टेबल नींद) में रखी जाएगी, जो सीपीयू को मुक्त करता है जब तक कोई हार्डवेयर इंटरप्ट नहीं होता है जो सीपीयू को प्रोग्राम को निष्पादित करने के लिए वापस लौटाता है। अन्य प्रक्रिया राज्यों के लिए man ps देखें।

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

2 में।6 कर्नेल, ओ (1) समय जटिलता शेड्यूलर है, इसलिए कोई फर्क नहीं पड़ता कि आप कितनी प्रक्रियाएं चल रहे हैं, यह निरंतर समय में CPU को असाइन करेगा। हालांकि यह अधिक जटिल है, चूंकि 2.6 ने पेश किया प्रमोशन और सीपीयू लोड संतुलन एक आसान एल्गोरिदम नहीं है। किसी भी मामले में, यह कुशल है और I/O की प्रतीक्षा करते समय CPUs निष्क्रिय नहीं रहेंगे।

1

हां, कार्य को पढ़ने() सिस्टम कॉल में अवरुद्ध हो जाता है। एक और काम जो तैयार है, या यदि कोई अन्य कार्य तैयार नहीं है, तो निष्क्रिय कार्य (उस सीपीयू के लिए) चलता है।

एक सामान्य, अवरुद्ध डिस्क पढ़ने से कार्य "डी" स्थिति में प्रवेश करने का कारण बनता है (जैसा कि अन्य ने नोट किया है)। ऐसे कार्य लोड औसत में योगदान देते हैं, भले ही वे सीपीयू का उपभोग नहीं कर रहे हों।

कुछ अन्य प्रकार के आईओ, विशेष रूप से ttys और नेटवर्क, काफी समान व्यवहार नहीं करते हैं - प्रक्रिया "एस" स्थिति में समाप्त होती है और इसे बाधित किया जा सकता है और लोड औसत के खिलाफ नहीं गिना जाता है।

112

जब किसी प्रक्रिया को डिस्क से डेटा लाने की आवश्यकता होती है, तो यह प्रभावी ढंग से CPU पर चलने से रोकता है ताकि अन्य प्रक्रियाएं चल सकें क्योंकि ऑपरेशन को पूरा करने में लंबा समय लग सकता है - कम से कम 5ms डिस्क की तलाश सामान्य है, और 5 एमएमएस 10 मिलियन सीपीयू चक्र है, कार्यक्रम के दृष्टिकोण से अनंत काल!

प्रोग्रामर बिंदु से ("उपयोगकर्ता स्थान में" भी कहा जाता है) से इसे अवरुद्ध सिस्टम कॉल कहा जाता है। यदि आप write(2) (जो एक ही नाम की सिस्टम कॉल के आस-पास एक पतली libc wrapper है) को कॉल करते हैं, तो आपकी प्रक्रिया बिल्कुल उस सीमा पर नहीं रुकती है: यह कर्नेल पक्ष पर, सिस्टम कॉल कोड चला रहा है। अधिकांश समय यह एक विशिष्ट डिस्क नियंत्रक ड्राइवर (फ़ाइल नाम → फाइल सिस्टम/वीएफएस → ब्लॉक डिवाइस → डिवाइस ड्राइवर) तक जाता है, जहां डिस्क पर ब्लॉक लाने के लिए एक आदेश उचित हार्डवेयर पर सबमिट किया जाता है: यह एक बहुत है ज्यादातर समय तेजी से ऑपरेशन।

तो प्रक्रिया नींद राज्य में डाल दिया जाता है (कर्नेल अंतरिक्ष में, अवरुद्ध नींद कहा जाता है - कुछ भी नहीं कभी देखने की गिरी बिंदु से 'अवरुद्ध' है)। एक बार हार्डवेयर ने अंततः उचित डेटा प्राप्त करने के बाद फिर से जागृत हो जाएगा, फिर प्रक्रिया को रननेबल के रूप में चिह्नित किया जाएगा, शेड्यूलर जितनी जल्दी हो सके निर्धारित और चलाएगा।

अंत में उपयोगकर्ता स्पेस में ब्लॉकिंग सिस्टम कॉल उचित स्थिति और डेटा के साथ लौटाता है, और प्रोग्राम प्रवाह चालू रहता है।

यह सबसे आई/ओ प्रणाली को लागू करने के लिए संभव है कॉल में गैर अवरुद्ध मोड (O_NONBLOCKopen(2) और fcntl(2) में देखें)। इस मामले में, सिस्टम तुरंत वापसी करता है और केवल डिस्क ऑपरेशन के उचित सबमिशन के बारे में बताता है। यदि ऑपरेशन सफलतापूर्वक पूरा नहीं हुआ है, तो इसके बाद प्रोग्रामर को बाद में जांच करनी होगी, और इसके परिणाम प्राप्त करें (उदा। select(2) के साथ)। इसे एसिंक्रोनस या इवेंट आधारित प्रोग्रामिंग कहा जाता है।

अधिकतर उत्तर डी राज्य का उल्लेख करते हैं (जो सटीक नाम TASK_UNINTERRUPTIBLE लिनक्स के नाम से) गलत है। डी राज्य एक विशेष नींद मोड है जो केवल कर्नेल स्पेस कोड पथ में ट्रिगर होता है, जब उस कोड पथ को में बाधित नहीं किया जा सकता है (क्योंकि यह प्रोग्राम के लिए जटिल होगा), आशा में अधिकांश समय कि यह बहुत जल्द ब्लॉक करेगा। मेरा मानना ​​है कि अधिकांश "डी राज्य" वास्तव में अदृश्य हैं, वे बहुत कम रहते हैं और 'टॉप' जैसे नमूने उपकरण द्वारा देखे जा सकते हैं।

लेकिन कभी-कभी आप कुछ स्थितियों में डी राज्य में उन अकुशल प्रक्रियाओं का सामना करेंगे। एनएफएस उस के लिए प्रसिद्ध है, और मैंने इसे कई बार सामना किया है। मुझे लगता है कि कुछ वीएफएस कोड पथों के बीच एक अर्थपूर्ण संघर्ष है जो हमेशा स्थानीय डिस्क तक पहुंचने और तेजी से त्रुटि का पता लगाने (एसएटीए पर, एक त्रुटि टाइमआउट लगभग 100 एमएस के आसपास होगा), और एनएफएस जो वास्तव में नेटवर्क से डेटा प्राप्त करता है जो अधिक है लचीला और धीमी वसूली है (300 सेकंड का एक टीसीपी टाइमआउट आम है)। लिनक्स 2.6.25 में TASK_KILLABLE राज्य के साथ पेश किए गए अच्छे समाधान के लिए this article पढ़ें। इस युग से पहले एक हैक था जहां आप वास्तव में कर्नेल थ्रेड rpciod पर सिगकिल भेजकर एनएफएस प्रोसेस क्लाइंट को सिग्नल भेज सकते थे, लेकिन उस बदसूरत चाल और नरक के बारे में भूल जाओ;

+2

+1, लेकिन कृपया ध्यान दें कि इस धागे के पास लगभग दो वर्षों के लिए एक स्वीकार्य उत्तर है। यदि आप हाल के प्रश्नों पर हाथ उधार देना चाहते हैं तो "प्रश्न" लिंक दबाएं। स्टैक ओवरफ़्लो में आपका स्वागत है, और योगदान के लिए धन्यवाद! – GargantuChet

+17

यह उत्तर एनएफएस का उल्लेख करने वाला एकमात्र ऐसा है, जो कुछ वातावरण में डी राज्य में प्रक्रियाओं के लिए सबसे आम व्याख्या है। +1। – Pinko

+12

बहुत अच्छा जवाब, धन्यवाद। यह भी ध्यान रखें कि प्रक्रियाएं डी राज्य में जाती हैं, जबकि उन पृष्ठों की प्रतीक्षा कर रही है, जिन्हें अलग-अलग किया गया है, इसलिए लंबे समय तक डी राज्य में एक थ्रैशिंग प्रक्रिया होगी। – cha0site

2

जैसा कि पहले से ही दूसरों द्वारा समझाया गया है, "डी" स्थिति (अनियंत्रित नींद) में प्रक्रियाएं पीएस प्रक्रिया के लटकने के लिए जिम्मेदार हैं। मेरे लिए यह RedHat 6.x और स्वचालित एनएफएस होम निर्देशिकाओं के साथ कई बार हुआ है।

डी राज्य में प्रक्रियाओं आप निम्न कमांड का उपयोग कर सकते सूचीबद्ध करने के लिए:

cd /proc 
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D 

प्रक्रिया के वर्तमान निर्देशिका पता करने के लिए और, हो सकता है, घुड़सवार एनएफएस डिस्क संबंधी समस्याएं हो सकती है कि आप एक आदेश समान उपयोग कर सकते हैं निम्न उदाहरण (नींद की प्रक्रिया संख्या के साथ 31134 की जगह) के लिए:

# ls -l /proc/31134/cwd 
lrwxrwxrwx 1 pippo users 0 Aug 2 16:25 /proc/31134/cwd -> /auto/pippo 

मैंने पाया कि -f साथ umount आदेश दे (बल) स्विच से संबंधित NFS फाइल सिस्टम घुड़सवार, wake- करने में सक्षम था नींद की प्रक्रिया ऊपर:

umount -f /auto/pippo 

फ़ाइल सिस्टम को अनमाउंट नहीं किया गया था, क्योंकि यह व्यस्त था, लेकिन संबंधित प्रक्रिया जागृत हुई और मैं बिना किसी रीबूट किए समस्या को हल करने में सक्षम था।

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