2012-06-29 16 views
9

करने के लिए काम न करे, ठीक है, इसलिए यह प्रश्न बिल्कुल थ्रेड प्रबंधन के बारे में नहीं है ... ठीक है, तरह। मैं इस विन्यास के विभिन्न समाधानों की तलाश में हूं। मेरे पास कुछ विचार हैं, लेकिन मैं ऐसे समाधान ढूंढ रहा हूं जो समस्या को पूरा कर सकें। और सबसे अच्छे को लागू करने के लिए पेशेवरों और विपक्ष का वजन होगा।मुझे इस धागे को सोने के लिए एक तरीका लागू करने की आवश्यकता है जब तक कि यह

यहां स्थिति है।

मेरे पास एक प्रबंधक अनुप्रयोग है जो धागे को जन्म देगा। यह धागा यूएसबी के माध्यम से सिस्टम से जुड़े बोर्डों के साथ सीरियल संचार को लगातार चलाएगा और संभाल देगा। प्रबंधक अनुप्रयोग सिस्टम और इस धागे पर चल रहे अन्य अनुप्रयोगों के बीच संचार की सुविधा प्रदान करता है। धागा वास्तव में दो बातें प्रदर्शन करने की जरूरत है: .. धारावाहिक के माध्यम से नमूना डेटा के लिए

  1. पोल बोर्डों एक चर टाइमर पर आमतौर पर के बारे में एक बार एक मिनट (सीरियल बस बल्कि धीमी गति से, बॉड 4800 है मैं नहीं कर सकता इसे नियंत्रित करें)
  2. प्रबंधक अनुप्रयोग के साथ संचार की सुविधा। (यानी अन्य अनुप्रयोग नमूना डेटा का अनुरोध करेंगे, प्रबंधक थ्रेड के अनुरोध को आगे बढ़ाएगा। थ्रेड ऑपरेशन करता है और डेटा देता है)

मेरा प्रारंभिक डिज़ाइन एक साधारण था और काम करता था। मैं थ्रेड संचार के लिए प्रबंधक के लिए एक कतार और एक mutex का उपयोग करें। तो धागे के तर्क इस प्रकार है:

  1. प्रारंभ
  2. हम प्रबंधक
  3. यदि हमारे टाइमर निर्भर है, डेटा
  4. के लिए बोर्ड अन्यथा मतदान से एक बंद आदेश नहीं मिला है, वहीं यह देखने के लिए जांचें कि क्या हमारे पास प्रबंधक द्वारा कतार में पोस्ट किया गया संदेश है या नहीं। यदि हां, तो इसे

समस्या यह है कि मैंने CPU उपयोग पर विचार नहीं किया। 99.9% जब मेरा धागा कुछ भी संसाधित नहीं कर रहा है और सिर्फ बिजली को चूस रहा है। मुझे इस थ्रेड को सोने के लिए एक तरीका लागू करने की आवश्यकता है जब तक कि यह करने के लिए काम न करे। तो कुछ विचार:

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

प्रो: बिल्कुल मुझे जिस कार्यक्षमता की आवश्यकता है।

कॉन: क्या थ्रेड को संचार के लिए थोड़ा भारी प्रोसेसिंग नहीं है जहां आप पहले से ही स्मृति साझा करते हैं?

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

प्रो: वर्तमान कार्यान्वयन साझा स्मृति का उपयोग कर

कोन को बनाये रखता है: सुनिश्चित नहीं हैं कि लागू करने के लिए। क्या कोई फ़ंक्शन चुनिंदा() है जो fds के बजाय सिग्नल के साथ काम करता है?

संभावित रूप से एक म्यूटेक्स। मैनेजर द्वारा एक म्यूटेक्स पोस्ट किए जाने तक मैं ब्लॉक कर सकता था।

प्रो: फिर भी साझा करने स्मृति

कोन: प्रबंधक को टाइमर प्रसंस्करण स्थानांतरित करने के लिए आवश्यकता हो सकती है और जो वास्तव में एक विकल्प के रूप में यह अन्य टाइमर और महत्वपूर्ण काम को करने के है नहीं है।

कृपया सिफारिश करें और आलोचना करने के लिए स्वतंत्र महसूस करें। मैं किसी भी कुशल विकल्प के लिए खुला हूँ। कृपया ध्यान दें कि यह एक एम्बेडेड सिस्टम पर चल रहा है, इसलिए संसाधनों का उपयोग महत्वपूर्ण है।

+3

जब आप किसी ईवेंट की प्रतीक्षा करते हैं तो सशर्त चर का उपयोग क्यों न करें? थ्रेड को तब तक नींद में डाल दिया जाता है जब तक चर को किसी अन्य थ्रेड द्वारा संकेतित नहीं किया जाता है। – Tudor

+0

मैं बिल्कुल कर सकता था, लेकिन मुद्दा यह है कि मैं कुछ भी संसाधित नहीं करना चाहता हूं। मैं बार-बार एक वैरिएबल के मान की जांच नहीं करना चाहता जो हर मिनट में एक बार बदलने जा रहा है। यह बहुत अधिक है। मैं धागा सोना चाहता हूं ताकि यह सीपीयू का समय छोड़ दे। – linsek

