2015-06-21 6 views
5

मुझे आश्चर्य है कि नींद/नैनोस्ली आंतरिक रूप से कैसे कार्यान्वित की जाती है? इस कोड पर विचार करें:क्या व्यस्त प्रतीक्षा योजना का उपयोग करके नींद/नैनोस्लीप काम करता है?

{ // on a thread other than main() thread 
    while(1) 
    { 
    //do something 
    sleep(1); 
    } 
} 

सीपीयू यदि 1 सेकंड की नींद (अर्थात एक आंतरिक व्यस्त प्रतीक्षा करें) किया जाता है की जाँच करने के लिए स्विचन निरंतर संदर्भ कर दिया जाएगा।

मुझे संदेह है कि यह इस तरह से काम करता है, बहुत अधिक अक्षमता। लेकिन फिर यह कैसे काम करता है?

वही प्रश्न नैनोस्ली पर लागू होता है।

नोट: यदि यह कार्यान्वयन/ओएस विशिष्ट है, तो मैं संभवतः एक और अधिक कुशल योजना कैसे कार्यान्वित कर सकता हूं जो निरंतर संदर्भ स्विचिंग का कारण नहीं बनता है?

+1

प्रश्न के साथ क्या गलत है? – Kam

+0

_ "प्रश्न के साथ क्या गलत है?" _ बहुत व्यापक। ओएस विशिष्ट, कार्यान्वयन विशिष्ट। –

+0

POSIX यह निर्दिष्ट नहीं करता है कि इसे कैसे लागू किया जाना चाहिए – StenSoft

उत्तर

2

सटीक कार्यान्वयन की गारंटी नहीं है लेकिन आप कुछ गुणों की अपेक्षा कर सकते हैं।

आमतौर पर sleep (3) काफी गलत है और लिनक्स 'मैन नींद 3' राज्यों को भी SIGALM (सिग्नल) का उपयोग करके कार्यान्वित किया जा सकता है। तो यह निश्चित रूप से प्रदर्शन के बारे में नहीं है। यह निश्चित रूप से स्पिन ताले के बारे में भी नहीं है इसलिए सीपीयू गहन नहीं हो सकता है।

nanosleep काफी अलग जानवर है जिसे स्पिनलॉक्स का उपयोग करके भी लागू किया जा सकता है। जो अधिक महत्वपूर्ण है, कम से कम लिनक्स nanosleep में आदमी खंड 2 में है जो खड़ा है कि यह सिस्टम कॉल है इसलिए कम से कम इसमें कर्नेल मोड में स्विच शामिल होना चाहिए। क्या आपको वास्तव में इसके उच्च संकल्प की आवश्यकता है?

अद्यतन

मैं अपनी टिप्पणी को देखने के रूप में मैं man select 3 राज्यों के रूप में select() उपयोग की सलाह देते हैं कार्य करें:

#include <stdio.h> 
    #include <stdlib.h> 
    #include <sys/time.h> 
    #include <sys/types.h> 
    #include <unistd.h> 

    int 
    main(void) 
    { 
     fd_set rfds; 
     struct timeval tv; 
     int retval; 

     /* Watch stdin (fd 0) to see when it has input. */ 
     FD_ZERO(&rfds); 
     FD_SET(0, &rfds); 

     /* Wait up to five seconds. */ 
     tv.tv_sec = 5; 
     tv.tv_usec = 0; 

     retval = select(1, &rfds, NULL, NULL, &tv); 
     /* Don't rely on the value of tv now! */ 

     if (retval == -1) 
      perror("select()"); 
     else if (retval) 
      printf("Data is available now.\n"); 
      /* FD_ISSET(0, &rfds) will be true. */ 
     else 
      printf("No data within five seconds.\n"); 

     exit(EXIT_SUCCESS); 
    } 

यह यांत्रिकी साबित होता है अगर आप कुछ घटना के लिए सूत्र में सोने के लिए की जरूरत है और इस घटना सकता है फ़ाइल डिस्क्रिप्टर से जुड़े रहें।

+0

मैं उच्च रिज़ॉल्यूशन की तलाश नहीं कर रहा हूं, मैं अधिक चिंतित हूं निरंतर संदर्भ स्विचिंग में मेरे अन्य धागे के प्रदर्शन के बारे में क्योंकि मेरे पास एक धागा है जो 99.9% समय सो रहा है (नींद (30) के साथ) – Kam

+0

30 सेकंड एक अनंत काल है, आप सुरक्षित रूप से थ्रेड सीपीयू क्वांटा को नींद के साथ फेंक सकते हैं प्रणाली के बिना एक गुच्छा मिलीसेकंड बिल्कुल ध्यान दे रहा है। –

+2

नोट: यह प्रश्न वर्तमान में [टैग: पॉज़िक्स] के रूप में टैग किया गया है, नहीं [टैग: लिनक्स]। पॉज़िक्स में, 'नैनोस्लीप' स्पिन ताले के साथ लागू नहीं किया जा सकता है। थ्रेड को निलंबित करने की जरूरत है। चाहे लिनक्स में यह मामला एक अलग सवाल है क्योंकि लिनक्स POSIX अनुपालन नहीं है। –

0

"मैं सोच रहा हूं कि नींद/नैनोस्ली आंतरिक रूप से कैसे कार्यान्वित होती है?"

इसके लिए एक कार्यान्वयन नहीं है, लेकिन प्रत्येक ओएस और sleep() और nanosleep() की POSIX शिकायत कार्यान्वयन कैसे वे वास्तव में इस सुविधा लागू कर रहे हैं में स्वतंत्र हैं।

