लिनक्स में एक स्पिनलॉक क्या है?


32

मैं लिनक्स स्पिनलॉक के बारे में विस्तार से जानना चाहूंगा; क्या कोई उन्हें मुझे समझा सकता है?

जवाबों:


34

स्पिन लॉक एक साझा संसाधन को एक साथ दो या अधिक प्रक्रियाओं द्वारा संशोधित होने से बचाने का एक तरीका है। पहली प्रक्रिया जो संसाधन को संशोधित करने की कोशिश करती है, ताला को "प्राप्त" करती है और अपने रास्ते पर जारी रखती है, यह करते हुए कि संसाधन के साथ इसकी क्या आवश्यकता है। बाद में ताला प्राप्त करने की कोशिश करने वाली कोई अन्य प्रक्रिया बंद हो जाती है; उन्हें कहा जाता है कि "स्पिन इन प्लेस" पहली प्रक्रिया द्वारा लॉक का इंतजार कर रहा है, इस प्रकार नाम स्पिन लॉक है।

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

स्पिन लॉक एक समस्या है क्योंकि स्पिनिंग उस थ्रेड के सीपीयू कोर को किसी अन्य कार्य को करने से रोकता है। हालांकि लिनक्स कर्नेल मल्टीटास्किंग सेवाएं प्रदान करता है, इसके तहत चलने वाले उपयोगकर्ता अंतरिक्ष कार्यक्रमों में, सामान्य-प्रयोजन मल्टीटास्किंग सुविधा कर्नेल कोड तक नहीं होती है।

यह स्थिति बदल रही है, और अधिकांश लिनक्स के अस्तित्व के लिए है। लिनक्स 2.0 के माध्यम से, कर्नेल लगभग पूरी तरह से एकल-टास्किंग कार्यक्रम था: जब भी सीपीयू कर्नेल कोड चला रहा था, केवल एक सीपीयू कोर का उपयोग किया गया था, क्योंकि सभी साझा संसाधनों की रक्षा करने वाला एक सिंगल स्पिन लॉक था, जिसे बिग कर्नेल लॉक (BKL) कहा जाता है )। लिनक्स 2.2 से शुरू होकर, BKL को धीरे-धीरे कई स्वतंत्र तालों में तोड़ा जा रहा है जो प्रत्येक संसाधन के अधिक केंद्रित वर्ग की रक्षा करते हैं। आज, कर्नेल 2.6 के साथ, BKL अभी भी मौजूद है, लेकिन इसका उपयोग केवल वास्तव में पुराने कोड द्वारा किया जाता है जिसे आसानी से कुछ और ग्रैन्यूल लॉक में स्थानांतरित नहीं किया जा सकता है। बहु-बॉक्स के लिए अब यह संभव है कि हर सीपीयू में उपयोगी कर्नेल कोड हो।

बीकेएल को तोड़ने की उपयोगिता के लिए एक सीमा है क्योंकि लिनक्स कर्नेल में सामान्य मल्टीटास्किंग का अभाव है। यदि सीपीयू कोर को एक कर्नेल स्पिन लॉक पर कताई अवरुद्ध हो जाती है, तो इसे तब तक रिटेक नहीं किया जा सकता है, जब तक कि लॉक जारी न हो जाए। यह बस बैठता है और तब तक घूमता है जब तक ताला जारी नहीं हो जाता।

स्पिन लॉक प्रभावी रूप से एक राक्षस-कोर बॉक्स को सिंगल-कोर बॉक्स में बदल सकता है, अगर वर्कलोड ऐसा है कि हर कोर हमेशा सिंगल स्पिन लॉक की प्रतीक्षा कर रहा है। यह लिनक्स कर्नेल की स्केलेबिलिटी की मुख्य सीमा है: 2 से 4 तक सीपीयू कोर को दोगुना करना संभवतः लिनक्स बॉक्स की गति को लगभग दोगुना कर देगा, लेकिन इसे 16 से 32 तक दोगुना करना संभवत: अधिकांश वर्कलोड के साथ नहीं होगा।


@Arren: संदेह की एक जोड़ी- मैं इस बिग कर्नेल लॉक और इसके निहितार्थ के बारे में अधिक जानना चाहूंगा। मैं यह भी समझता हूं कि पिछले पैराग्राफ को "2 से 4 तक सीपीयू कोर को दोगुना करना संभवत: एक लिनक्स बॉक्स की गति से लगभग दोगुना होगा, लेकिन इसे 16 से 32 तक दोगुना करना संभवत: नहीं होगा"
सेन

