2012-09-27 7 views
8

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

#include <pthread.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <iostream> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/time.h> 
#include <signal.h> 
#include <cstdio> 
#include <stdlib.h> 

#define NUM_SENDER_PROCESSES 3 
#define NUM_HANDLER_PROCESSES 4 
#define NUM_SIGNAL_REPORT 10 
#define MAX_SIGNAL_COUNT 100000 


using namespace std; 

volatile int usrsig1_handler_count = 0; 
int usrsig2_handler_count = 0; 
int usrsig1_sender_count = 0; 
int usrsig2_sender_count = 0; 
int monitor_count = 0; 
int usrsig1_monitor_count = 0; 
int usrsig2_monitor_count = 0; 
double time_1[10]; 
double time_2[10]; 
int lock_1 = 0; 
int lock_2 = 0; 
int lock_3 = 0; 
int lock_4 = 0; 
int lock_5 = 0; 


double timestamp() { 
    struct timeval tp; 
    gettimeofday(&tp, NULL); 
    return (double)tp.tv_sec + tp.tv_usec/1000000.; 
} 

void sleepMs(double seconds) { 
    usleep((unsigned int)(seconds*1000000)); 
} 

void *senderfunc(void *parm) { 
    srand(time(0)); 
    while(true) { 
    int signal_id = rand()%2 + 1; 
    if(signal_id == 1) { 
     while(__sync_lock_test_and_set(&lock_3,1) != 0) { 
     } 
     usrsig1_sender_count++; 
     lock_3 = 0; 
     kill(getpid(), SIGUSR1); 
    } else { 
     while(__sync_lock_test_and_set(&lock_4,1) != 0) { 
     } 
     usrsig2_sender_count++; 
     lock_4 = 0; 
     kill(getpid(), SIGUSR2); 
    } 


    int r = rand()%10 + 1; 
    double s = (double)r/100; 
    sleepMs(s); 
    } 
} 

void *handlerfunc(void *parm) 
{ 
    int *index = (int *)parm; 
    sigset_t set; 
    sigemptyset(&set); 
    //cout << (*index) << endl; 
    if((*index) % 2 == 0) { 
    sigaddset(&set, SIGUSR1); 
    } else { 
    sigaddset(&set, SIGUSR2); 
    } 


    int sig; 

    while(true) { 
    sigwait(&set, &sig); 
    //cout << "Handler" << endl; 
    if (sig == SIGUSR1) { 
     while(__sync_lock_test_and_set(&lock_1,1) != 0) { 
     } 
     usrsig1_handler_count++;   
     lock_1 = 0; 
    } else if(sig == SIGUSR2) { 
     while(__sync_lock_test_and_set(&lock_2,1) != 0) { 
     } 
     usrsig2_handler_count++; 
     lock_2 = 0; 
    } 

    sleepMs(0.0001); 
    } 

} 

void *monitorfunc(void *parm) { 

    sigset_t set; 
    sigemptyset(&set); 

    sigaddset(&set, SIGUSR1); 
    sigaddset(&set, SIGUSR2); 

    int sig; 

    while(true) { 
    sigwait(&set, &sig); 
    //cout << "Monitor" << endl; 
    if(sig == SIGUSR1) { 
     time_1[usrsig1_monitor_count] = timestamp(); 
     usrsig1_monitor_count++; 
    } else if(sig == SIGUSR2) { 
     time_2[usrsig2_monitor_count] = timestamp(); 
     usrsig2_monitor_count++; 
    } 
    monitor_count++; 
    //cout << monitor_count << endl; 

    if(monitor_count == NUM_SIGNAL_REPORT) { 
     double difference_1 = 0; 
     double difference_2 = 0; 
     if(usrsig1_monitor_count > 1) { 
     for(int i=0; i<usrsig1_monitor_count-1; i++) { 
      difference_1 = difference_1 + time_1[i+1] - time_1[i]; 
     } 
     cout << "Interval SIGUSR1 = " << difference_1/(usrsig1_monitor_count-1)<< endl; 
     } 

     if(usrsig2_monitor_count > 1) { 
     for(int i=0; i<usrsig2_monitor_count-1; i++) { 
      difference_2 = difference_2 + time_2[i+1] - time_2[i]; 
     } 
     cout << "Interval SIGUSR2 = " << difference_2/(usrsig2_monitor_count-1) << endl; 
     } 
     cout << "Count SIGUSR1 = " << usrsig1_sender_count << endl; 
     cout << "Count SIGUSR2 = " << usrsig2_sender_count << endl; 
     monitor_count = 0; 
     usrsig1_monitor_count = 0; 
     usrsig2_monitor_count = 0; 
    } 

    sleepMs(0.001); 

    } 
} 

