लिनक्स में, डिस्क से ब्लॉक पढ़ने की आवश्यकता होने पर एक प्रक्रिया की स्थिति क्या होती है? क्या यह अवरुद्ध है? यदि हां, तो निष्पादित करने के लिए एक और प्रक्रिया कैसे चुनी जाती है?
जवाबों:
फ़ाइल डिस्क्रिप्टर रिटर्न से read()
या उसके लिए प्रतीक्षा करते समय write()
, प्रक्रिया को एक विशेष प्रकार की नींद में रखा जाएगा, जिसे "डी" या "डिस्क स्लीप" के रूप में जाना जाता है। यह विशेष है, क्योंकि इस तरह की स्थिति में प्रक्रिया को मारा या बाधित नहीं किया जा सकता है। Ioctl () से वापसी की प्रतीक्षा करने वाली एक प्रक्रिया को भी इस तरीके से सोने के लिए रखा जाएगा।
इसका अपवाद तब होता है जब कोई फ़ाइल (जैसे कि टर्मिनल या अन्य वर्ण डिवाइस) O_NONBLOCK
मोड में खोली जाती है, तब पारित की जाती है जब यह मान लिया जाता है कि एक डिवाइस (जैसे मॉडेम) को आरंभ करने के लिए समय की आवश्यकता होगी। हालाँकि, आपने अपने प्रश्न में ब्लॉक उपकरणों का संकेत दिया है। इसके अलावा, मैंने कभी कोशिश नहीं की है ioctl()
कि गैर ब्लॉकिंग मोड में खोले गए fd पर ब्लॉक होने की संभावना है (कम से कम जानबूझकर नहीं)।
किसी अन्य प्रक्रिया को कैसे चुना जाता है यह पूरी तरह से उस शेड्यूलर पर निर्भर करता है जिसका आप उपयोग कर रहे हैं, साथ ही साथ इस शेड्यूलर के भीतर उनके वज़न को संशोधित करने के लिए अन्य प्रक्रियाओं ने क्या किया है।
कुछ परिस्थितियों में कुछ उपयोगकर्ता अंतरिक्ष कार्यक्रम रिबूट होने तक हमेशा के लिए इस स्थिति में बने रहने के लिए जाने जाते हैं। ये आम तौर पर अन्य "लाश" के साथ समूहीकृत होते हैं, लेकिन यह शब्द सही नहीं होगा क्योंकि वे तकनीकी रूप से खराब नहीं हैं।
जब एक प्रक्रिया को डिस्क से डेटा प्राप्त करने की आवश्यकता होती है, तो यह सीपीयू पर प्रभावी ढंग से बंद हो जाता है ताकि अन्य प्रक्रियाएं चल सकें क्योंकि ऑपरेशन को पूरा होने में लंबा समय लग सकता है - डिस्क के लिए कम से कम 5ms का समय सामान्य है, और 5ms 10 मिलियन है सीपीयू चक्र, कार्यक्रम के दृष्टिकोण से एक अनंत काल!
प्रोग्रामर के दृष्टिकोण से ("यूजर्सस्पेस में" भी कहा गया है), इसे ब्लॉकिंग सिस्टम कॉल कहा जाता है । यदि आप कॉल करते हैं write(2)
(जो एक ही नाम के सिस्टम कॉल के चारों ओर एक पतली libc आवरण है), तो आपकी प्रक्रिया उस सीमा पर बिल्कुल नहीं रुकती है; यह जारी है, कर्नेल में, सिस्टम कॉल कोड चला रहा है। अधिकांश समय यह एक विशिष्ट डिस्क नियंत्रक चालक (फ़ाइल नाम → फाइलसिस्टम / वीएफएस → ब्लॉक डिवाइस → डिवाइस ड्राइवर) तक जाता है, जहां डिस्क पर एक ब्लॉक लाने के लिए एक आदेश उचित हार्डवेयर को प्रस्तुत किया जाता है, जो बहुत ही महत्वपूर्ण है। तेजी से ऑपरेशन ज्यादातर समय।
जब इस प्रक्रिया को स्लीप अवस्था में रखा जाता है (कर्नेल स्पेस में, ब्लॉकिंग को स्लीपिंग कहा जाता है - कर्नेल बिंदु से कुछ भी 'अवरुद्ध' कभी नहीं होता)। एक बार जब हार्डवेयर ने उचित डेटा प्राप्त कर लिया है, तो यह जागृत हो जाएगा, फिर प्रक्रिया को चलाने योग्य के रूप में चिह्नित किया जाएगा और शेड्यूल किया जाएगा। आखिरकार, शेड्यूलर प्रक्रिया को चलाएगा।
अंत में, यूजरस्पेस में, अवरुद्ध प्रणाली उचित स्थिति और डेटा के साथ रिटर्न कॉल करती है, और प्रोग्राम फ्लो चलता है।
गैर-अवरोधक मोड (देखें और ) O_NONBLOCK
में अधिकांश I / O सिस्टम कॉल को लागू करना संभव है । इस स्थिति में, सिस्टम कॉल तुरंत वापस आती है और केवल डिस्क ऑपरेशन सबमिट करने की रिपोर्ट करती है। प्रोग्रामर को बाद में स्पष्ट रूप से जांचना होगा कि क्या ऑपरेशन पूरा हुआ, सफलतापूर्वक या नहीं, और इसका परिणाम प्राप्त करना (जैसे, साथ )। इसे एसिंक्रोनस या ईवेंट-आधारित प्रोग्रामिंग कहा जाता है।open(2)
fcntl(2)
select(2)
डी राज्य (जिसे TASK_UNINTERRUPTIBLE
लिनक्स राज्य नामों में कहा जाता है) का उल्लेख करने वाले अधिकांश उत्तर गलत हैं। डी राज्य एक विशेष स्लीप मोड जो केवल एक कर्नेल अंतरिक्ष कोड पथ, जब कि कोड पथ में शुरू हो रहा है है बाधित नहीं किया जा सकता है (क्योंकि यह कार्यक्रम करने के लिए बहुत जटिल हो जाएगा), उम्मीद के साथ कि यह केवल एक बहुत ही के लिए ब्लॉक कर देगा कम समय। मेरा मानना है कि अधिकांश "डी स्टेट्स" वास्तव में अदृश्य हैं; वे बहुत कम रहते हैं और 'टॉप' जैसे सैंपलिंग टूल्स द्वारा नहीं देखे जा सकते हैं।
आप कुछ स्थितियों में डी राज्य में अनजानी प्रक्रियाओं का सामना कर सकते हैं। एनएफएस उस के लिए प्रसिद्ध है, और मैंने इसे कई बार सामना किया है। मुझे लगता है कि कुछ वीएफएस कोड रास्तों के बीच एक शब्दार्थ झड़प है, जो हमेशा स्थानीय डिस्क और तेजी से त्रुटि का पता लगाने के लिए मानती है (एसएटीए पर, एक त्रुटि टाइमआउट लगभग 100 एमएस होगा), और एनएफएस, जो वास्तव में नेटवर्क से डेटा प्राप्त करता है जो अधिक लचीला है और इसमें धीमी गति से रिकवरी है (300 सेकंड का एक टीसीपी समय सामान्य है)। राज्य में लिनक्स 2.6.25 में पेश किए गए शांत समाधान के लिए इस लेख को पढ़ें TASK_KILLABLE
। इस युग से पहले एक हैक था जहाँ आप वास्तव में एनजीएस प्रोसेस क्लाइंट्स को एक संकेत भेज सकते हैं एक कर्नेल को कर्नेल थ्रेड पर भेजकर rpciod
, लेकिन उस बदसूरत चाल के बारे में भूल जाएं।…
/proc/stat
?
I / O करने वाली एक प्रक्रिया को D अवस्था (निर्बाध नींद) में रखा जाएगा , जो CPU को तब तक मुक्त करता है जब तक कि कोई हार्डवेयर व्यवधान न हो जो CPU को प्रोग्राम को निष्पादित करने के लिए वापस जाने के लिए कहता है। man ps
अन्य प्रक्रिया राज्यों के लिए देखें ।
आपके कर्नेल के आधार पर, एक प्रक्रिया अनुसूचक है , जो निष्पादित करने के लिए तैयार प्रक्रियाओं के एक रनवे का ट्रैक रखता है। यह एक शेड्यूलिंग एल्गोरिदम के साथ, कर्नेल को बताता है कि कौन सी सीपीयू को असाइन करना है। विचार करने के लिए कर्नेल प्रक्रियाएं और उपयोगकर्ता प्रक्रियाएं हैं। प्रत्येक प्रक्रिया को एक टाइम-स्लाइस आवंटित किया जाता है, जो कि सीपीयू समय का एक हिस्सा होता है जिसे इसका उपयोग करने की अनुमति है। एक बार जब प्रक्रिया अपने सभी टाइम-स्लाइस का उपयोग करती है, तो इसे समय-सीमा के रूप में चिह्नित किया जाता है और शेड्यूलिंग एल्गोरिदम में कम प्राथमिकता दी जाती है।
में 2.6 गिरी , वहाँ एक है हे (1) समय जटिलता अनुसूचक कितने प्रक्रियाओं द्वारा चलाए ऊपर है, यह लगातार समय में सीपीयू आवंटित करेगा, तो कोई बात नहीं। यह अधिक जटिल है, हालांकि 2.6 के बाद से प्रीमेशन और सीपीयू लोड बैलेंसिंग एक आसान एल्गोरिथ्म नहीं है। किसी भी मामले में, यह कुशल है और सीपीयू निष्क्रिय नहीं रहेगा, जब तक आप आई / ओ की प्रतीक्षा नहीं करते।
जैसा कि पहले से ही दूसरों द्वारा समझाया गया है, "डी" राज्य (निर्बाध नींद) में प्रक्रियाएं पीएस प्रक्रिया के लटकने के लिए जिम्मेदार हैं। मेरे लिए यह रेडहैट 6.x और ऑटोमैटिक एनएफएस होम डाइरेक्टरीज़ के साथ कई बार हुआ है।
डी राज्य में प्रक्रियाओं को सूचीबद्ध करने के लिए आप निम्नलिखित आदेशों का उपयोग कर सकते हैं:
cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D
प्रक्रिया की वर्तमान निर्देशिका को जानने के लिए और, हो सकता है कि माउंट की गई NFS डिस्क में आपके द्वारा निम्न उदाहरण के समान एक कमांड का उपयोग किया जा सकता है (31134 को स्लीपिंग प्रक्रिया संख्या के साथ बदलें):
# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug 2 16:25 /proc/31134/cwd -> /auto/pippo
मैंने पाया कि संबंधित माउंट किए गए nfs फाइल सिस्टम में -f (बल) स्विच के साथ umount कमांड देना, नींद की प्रक्रिया को जगाने में सक्षम था:
umount -f /auto/pippo
फ़ाइल सिस्टम अनमाउंट नहीं था, क्योंकि यह व्यस्त था, लेकिन संबंधित प्रक्रिया जाग गई और मैं रिबूट किए बिना समस्या को हल करने में सक्षम था।
मान लें कि आपकी प्रक्रिया एक एकल धागा है, और आप I / O को अवरुद्ध करने का उपयोग कर रहे हैं, तो आपकी प्रक्रिया I / O के पूर्ण होने तक प्रतीक्षा को अवरुद्ध कर देगी। कर्नेल इस बीच में चलाने के लिए एक और प्रक्रिया चुन लेगा, जो प्राथमिकता, अंतिम रन समय आदि के आधार पर होगी, अगर अन्य कोई रन करने योग्य प्रक्रिया नहीं है, तो कर्नेल कोई भी नहीं चलेगा; इसके बजाय, यह हार्डवेयर को बताएगा कि मशीन बेकार है (जिसके परिणामस्वरूप बिजली की खपत कम होगी)।
वे प्रक्रियाएँ जो I / O के पूरा होने की प्रतीक्षा कर रही हैं, आमतौर पर राज्य में डी, जैसे, ps
औरtop
।
हां, रीड () सिस्टम कॉल में कार्य अवरुद्ध हो जाता है। एक अन्य कार्य जो तैयार रन है, या यदि कोई अन्य कार्य तैयार नहीं है, तो निष्क्रिय कार्य (सीपीयू के लिए) चलता है।
एक सामान्य, ब्लॉकिंग डिस्क रीड "D" स्थिति में प्रवेश करने का कारण बनता है (जैसा कि अन्य ने नोट किया है)। ऐसे कार्य लोड औसत में योगदान करते हैं, भले ही वे सीपीयू का उपभोग नहीं कर रहे हों।
कुछ अन्य प्रकार के IO, विशेष रूप से टैटी और नेटवर्क, एक समान व्यवहार नहीं करते हैं - प्रक्रिया "S" स्थिति में समाप्त हो जाती है और बाधित हो सकती है और लोड औसत के खिलाफ गिनती नहीं करती है।
हां, IO की प्रतीक्षा में कार्य अवरुद्ध हो जाते हैं, और अन्य कार्य निष्पादित हो जाते हैं। अगले कार्य का चयन लिनक्स अनुसूचक द्वारा किया जाता है ।
आमतौर पर प्रक्रिया अवरुद्ध हो जाएगी। यदि रीड ऑपरेशन नॉन-ब्लॉकिंग के रूप में चिह्नित फ़ाइल डिस्क्रिप्टर पर है या यदि प्रक्रिया अतुल्यकालिक IO का उपयोग कर रही है तो यह ब्लॉक नहीं होगी। इसके अलावा अगर प्रक्रिया में अन्य धागे हैं जो अवरुद्ध नहीं हैं तो वे चालू रह सकते हैं।
निर्णय के रूप में जो प्रक्रिया आगे चलती है कर्नेल में शेड्यूलर पर निर्भर है ।