2
बीकेएल के निहितार्थ: मुझे लगा कि मैंने ऊपर स्पष्ट कर दिया है। कर्नेल में केवल एक लॉक के साथ, किसी भी समय दो कोर बीकेएल द्वारा संरक्षित कुछ करने की कोशिश करते हैं, एक कोर अवरुद्ध होता है जबकि पहला अपने संरक्षित संसाधन का उपयोग करके समाप्त होता है। लॉकिंग जितना अधिक बारीक होता है, यह मौका उतना ही कम होगा, जिससे प्रोसेसर का उपयोग उतना अधिक होगा।
वॉरेन यंग

2
पुन :: दोहरीकरण: मेरा मतलब है कि कंप्यूटर में प्रोसेसर कोर जोड़ने पर रिटर्न कम होने का एक नियम है। जैसे-जैसे कोर की संख्या बढ़ती जाती है, वैसे-वैसे यह मौका मिलता है कि उनमें से दो या अधिक को किसी विशेष लॉक द्वारा संरक्षित संसाधन तक पहुंचने की आवश्यकता होगी। लॉक ग्रैन्युलैरिटी बढ़ने से इस तरह के टकराव की संभावना कम हो जाती है, लेकिन बहुत अधिक, बहुत अधिक जोड़ने में अतिशय है। आप इसे सुपर कंप्यूटरों में आसानी से देख सकते हैं, जिनमें अक्सर इन दिनों हजारों प्रोसेसर होते हैं: अधिकांश कार्यभार उन पर अक्षम होते हैं क्योंकि वे साझा संसाधन विवाद के कारण कई प्रोसेसर को बेकार करने से बच नहीं सकते हैं।
वॉरेन यंग

1
हालांकि यह एक दिलचस्प स्पष्टीकरण (उस के लिए +1) है, मुझे नहीं लगता कि यह स्पिनलॉक और अन्य प्रकार के तालों के बीच अंतर बताने में प्रभावी है।
गिल्स एसओ- बुराई को रोकना '

2
अगर कोई स्पिन लॉक के बीच का अंतर जानना चाहता है, और कहे, एक अर्धकुंभ, तो यह एक अलग सवाल है। एक और अच्छा लेकिन स्पर्धात्मक प्रश्न यह है कि लिनक्स कर्नेल डिज़ाइन के बारे में ऐसा क्या है जो उपयोगकर्ता के कोड में म्यूटेक्स की तरह कुछ और के बजाय स्पिन लॉक को अच्छा विकल्प बनाता है। यह उत्तर बहुत कुछ बताता है।
वारेन यंग

11

एक स्पिन लॉक तब होता है जब एक प्रक्रिया एक ताला हटाने के लिए लगातार मतदान करती है। इसे बुरा माना जाता है क्योंकि यह प्रक्रिया अनावश्यक रूप से चक्रों का उपभोग कर रही है। यह लिनक्स-विशिष्ट नहीं है, लेकिन एक सामान्य प्रोग्रामिंग पैटर्न है। और जबकि यह आमतौर पर एक बुरा अभ्यास माना जाता है, यह वास्तव में सही समाधान है; ऐसे मामले हैं जहां शेड्यूलर का उपयोग करने की लागत कुछ चक्रों की लागत की तुलना में अधिक (सीपीयू चक्रों के संदर्भ में) है जो कि स्पिनलॉक के अंतिम होने की उम्मीद है।

पालक का उदाहरण:

#!/bin/sh
#wait for some program to clear a lock before doing stuff
while [ -f /var/run/example.lock ]; do
  sleep 1
done
#do stuff

स्पिन लॉक से बचने का अक्सर एक तरीका है। इस विशेष उदाहरण के लिए, एक लिनक्स उपकरण है जिसे इनोटिफ़ाइविट कहा जाता है (यह आमतौर पर डिफ़ॉल्ट रूप से स्थापित नहीं होता है)। यदि यह सी में लिखा गया था, तो आप बस का प्रयोग करेंगे inotify एपीआई कि लिनक्स प्रदान करता है।

एक ही उदाहरण, inotifywait का उपयोग करके दिखाता है कि स्पिन लॉक के बिना एक ही चीज़ को कैसे पूरा किया जाए:

#/bin/sh
inotifywait -e delete_self /var/run/example.lock
#do stuff

वहाँ अनुसूचक की भूमिका क्या है? या इसकी कोई भूमिका है?
सेन

1
स्पिन लॉक विधि में, शेड्यूलर अपने कार्य को करने के लिए हर ~ 1 सेकंड की प्रक्रिया को फिर से शुरू करता है (जो कि बस एक फ़ाइल के अस्तित्व की जांच करता है)। Inotifywait उदाहरण में, शेड्यूलर केवल उस प्रक्रिया को फिर से शुरू करता है जब बच्चा प्रक्रिया (inotifywait) से बाहर निकलता है। Inotifywait भी सो रहा है; शेड्यूलर तब ही इसे फिर से शुरू करता है जब इनॉटिफाई इवेंट होता है।
शॉन जे। गोफ

