कृपया लिनक्स, विंडोज के दृष्टिकोण से समझाएं?
मैं C # में प्रोग्रामिंग कर रहा हूं, क्या इन दोनों शब्दों से फर्क पड़ेगा। कृपया उदाहरणों और जैसे…
धन्यवाद
कृपया लिनक्स, विंडोज के दृष्टिकोण से समझाएं?
मैं C # में प्रोग्रामिंग कर रहा हूं, क्या इन दोनों शब्दों से फर्क पड़ेगा। कृपया उदाहरणों और जैसे…
धन्यवाद
जवाबों:
विंडोज के लिए, महत्वपूर्ण खंड म्यूटेक्स की तुलना में हल्के वजन वाले हैं।
म्यूटेक्स को प्रक्रियाओं के बीच साझा किया जा सकता है, लेकिन हमेशा कर्नेल में एक सिस्टम कॉल का परिणाम होता है जिसमें कुछ ओवरहेड होता है।
महत्वपूर्ण वर्गों का उपयोग केवल एक प्रक्रिया के भीतर किया जा सकता है, लेकिन इसका फायदा यह है कि वे केवल विवाद के मामले में कर्नेल मोड पर स्विच करते हैं - अनियंत्रित परिचित, जो सामान्य मामला होना चाहिए, अविश्वसनीय रूप से तेज़ हैं। विवाद के मामले में, वे कुछ तुल्यकालन आदिम (किसी घटना या अर्धकुंभ की तरह) पर प्रतीक्षा करने के लिए कर्नेल में प्रवेश करते हैं।
मैंने एक त्वरित नमूना ऐप लिखा है जो उन दोनों के बीच के समय की तुलना करता है। 1,000,000 अप्रतिबंधित परिचितों और रिलीज़ के लिए मेरे सिस्टम पर, एक म्यूटेक्स एक सेकंड से अधिक लेता है। एक महत्वपूर्ण खंड 1,000,000 प्राप्तियों के लिए ~ 50 एमएस लेता है।
यहां परीक्षण कोड है, मैंने इसे चलाया और यदि म्यूटेक्स पहले या दूसरे स्थान पर है, तो इसी तरह के परिणाम मिले हैं, इसलिए हम कोई अन्य प्रभाव नहीं देख रहे हैं।
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;
// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
}
QueryPerformanceCounter(&end);
int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
}
QueryPerformanceCounter(&end);
int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
printf("Mutex: %d CritSec: %d\n", totalTime, totalTimeCS);
सैद्धांतिक दृष्टिकोण से, एक महत्वपूर्ण खंड कोड का एक टुकड़ा है जिसे एक साथ कई थ्रेड्स द्वारा नहीं चलाया जाना चाहिए क्योंकि कोड साझा संसाधनों तक पहुंचता है।
एक म्यूटेक्स एक एल्गोरिथ्म है (और कभी-कभी एक डेटा संरचना का नाम) जिसका उपयोग महत्वपूर्ण वर्गों की सुरक्षा के लिए किया जाता है।
सेमीफोर और मॉनिटर एक म्यूटेक्स के सामान्य कार्यान्वयन हैं।
व्यवहार में विंडोज़ में कई म्यूटेक्स कार्यान्वयन उपलब्ध हैं। वे मुख्य रूप से लॉकिंग के अपने स्तर, उनके स्कोप, उनकी लागत और विवाद के विभिन्न स्तरों के तहत उनके प्रदर्शन के कार्यान्वयन के परिणामस्वरूप भिन्न होते हैं। सीएलआर इनसाइड आउट देखें - विभिन्न म्यूटेक्स कार्यान्वयन की लागत के एक चार्ट के लिए स्केलेबिलिटी के लिए संगामिति का उपयोग करना ।
लाभकारी तुल्यकालन आदिम।
संदर्भ के लिए lock(object)
एक Monitor
- देखें MSDN का उपयोग करके यह कथन लागू किया गया है ।
पिछले वर्षों में गैर-अवरोधक तुल्यकालन पर बहुत शोध किया गया है । लक्ष्य एल्गोरिदम को लॉक-फ्री या प्रतीक्षा-मुक्त तरीके से लागू करना है। इस तरह के एल्गोरिदम में एक प्रक्रिया अन्य प्रक्रियाओं को अपना काम पूरा करने में मदद करती है ताकि प्रक्रिया अंत में अपना काम खत्म कर सके। परिणाम में एक प्रक्रिया अन्य प्रक्रियाओं के बावजूद भी अपना काम पूरा कर सकती है, जिसने कुछ काम करने की कोशिश की, लटका। Usinig ताले, वे अपने ताले जारी नहीं करेंगे और अन्य प्रक्रियाओं को जारी रखने से रोकेंगे।
अन्य उत्तरों के अलावा, निम्न विवरण खिड़कियों पर महत्वपूर्ण खंडों के लिए विशिष्ट हैं:
InterlockedCompareExchange
ऑपरेशन के रूप में सरल हैलिनक्स में, मुझे लगता है कि उनके पास एक "स्पिन लॉक" है जो स्पिन गणना के साथ महत्वपूर्ण खंड के समान उद्देश्य को पूरा करता है।
क्रिटिकल सेक्शन और म्यूटेक्स ऑपरेटिंग सिस्टम विशिष्ट नहीं हैं, उनकी मल्टीथ्रेडिंग / मल्टीप्रोसेसिंग की अवधारणाएं हैं।
क्रिटिकल सेक्शन एक ऐसा कोड है जो केवल किसी भी समय स्वयं द्वारा चलाया जाना चाहिए (उदाहरण के लिए, एक साथ 5 थ्रेड चल रहे हैं और एक फ़ंक्शन जिसे "क्रांतिक_सेंशन_फंक्शन" कहा जाता है जो एक सरणी को अपडेट करता है ... आप सभी 5 थ्रेड नहीं चाहते हैं एक बार में सरणी को अपडेट करना। इसलिए जब प्रोग्राम महत्वपूर्ण_ चल रहा है_फंक्शन (), तो अन्य थ्रेड्स में से किसी को भी अपने महत्वपूर्ण_संबंध_फंक्शन को नहीं चलाना चाहिए।
Mutex * Mutex महत्वपूर्ण अनुभाग कोड को लागू करने का एक तरीका है (इसे टोकन की तरह समझें ... महत्वपूर्ण-section_code को चलाने के लिए धागे के पास इसका अधिकार होना चाहिए)
एक म्यूटेक्स एक ऐसी वस्तु है जिसे एक धागा प्राप्त कर सकता है, अन्य धागों को प्राप्त करने से रोकता है। यह सलाहकार है, अनिवार्य नहीं है; एक धागा संसाधन का उपयोग कर सकता है म्यूटेक्स इसे प्राप्त किए बिना प्रतिनिधित्व करता है।
एक महत्वपूर्ण खंड एक कोड की लंबाई है जिसे ऑपरेटिंग सिस्टम द्वारा बाधित नहीं होने की गारंटी है। छद्म कोड में, यह इस तरह होगा:
StartCriticalSection();
DoSomethingImportant();
DoSomeOtherImportantThing();
EndCriticalSection();
लिनक्स में महत्वपूर्ण चयन के बराबर 'तेज' विंडोज एक फ्यूटेक्स होगा , जो फास्ट यूजर स्पेस म्यूटेक्स के लिए है। एक फ़ुटेक्स और म्यूटेक्स के बीच का अंतर यह है कि फ़ुटेक्स के साथ, कर्नेल केवल तब शामिल होता है जब मध्यस्थता की आवश्यकता होती है, इसलिए आप कर्नेल से बात करने के ओवरहेड को बचाते हैं जब परमाणु काउंटर को संशोधित किया जाता है। कि .. कुछ अनुप्रयोगों में ताले पर बातचीत के समय की एक महत्वपूर्ण राशि बचा सकता है ।
एक फ़ुटेक्स को प्रक्रियाओं के बीच भी साझा किया जा सकता है, इसका उपयोग करके आप एक म्यूटेक्स को साझा करने के लिए नियोजित करेंगे।
दुर्भाग्य से, futexes को लागू करने के लिए बहुत मुश्किल हो सकता है (पीडीएफ)। (2018 अपडेट, वे लगभग डरावने नहीं हैं क्योंकि वे 2009 में थे)।
इसके अलावा, दोनों प्लेटफार्मों में बहुत अधिक समान है। आप साझा संरचना में परमाणु, टोकन संचालित अपडेट इस तरीके से कर रहे हैं कि (उम्मीद है) भुखमरी का कारण न बने। जो बचता है, बस उसे पूरा करने की विधि है।
मेरे 2 सेंट जोड़ने के लिए, महत्वपूर्ण अनुभागों को एक संरचना के रूप में परिभाषित किया गया है और उन पर संचालन उपयोगकर्ता-मोड संदर्भ में किया जाता है।
ntdll! _RTL_CRITICAL_SECTION + 0x000 डीबगइन्फो: Ptr32 _RTL_CRITICAL_SECTION_DEBUG + 0x004 लॉककाउंट: Int4B + 0x008 पुनरावर्तन करें: Int4B + 0x00c का मालिक है: Ptr32 शून्य + 0x010 लॉकस्मैफोर: Ptr32 शून्य + 0x014 स्पिनकाउंट: Uint4B
जबकि म्यूटेक्स विंडोज ऑब्जेक्ट डायरेक्टरी में बनाए गए कर्नेल ऑब्जेक्ट (ExMutantObjectType) हैं। म्यूटेक्स ऑपरेशन ज्यादातर कर्नेल-मोड में लागू किए जाते हैं। उदाहरण के लिए, एक म्यूटेक्स बनाते समय, आप अंत में कर्नेल में nt! NtCreateMutant कहते हैं।
माइकल से बढ़िया जवाब। मैंने C ++ 11 में पेश किए गए म्यूटेक्स वर्ग के लिए तीसरा परीक्षण जोड़ा है। परिणाम कुछ दिलचस्प है, और अभी भी एकल प्रक्रियाओं के लिए CRITICAL_SECTION वस्तुओं के अपने मूल समर्थन का समर्थन करता है।
mutex m;
HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;
// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
}
QueryPerformanceCounter(&end);
int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);
}
QueryPerformanceCounter(&end);
int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
// Force code into memory, so we don't see any effects of paging.
m.lock();
m.unlock();
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
m.lock();
m.unlock();
}
QueryPerformanceCounter(&end);
int totalTimeM = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);
printf("C++ Mutex: %d Mutex: %d CritSec: %d\n", totalTimeM, totalTime, totalTimeCS);
मेरे परिणाम 217, 473 और 19 थे (ध्यान दें कि पिछले दो बार के मेरे अनुपात माइकल की तुलना में लगभग बराबर हैं, लेकिन मेरी मशीन उनके मुकाबले कम से कम चार साल छोटी है, इसलिए आप 2009 और 2013 के बीच बढ़ी हुई गति के प्रमाण देख सकते हैं। , जब XPS-8700 बाहर आया)। नया म्यूटेक्स वर्ग विंडोज म्यूटेक्स की तुलना में दोगुना है, लेकिन अभी भी विंडोज CRITICAL_SECTION ऑब्जेक्ट की गति से दसवें से कम है। ध्यान दें कि मैंने केवल गैर-पुनरावर्ती म्यूटेक्स का परीक्षण किया था। CRITICAL_SECTION ऑब्जेक्ट पुनरावर्ती हैं (एक धागा उन्हें बार-बार दर्ज कर सकता है, बशर्ते वह समान संख्या में छोड़ देता है)।
यदि इसे अपने वास्तविक मापदंडों का उपयोग किया जाता है, तो एसी फ़ंक्शन को रीएन्टेंट कहा जाता है।
एक ही समय में कई थ्रेड्स द्वारा रेंटेंट फ़ंक्शन को बुलाया जा सकता है।
रीक्रेंट फंक्शन का उदाहरण:
int reentrant_function (int a, int b)
{
int c;
c = a + b;
return c;
}
गैर प्रतिवादी समारोह का उदाहरण:
int result;
void non_reentrant_function (int a, int b)
{
int c;
c = a + b;
result = c;
}
C मानक लाइब्रेरी स्ट्रेटोक () एक बार में नहीं है और एक ही समय में 2 या अधिक थ्रेड द्वारा उपयोग नहीं किया जा सकता है।
कुछ प्लेटफ़ॉर्म SDK, strtok () जिसे strtok_r () कहा जाता है, के रीक्रेंटली संस्करण के साथ आता है;
एनरिको मिग्लोर