int main(int argc, char **argv) 
{ 
    if(argc != 2) { 
    cout << "Required parameters missing. " << endl; 
    cout << "Option 1 = 1 which means run for 30 seconds" << endl; 
    cout << "Option 2 = 2 which means run until 100000 signals" << endl; 
    exit(0); 
    } 

    int option = atoi(argv[1]); 
    int i; 

    pthread_t handlers[NUM_HANDLER_PROCESSES]; 
    pthread_t generators[NUM_SENDER_PROCESSES]; 
    pthread_t monitor; 

    sigset_t set; 
    sigset_t oldset; 
    sigemptyset(&oldset); 
    sigemptyset(&set); 
    sigaddset(&set, SIGUSR1); 
    sigaddset(&set, SIGUSR2); 

    pthread_sigmask(SIG_BLOCK, &set, &oldset); 


    int handler_mask[4] = {0,1,2,3}; 
    //Initializing the handler threads 
    for(i=0; i<NUM_HANDLER_PROCESSES; i++) { 
    pthread_create(&handlers[i], NULL, handlerfunc, (void *)&handler_mask[i]); 
    } 

    pthread_create(&monitor, NULL, monitorfunc, NULL); 

    sleep(5); 

    for(i=0; i<NUM_SENDER_PROCESSES; i++) { 
    pthread_create(&generators[i], NULL, senderfunc, NULL); 
    } 

    if(option == 1) { 
    cout << "Option 1 " << endl; 
    //sleep(30); 
    while(true){ 

    } 
    exit(0); 
    } else { 
    while(true) { 
     if((usrsig1_handler_count + usrsig2_handler_count) >= MAX_SIGNAL_COUNT) { 
     cout << "Count SIGUSR1 = " << usrsig1_handler_count << endl; 
     cout << "Count SIGUSR2 = " << usrsig2_handler_count << endl; 
     exit(0); 
     } else { 
     pthread_yield(); 
     } 
    } 
    } 
} 

प्रदर्शित नहीं करता है यहाँ आप हैंडलर के फट द्वारा पीछा किया पर नजर रखने के फट देख सकते हैं मेरी उत्पादन

HandlerHandler 

Handler 
Handler 
Monitor 
Monitor 
... whole bunch of Monitor messages 
Monitor 
Monitor 
Handler 
Handler 
... whole bunch of Handler messages 
Handler 
Handler 

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

+0

यदि आप आउटपुट को अंतःस्थापित करना चाहते हैं तो आपको सेमफोर या सिग्नल का उपयोग करना चाहिए। –

+0

@ जोचिम मुझे यह नहीं मिला कि आपका क्या मतलब है? – user34790

+0

उदा। देखें [ 'Pthread_cond_init'] (http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_init.html)। –

उत्तर

1

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

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

अब संकेतों को समान रूप से प्रेषित करने के लिए मुझे अपने स्वयं के तंत्र को लागू करना होगा (चूंकि ओएस के पास इसके लिए कोई तंत्र नहीं है)। मैं प्रत्येक थ्रेड के लिए condition_variable बना सकता हूं और उनमें से प्रत्येक पहले अपने condition_variable के लिए प्रतीक्षा कर सकता है और फिर sigwait पर कॉल कर सकता है और निष्पादन पूरा करने के बाद यह अगले थ्रेड के condition_variable सेट करेगा और ऑपरेशन जैसा होगा!

3

आप किस ओएस का उपयोग कर रहे हैं? निर्भर करने के लिए आपको रीयलटाइम ऑपरेटिंग सिस्टम (आरटीओएस) की आवश्यकता है। रोबोट नियंत्रक को चलाने के लिए On Time RTOS-32 नामक बहुत छोटे आरटीओएस का उपयोग करके मेरे अच्छे नतीजे थे। यह गारंटीकृत विलंबता के साथ समय-टुकड़ा कर सकता है, या आप सहकारी शेड्यूलिंग करना चुन सकते हैं। इसमें Win API के सबसेट के लिए विंडो इम्यूलेशन सेट है। हमने आईडीई के रूप में विजुअल स्टूडियो/वीसी ++ का इस्तेमाल किया। आरटीओएस के अब उपलब्ध एक बहुत अच्छी किस्म हो सकती है। वह लगभग 10 साल पहले था। आरटीओएस और "रीयलटाइम ऑपरेटिंग सिस्टम" के लिए Google।

विकल्प, जो तेजी से, समर्पित मशीन पर पर्याप्त हो सकता है, "हाथ से" धागे को निर्धारित करने के लिए अपना "ओएस के भीतर ओएस" लिखना है। थ्रेड को असाइनमेंट के लिए इंतजार करने के तरीके को बदलना होगा।

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

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

  • कोई संबंधित समस्या नहीं^_^