तो इस परिदृश्य को सिंगल कोर प्रोसेसर सिस्टम में कैसे संभाला जाता है?
सेन

@ सीन: यह लिनक्स डिवाइस ड्राइवर्स में अच्छी तरह से समझाया गया है ।
गिल्स एसओ- बुराई को रोकना '

1
वह बैश लिपि स्पिनक का एक बुरा उदाहरण है। आप इस प्रक्रिया को विराम दे रहे हैं जिससे यह सोने पर सुहागा है एक पालक कभी नहीं सोता है। सिंगल कोर मशीन पर यह केवल शेड्यूलर को निलंबित कर देता है और जारी रहता है (व्यस्त प्रतीक्षा के बिना)
मार्टिन

7

जब एक थ्रेड लॉक हासिल करने की कोशिश करता है, तो तीन चीजें हो सकती हैं यदि यह विफल हो जाता है, तो यह कोशिश कर सकता है और अवरुद्ध कर सकता है, यह कोशिश कर सकता है और जारी रख सकता है, फिर कोशिश कर सकता है कि सो जाने के लिए ओएस से कहे कि जब कोई घटना घटती है तो उसे उठाएं।

अब एक कोशिश और जारी रखना बहुत कम समय का उपयोग करता है फिर एक कोशिश और ब्लॉक। आइए इस क्षण के लिए कहें कि एक "कोशिश और जारी" मैं समय की इकाई ले जाएगा और एक "कोशिश और ब्लॉक" एक सौ ले जाएगा।

अब हमें इस समय के लिए मान लेते हैं कि औसतन एक थ्रेड को लॉक पकड़े हुए 4 यूनिट समय लगेगा। 100 इकाइयों का इंतजार करना बेकार है। इसलिए इसके बजाय आप "कोशिश और जारी रखें" का एक लूप लिखें। अगले प्रयास में आप आमतौर पर ताला प्राप्त करेंगे। यह एक स्पिन लॉक है। यह कहा जाता है क्योंकि धागा जगह में घूमता रहता है जब तक कि यह ताला प्राप्त नहीं करता है।

एक अतिरिक्त सुरक्षा उपाय लूप के चलने की संख्या को सीमित करना है। इसलिए उदाहरण में आप लूप रन के लिए उदाहरण के लिए छह बार बनाते हैं, अगर यह विफल रहता है तो आप "प्रयास करें और ब्लॉक करें"।

यदि आप जानते हैं कि एक धागा हमेशा 200 इकाइयों को कहने के लिए लॉक रखेगा, तो आप प्रत्येक प्रयास के लिए कंप्यूटर का समय बर्बाद कर रहे हैं और जारी रखेंगे।

तो अंत में, एक स्पिन लॉक बहुत कुशल या बेकार हो सकता है। यह तब बेकार है जब एक ताला रखने के लिए "विशिष्ट" समय अधिक होता है, फिर "कोशिश और ब्लॉक" करने का समय। यह तब प्रभावी होता है जब एक लॉक को रखने का विशिष्ट समय बहुत छोटा होता है, फिर 'कोशिश और ब्लॉक' करने का समय।

Ps: थ्रेड पर पढ़ने के लिए पुस्तक "ए थ्रेड प्राइमर" है, यदि आप अभी भी इसे पा सकते हैं।


धागा तब तक घूमता रहता है जब तक कि उसे ताला न मिल जाए । क्या आप मुझे बता सकते हैं कि यह कताई क्या है? क्या यह वैसा ही है जैसा कि वास_के पास आता है और शेड्यूलर द्वारा निष्पादित किया जाता है? हो सकता है कि मैं निम्न स्तर पर आने की कोशिश कर रहा हूं, लेकिन फिर भी मेरी शंका का सामना नहीं कर सकता।
सेन

मूल रूप से लूप में 3-4 निर्देशों के बीच कताई।
पॉल स्टेलियन

5

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

take the lock
use the resource
release the lock

यदि कोई अन्य कार्य पहले ही ले लिया है तो ताला लेना संभव नहीं है। (लॉक को एक भौतिक टोकन ऑब्जेक्ट के रूप में सोचें। या तो ऑब्जेक्ट एक दराज में है, या किसी के हाथ में है। केवल ऑब्जेक्ट को रखने वाला व्यक्ति ही संसाधन तक पहुंच सकता है।) इसलिए "लॉक करें" का वास्तव में अर्थ है "जब तक प्रतीक्षा करें।" किसी और के पास ताला नहीं है, तो इसे ले लो ”।