तो यह पूछना कि वास्तव में यह कैसे किया जाता है, यह एक विशेष ओएस/पॉज़िक्स लाइब्रेरी कार्यान्वयन के अधिक संदर्भ के बिना बहुत बेकार है।

1

sleep की POSIX विनिर्देशन और nanosleep कहना (जोर मेरा)

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

(स्रोत:। http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html)

और

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

(स्रोत:। http://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html)

मुझे लगता है कि पढ़ने के लिए कहना है कि एक POSIX शिकायत प्रणाली sleep या nanosleep लिए एक व्यस्त पाश का उपयोग नहीं कर सकते हैं। कॉलिंग थ्रेड को निष्पादन से निलंबित करने की आवश्यकता है।

3

sleep() लागू करने के लिए विशिष्ट तरीका और nanosleep() जो कुछ पैमाने ओएस अनुसूचक का उपयोग करता है में परिवर्तित करने के लिए तर्क है (ऊपर गोलाई जबकि) और एक "पूर्ण जगाने के समय" के रूप में इसे करने के लिए वर्तमान समय जोड़ने; फिर शेड्यूलर को बताएं कि थ्रेड CPU समय देने के बाद तक "पूर्ण जागने का समय" तक पहुंच गया है। कोई व्यस्त प्रतीक्षा शामिल नहीं है।

ध्यान दें कि ओएस के शेड्यूलर का जो भी पैमाने सामान्य रूप से उपयोग करता है, उस पर निर्भर करता है कि कौन सा हार्डवेयर उपलब्ध है और/या समय रखने के लिए उपयोग किया जा रहा है। यह एक नैनोसेकंड से छोटा हो सकता है (उदाहरण के लिए 80x86 पर स्थानीय एपीआईसी "टीएससी समय सीमा मोड" में उपयोग किया जा रहा है) या 100 एमएस जितना बड़ा हो सकता है।

यह भी ध्यान दें कि ओएस गारंटी देता है कि देरी आपके द्वारा पूछे जाने वाले कार्यों से कम नहीं होगी; लेकिन आम तौर पर कोई गारंटी नहीं है कि यह अधिक नहीं होगा और कुछ मामलों में (जैसे भारी भारित प्रणाली पर कम प्राथमिकता धागा) देरी अनुरोध से कहीं अधिक बड़ी हो सकती है। उदाहरण के लिए, यदि आप 123 नैनोसेकंड के लिए सोने के लिए कहते हैं तो शेड्यूलर निर्णय लेने से पहले आप 2 एमएस के लिए सो सकते हैं, यह आपको CPU समय दे सकता है, और फिर शेड्यूलर वास्तव में आपको CPU समय देता है (उदाहरण के लिए अन्य) धागे सीपीयू का उपयोग कर रहे हैं)।

कुछ ओएस इसे "अनुरोध से अधिक लंबे समय तक सोए" को कम करने का प्रयास कर सकते हैं, और कुछ ओएस (जैसे हार्ड-रीयल टाइम के लिए डिज़ाइन किया गया) कुछ प्रकार की गारंटी प्रदान कर सकता है (प्रतिबंधों के साथ - उदाहरण के लिए थ्रेड प्राथमिकता के अधीन) देरी की समाप्ति और सीपीयू वापस पाने के बीच न्यूनतम समय। ऐसा करने के लिए, ओएस/कर्नेल ओएस के शेड्यूलर का उपयोग करने वाले किसी भी पैमाने पर तर्क को परिवर्तित करेगा (गोल करने के दौरान और गोल नहीं होने पर) और "केवल मामले में" एक छोटी राशि घटा सकता है; ताकि शेड्यूलर अनुरोधित विलंब समाप्त होने से ठीक पहले (और बाद में नहीं) थ्रेड को जगाता है; और फिर जब थ्रेड को CPU समय दिया जाता है (संदर्भ की लागत के बाद धागे पर स्विच किया जाता है, और संभावित रूप से विभिन्न कैश लाइनों को प्री-फ़ेच करने के बाद थ्रेड को उपयोग करने की गारंटी दी जाती है) कर्नेल वास्तव में देरी की अवधि समाप्त होने तक संक्षेप में प्रतीक्षा करेगा। यह कर्नेल को देरी की समाप्ति के बहुत करीब थ्रेड पर वापस नियंत्रण करने की अनुमति देता है।

उदाहरण के लिए, यदि आप 123 नैनोसेकंड के लिए सोने के लिए कहते हैं, तो शेड्यूलर आपको 100 नैनोसेकंड के लिए CPU समय नहीं दे सकता है, तो यह आपके थ्रेड पर 10 नैनोसेकंड स्विच कर सकता है, फिर यह शेष 13 नैनोसेकंडों के लिए प्रतीक्षा कर सकता है। यहां तक ​​कि इस मामले में (जहां व्यस्त प्रतीक्षा की जाती है) यह आमतौर पर देरी की पूरी अवधि के लिए प्रतीक्षा में व्यस्त नहीं होगा।हालांकि, अगर देरी बहुत कम है तो कर्नेल केवल अंतिम व्यस्त प्रतीक्षा करेगा।

अंत में, एक विशेष मामला है जो उल्लेखनीय हो सकता है। POSIX सिस्टम पर sleep(0); आमतौर पर yield() के रूप में दुरुपयोग किया जाता है। मुझे यह भी यकीन नहीं है कि यह अभ्यास कितना वैध है - शेड्यूलर के लिए yield() जैसे कुछ का समर्थन करना असंभव है जब तक कि शेड्यूलर CPU समय को अपरिहार्य काम करने के लिए तैयार नहीं करता है, जबकि अधिक महत्वपूर्ण काम प्रतीक्षा करता है।

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