2011-08-25 10 views
14

में टाइमर करने का सबसे अच्छा तरीका मैं हमेशा नोटिस करता हूं कि यूनिक्स में टाइमर बनाने के विभिन्न तरीकों से लोगों की अलग-अलग प्रतिक्रियाएं होती हैं।यूनिक्स

मैं कुछ अलग अलग तरीकों से है कि मैं एक घटना यूनिक्स के भीतर हर एक्स सेकंड पर अमल कर सकता है पता है:

  • आप एक मतदान धागा कर सकते हैं - सोता साथ pthread_t;
  • आप एक टाइमआउट के साथ एक चयन() कर सकते हैं;
  • और मुझे लगता है कि आप कुछ अन्य तरीकों से ओएस का उपयोग कर सकते हैं।

क्या कोई टाइमर करने के लिए "सर्वश्रेष्ठ" या सबसे प्रभावी तरीका के साथ कुछ नमूना कोड प्रदान कर सकता है और इसका विवरण क्यों सर्वोत्तम है? मैं इसके लिए सबसे कुशल तंत्र का उपयोग करना चाहता हूं लेकिन मुझे यकीन नहीं है कि यह कौन सा है!

हमारे उद्देश्यों के लिए, बस दिखाएं कि आप "हैलो वर्ल्ड!" प्रिंट कर रहे हैं हर 10 सेकंड में एक बार।

नोट: मेरे पास TR1/बूस्ट/आदि नहीं है। इस प्रणाली पर, कृपया इसे सीधे सी/सी ++ और यूनिक्स सिस्टम कॉल पर रखें। पहली बार उल्लेख नहीं करने के लिए खेद है :)

+0

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

+0

सिस्टम पहले से ही मल्टीथ्रेडिंग का भारी उपयोग करता है ताकि यह कोई समस्या न हो। इसे उत्तर के रूप में टॉस करें :) –

+0

एचएम, मेरे पास वास्तव में वास्तविक प्रश्न पर कुछ भी कहना नहीं है। मैंने पहले अपनी आवश्यकताओं की आवश्यकता के लिए boost.asio का उपयोग किया है (ioservice लूप एक अलग थ्रेड में चल रहा है), लेकिन मैं शायद विभिन्न दृष्टिकोणों के तुलनात्मक फायदों से बात नहीं कर सकता ... –

उत्तर

5

यह निर्भर करता है। "हैलो" के बीच 10 सेकंड प्रतीक्षा करने के आपके छोटे उदाहरण के लिए एक साधारण नींद पर्याप्त होगी क्योंकि आप अपना समय समाप्त होने तक अपने वर्तमान धागे को निलंबित कर सकते हैं।

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

यदि आप एक तंग पाश में सामान संसाधित कर रहे हैं, तो आप नियमित रूप से एक प्रारंभ समय मतदान कर सकते हैं यह देखने के लिए कि आपका 10 सेकंड ऊपर है या नहीं।

एक उचित संकेत हैंडलर के साथ alarm रूप में अच्छी तरह से काम करेगा लेकिन वहाँ आप एक संकेत हैंडलर में क्या कर सकते हैं गंभीर सीमा नहीं है। अधिकांश समय, इसमें एक ध्वज स्थापित करना शामिल था जिसे हर बार मतदान किया जाना चाहिए।

संक्षेप में, यह आपके धागे की घटनाओं को संसाधित करने के तरीके के नीचे आता है।

2

यदि आपका प्रोग्राम पहले ही थ्रेड हो चुका है, तो एक मतदान धागा का उपयोग करना सरल और प्रभावी है।

यदि आपका प्रोग्राम पहले से ही थ्रेड नहीं हुआ है, तो यह ट्रिकियर हो जाता है। क्या आप नौकरी करने के लिए एक अलग प्रक्रिया का उपयोग कर सकते हैं? यदि ऐसा है, तो बहु-थ्रेडिंग के बजाय बहु-प्रसंस्करण का उपयोग करना।