एक उच्च-स्तरीय दृष्टिकोण से, ताले को लागू करने के दो प्रमुख तरीके हैं: स्पिनलॉक, और स्थितियां। स्पिनलॉक के साथ , लॉक लेने का मतलब सिर्फ "स्पिनिंग" है (यानी लूप में कुछ नहीं करना) जब तक कि किसी और के पास लॉक न हो। शर्तों के साथ, यदि कोई कार्य लॉक लेने का प्रयास करता है, लेकिन अवरुद्ध हो जाता है क्योंकि एक अन्य कार्य इसे रखता है, तो नवागंतुक एक प्रतीक्षा कतार में प्रवेश करता है; किसी भी प्रतीक्षा कार्य के लिए रिलीज़ ऑपरेशन सिग्नल संकेत देता है कि ताला अब उपलब्ध है।

(ये स्पष्टीकरण आपको लॉक लागू करने के लिए पर्याप्त नहीं हैं, क्योंकि मैंने परमाणुता के बारे में कुछ भी नहीं कहा है। लेकिन परमाणु यहाँ महत्वपूर्ण नहीं है।)

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

लिनक्स डिवाइस ड्राइवर्स , अध्याय 5 में लिनक्स कर्नेल के स्पिनलॉक और अन्य संगामिति तंत्रों की एक अच्छी व्याख्या है ।


अन्य सिंक्रोनाइज़ेशन प्राइमेटिव को लागू करने का एक अच्छा तरीका क्या होगा? एक स्पिनलॉक लें, जांचें कि क्या किसी और के पास वास्तविक आदिम लागू किया जा रहा है, तो या तो अनुसूचक का उपयोग करें या पहुंच का उपयोग करें? क्या हम जावा में स्पिनकॉक का एक रूप में सिंक्रनाइज़ () ब्लॉक पर विचार कर सकते हैं, और ठीक से लागू किए गए आदिम में सिर्फ एक स्पिनलॉक का उपयोग कर सकते हैं?
पॉल स्टेलियन

@PaulStelian इस तरह से "धीमी" ताले को लागू करना वास्तव में सामान्य है। मुझे उस हिस्से का जवाब देने के लिए पर्याप्त जावा नहीं पता है, लेकिन मुझे संदेह है कि synchronizedयह एक स्पिनलॉक द्वारा लागू किया जाएगा: एक synchronizedब्लॉक बहुत लंबे समय तक चल सकता है। synchronizedकुछ मामलों में उपयोग करने के लिए ताले को आसान बनाने के लिए एक भाषा का निर्माण होता है, न कि बड़े तुल्यकालन के निर्माण के लिए एक आदिम।
गिल्स एसओ- बुराई को रोकना '19

3

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

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

जब आप अपने स्पिनलॉक को एक रुकावट के साथ साझा करना चाहते हैं तो आपको irssave वेरिएंट का उपयोग करना चाहिए। यह न केवल शेड्यूलर को अक्षम करेगा, बल्कि इंटरप्ट को भी अक्षम करेगा। यह सही समझ में आता है? कुछ और नहीं चलेगा यह सुनिश्चित करके स्पिनलॉक काम करता है। यदि आप इसे चलाने के लिए कोई व्यवधान नहीं चाहते हैं तो आप इसे अक्षम कर सकते हैं और महत्वपूर्ण अनुभाग में सुरक्षित रूप से आगे बढ़ सकते हैं।

मल्टीकोर मशीन पर एक स्पिनलॉक वास्तव में एक और कोर की प्रतीक्षा में स्पिन करेगा जो इसे जारी करने के लिए लॉक रखता है। यह कताई केवल मल्टीकोर मशीनों पर होती है क्योंकि सिंगल कोर वाले पर ऐसा नहीं हो सकता है (आप या तो स्पिनलॉक पकड़ें और आगे बढ़ें या आप तब तक कभी न चलें जब तक कि लॉक निकल न जाए)।

स्पिनलॉक बेकार नहीं है जहां यह समझ में आता है। बहुत छोटे महत्वपूर्ण खंडों के लिए केवल कुछ माइक्रोसेकंड के लिए शेड्यूलर को निलंबित करने की तुलना में एक म्यूटेक्स कार्य कतार आवंटित करना बेकार होगा जो महत्वपूर्ण कार्य को पूरा करने के लिए लेता है। यदि आपको एक io ऑपरेशन (जो सो सकता है) में ताला खोलने या सोने की आवश्यकता है, तो एक म्यूटेक्स का उपयोग करें। निश्चित रूप से एक स्पिनलॉक को कभी भी लॉक न करें और फिर इसे एक रुकावट के अंदर छोड़ने की कोशिश करें। जबकि यह काम करेगा, यह उस समय (फ्लैगोनोसेट) के आर्डिनो बकवास की तरह होगा; ऐसे मामले में एक सेमाफोर का उपयोग करें।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.