+1

सुनिश्चित करें कि आप इससे बचें: http://stackoverflow.com/questions/3886171/why-thread-sleep-is-so-cpu-intensive –

उत्तर

3

कोशिश कुछ, संकेतबाहु का उपयोग कर:

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <semaphore.h> 

static sem_t s_sem; 
static int iAlive = 1; 

void* thFunc(void *param) 
{ 
    printf("%s : ENTER \n", __FUNCTION__); 
    while(iAlive) 
    { 
     printf("%s : waiting \n", __FUNCTION__); 
     sem_wait(&s_sem); 

     printf("%s : got a signal - doing something \n", __FUNCTION__); 
     sleep(1); 
    } 

    printf("%s : EXIT \n", __FUNCTION__); 
    return 0; 
} 

int main() 
{ 
    pthread_t thread; 
    sem_init(&s_sem, 0, 0); 

    if(0 != pthread_create(&thread, NULL, thFunc, NULL)) 
    { 
     printf("%s : pthread_create FAILED \n", __FUNCTION__); 
     return -1; 
    } 

    while (getchar() != 'q') 
    { 
     printf("%s : sending signal \n", __FUNCTION__); 
     sem_post(&s_sem); 
    } 

    iAlive = 0; 
    sem_post(&s_sem); 
    pthread_join(thread, NULL); 
    sem_destroy(&s_sem); 

    return 0; 
} 

आप sem_timedwait साथ sem_wait जगह ले सकता है अगर आप एक समय समाप्ति की जरूरत है।

3

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

टाइमआउट को बदलने के लिए, थ्रेड को 'EchangeWaitInterval', (कहें :), और अगली प्रतीक्षा के लिए उपयोग करने के लिए नए टाइमआउट अंतराल के साथ एक संदेश भेजें।

4

अपने आप के बजाय POSIX संदेश कतार में स्विच करें। mq_timedreceive प्रबंधक वापस अनुरोध करेगा अगर वापस आ जाएगा। यदि यह समय समाप्त हो जाता है, तो आपको अपना टाइमर मतदान करना होगा। Synchonization और अवरुद्ध पहले से ही पैक आता है।

+0

यूप, जो करना चाहिए। –

+0

थोड़ा बहुत भारी, सेमफोर थोड़ा सा सरल हैं। –

5

ऐसी परिस्थितियों को संभालने के लिए शास्त्रीय उपकरण सेमफोर हैं और म्यूटेक्स या हालत चर नहीं हैं। उनके बारे में सोचें कि प्रबंधक से थ्रेड तक टकन पास हो गए हैं।

धागा डेटा की जांच करने के लिए थोड़ी देर में जागने के लिए sem_timedwait का उपयोग कर सकता है।

sem_ फ़ंक्शन अच्छी तरह से त्रुटि रिटर्न कैप्चर करने के लिए सावधान रहें, वे बाधित हैं। तो आपके विचार से थोड़ा अधिक जाग उठ सकता है।

+0

यहां एक जोड़े सेमफोर उत्तर दिए गए हैं, इसलिए बस उन सभी को जवाब देंगे। जागने के लिए टाइमर के रूप में एक सेमफोर का उपयोग करना और डेटा की जांच करना() के साथ अवरुद्ध करने और सॉकेट पर डेटा प्राप्त करने से अधिक कुशल होना चाहिए? एक ओर, मैं recv() की बजाय साझा स्मृति का उपयोग कर रहा हूं, लेकिन दूसरी तरफ, अगर मुझे किसी अन्य एप्लिकेशन से अनुरोध प्राप्त नहीं होता है। मैं किसी कारण से प्रसंस्करण कर रहा हूँ। – linsek

+0

जैसा कि आप अपनी समस्या का वर्णन करते हैं, तथ्य यह है कि आपका धागा सो नहीं है वास्तव में महत्वपूर्ण है। इसका मतलब है कि यदि आप इसे चारों ओर बदलते हैं, तो आपका धागा उस से अधिक काम नहीं कर रहा है। तो यदि आप इस "नींद" समस्या को निपुण करते हैं, तो आप जो समाधान लेते हैं, उस पर समग्र काम (सीपीयू चक्र) पर अधिक प्रभाव नहीं पड़ता है जो थ्रेड द्वारा उपयोग किया जाता है। अंतर तब (1) सुविधा में हैं, प्रोग्राम किया गया है और सबसे आसान (2) विलंबता बनाए रखा है। दोनों के लिए मुझे लगता है कि semaphores जीत। –

+0

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

0

क्लासिक pthreads दृष्टिकोण के लिए pthread_cond_wait() में आपका थ्रेड ब्लॉक होना होगा जब तक कि प्रबंधक धागा कतार में कोई संदेश न रखे और स्थिति चर को सिग्नल करे। इस मामले में, धारावाहिक उपकरणों को मतदान करने के लिए समय पर जागने के लिए, pthread_cond_timedwait() का उपयोग करें। इस तरह