यदि आप नियंत्रण (प्रक्रिया या धागा) के स्वायत्त धागे का उपयोग नहीं कर सकते हैं, तो यह इस बात पर निर्भर करता है कि आपका प्रोग्राम कैसे व्यवस्थित होता है, यही कारण है कि कई पसंदीदा विकल्प हैं (उन्हें विभिन्न परिस्थितियों के लिए प्राथमिकता दी जाती है)। यह आपको आवश्यक समय की सटीकता पर भी निर्भर करता है। मल्टी-सेकंड अंतराल और कोई वास्तविक रीयल-टाइम प्रतिक्रिया आवश्यकता के साथ, आप अलार्म का उपयोग कर सकते हैं और SIGALRM हैंडलर ध्वज सेट कर सकता है और आपका मुख्य प्रोसेसिंग लूप सुविधाजनक, समझदार बिंदुओं पर ध्वज की निगरानी कर सकता है और गतिविधि कर सकता है। यह कुछ हद तक गन्दा है (क्योंकि सिग्नल गन्दा हैं), लेकिन आपकी आवश्यकताओं और बाधाओं के बारे में अधिक विस्तृत विवरण के बिना, यह जानना मुश्किल है कि और क्या सुझाव देना है।

तो संक्षेप में, एक सार्वभौमिक रूप से सबसे अच्छा समाधान नहीं है क्योंकि अलग-अलग शैलियों में और विभिन्न बाधाओं के तहत विभिन्न कार्यक्रम लिखे जाते हैं।

+0

+1: बहुत अच्छा .. –

+0

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

3

तरह Boost.Asio

#include <iostream> 
#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 

class Timer 
{ 
public: 
    Timer(
      boost::asio::io_service& io_service 
     ) : 
     _impl(io_service) 
    { 
     this->wait(); 
    } 

private: 
    void wait() 
    { 
     _impl.expires_from_now(boost::posix_time::seconds(10)); 
     _impl.async_wait(
       boost::bind(
        &Timer::handler, 
        this, 
        _1 
        ) 
       ); 
    } 

    void handler(
      const boost::system::error_code& error 
      ) 
    { 
     if (error) { 
      std::cerr << "could not wait: " << boost::system::system_error(error).what() << std::endl; 
      return; 
     } 

     std::cout << "Hello World!" << std::endl; 

     this->wait(); 
    } 

private: 
    boost::asio::deadline_timer _impl; 
}; 

int main() 
{ 
    boost::asio::io_service io; 

    Timer t(io); 

    io.run(); 

    return 0; 
} 

निर्माण & रन एक घटना चालित पाश का उपयोग करें: आप करना चाहते रहे हैं पर

stackoverflow samm$ ./a.out 
Hello World! 
Hello World! 
Hello World! 
^C 
stackoverflow samm$ 
+1

मुझे वह जवाब पसंद है, लेकिन दुर्भाग्य से मेरे पास TR1/बूस्ट उपलब्ध नहीं है - साथ ही मुझे कुछ चाहिए वह ओएस या सीधा-सी आधारित है, इसलिए यह अधिक पोर्टेबल है। हालांकि इसे एक अच्छा समाधान के बाद इसे वोट दिया :) –

+0

अच्छा; और यदि इसे 'रन()' को एक अलग थ्रेड में डालकर आवश्यक हो तो इसे आसानी से बहुप्रचारित किया जा सकता है! –

+1

@ w00te: यदि आप कुछ "सीधी सी" चाहते हैं, तो कृपया अपने प्रश्न "सी ++" को टैग न करें! –

1

कैसे एक टाइमर करने के लिए के विकल्पों का उपयोग करें, पोर्टेबिलिटी, सटीकता, कुरूपता (वैश्विक राज्य/संकेतों), और उपयुक्तता वास्तविक समय अनुप्रयोगों के लिए में आसानी में भिन्नता है। निजी तौर पर, सभी दुनिया के सर्वश्रेष्ठ के लिए, मैं अपने स्वयं के टाइमर को थ्रेड के साथ रोल करने की सलाह देता हूं, और clock_nanosleep का उपयोग TIMER_ABSTIME ध्वज और CLOCK_MONOTONIC घड़ी स्रोत के साथ करता हूं। इस तरह आप सिस्टम समय को सेट करने से संचित त्रुटि और असंतुलन से बच सकते हैं, और आप स्वयं को ओवररन्स कर सकते हैं। सिद्धांत रूप में, SIGEV_THREAD वितरण के साथ POSIX timer_create आपको समान गुण दे सकता है, लेकिन ग्लिब कार्यान्वयन वास्तव में खराब है और यह गारंटी नहीं दे सकता कि यह भारी भार के तहत टाइमर समाप्ति घटनाओं को खो नहीं देगा।

+0

मुझे नहीं पता था कि 'SIGEV_THREAD' अविश्वसनीय माना जाता है। क्या यह व्यक्तिगत अनुभव से आता है, या कहीं कहीं एक बग रिपोर्ट है? – cnicutar

+0

यह स्रोत पढ़ने से आता है (टिप्पणियों सहित विफलता दस्तावेज सहित)। यह प्रत्येक डिलीवरी के लिए 'malloc' और' pthread_create' को कॉल करता है, और यदि विफल हो जाता है, तो डिलीवरी खो जाएगी और 'timer_getoverrun' में रिपोर्ट नहीं की जाएगी। सुरक्षित कार्यान्वयन टाइमर के लिए एक सतत धागा है जो प्रत्येक डिलीवरी के लिए पुन: उपयोग किया जाता है, लेकिन इसके लिए कुछ हैक्स और थ्रेड कार्यान्वयन के साथ बातचीत की आवश्यकता होती है ताकि 'pthread_exit' और' pthread_cancel' काम हो और थ्रेड का पुन: उपयोग किया जा सके। –

+0

जानकारी के लिए धन्यवाद, सराहना की :-) – cnicutar

1

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

वास्तव में, सभी विधियां बराबर हैं; ओएस टाइमआउट अवधि के लिए थ्रेड शेड्यूल करना बंद कर देता है।

SIGALARM विधि Blagovestus ने सुझाव दिया (कुछ) unportable, भले ही यह लिनक्स पर काम करना चाहिए है।

0

यदि आपको हर 10 सेकंड में एक बार "हैलो वर्ल्ड" आउटपुट करना है, तो मुझे लगता है कि नींद और नैनोस्लीस करेंगे। यदि आपके कार्य किसी भी तरह से अधिक महत्वपूर्ण हैं, तो आप रीयलटाइम लिनक्स पर एक नज़र डाल सकते हैं। वहां (www.ee.nmt.edu/~rison/ee352_fall09/Getting_Started_with_RTLinux.pdf) उन्होंने उस पर एक अच्छी मार्गदर्शिका डाली। आरटीएलनक्स का उपयोग करते समय आप कार्य अवधि के लिए pthread_make_periodic_np का उपयोग कर सकते हैं, हालांकि आप यह सुनिश्चित करने के प्रभारी होंगे कि वास्तविक समय की शर्तें संतुष्ट हैं।

1

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

कोड एक टाइमर का उपयोग करता है जो कॉलबैक ऑब्जेक्ट पर कॉल करता है। पूरे स्रोत

http://matthewh.me/playground/browser/branches/C%2B%2B/c%2B%2B_callbacks

+1

ठीक है, मैं अब सी # दुनिया में हूं, लेकिन प्रतिक्रिया अभी भी सराहना की गई है :) यह अच्छा कोड है इसलिए मुझे यकीन है कि यह किसी ऐसे व्यक्ति के लिए आसान होगा जो इसे देखता है सवाल। –