كيفية تعيين حد زمني على وظيفة مع منطقة آمنة

StackOverflow https://stackoverflow.com/questions/3622015

  •  26-09-2019
  •  | 
  •  

سؤال

أحاول تطوير برنامج للوقت الزمني لتنفيذ الوظيفة. في الكود أدناه لدي وظيفة مسماة Inc الذي يقوم بالكثير من التكرارات (محاكاة بواسطة الحلقة اللانهائية). الجزء الأول من كل تكرار طويل جدًا ، يليه الجزء الثاني الذي يجب أن يكون سريعًا جدًا.

لا مانع من الاستباق للتنفيذ بينما في الجزء الأول من الكود ، لكنني أرغب في تجنب التنبيه أثناء القيام بعملية الكتابة في الجزء الثاني.

كانت فكرتي الأولى هي إيقاف تشغيل المنبه قبل الدخول إلى "المنطقة الآمنة" في توفير الوقت المتبقي. ثم بعد الخروج ، كنت أقوم بإعداد المنبه مع الوقت المحفوظ. لا أعرف كيفية تنفيذ هذا. هل يمكن لأحد أن يساعدني؟ الطرق البديلة موضع ترحيب أيضًا.

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

pthread_t thread;
FILE *fout;

void *Inc(void *param){

    int i;
    long long int x = 0;

    fout = fopen("file.txt", "w");

    /* Large number of iterations */
    while(1){

        int k = 0;
        for(i=0; i<5000000; i++)
            k += (rand())%3;
        x += k;

        printf("%lld\n", x);
        /* Enter Safe Region */
        fprintf(fout, "%lld\n", x);
        /* Exit Safe Region */
    }   
}

void Finish(int param){
    pthread_cancel(thread);
    fclose(fout);
}

main (){

    pthread_attr_t attr;
    void *status;

    signal(SIGALRM, Finish);
    alarm(10);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&thread, &attr, Inc, NULL);
    pthread_attr_destroy(&attr);
    pthread_join(thread, &status);

    printf("Program Finished\n");
}
هل كانت مفيدة؟

المحلول

الشيء الواضح هو أخذ قفل قبل الاتصال pthread_cancel, ، وللحصول على نفس القفل عبر "منطقتك الآمنة".

لسوء الحظ ، لا يمكنك الانتظار على mutex أو semaphore في معالج الإشارة. لكن إشارات الإنذار ليست هي الطريقة الوحيدة للقيام بشيء ما بعد 10 ثوانٍ - يمكنك بدلاً من ذلك أن ينام خيطك الرئيسي لمدة 10 ثوانٍ ، ثم استيقظ ، واتخذ القفل ، وإلغاء موضوع العامل ثم الانضمام إليه.

بالطبع هذا يعني أن الخيط الرئيسي سينام 10 ثوانٍ حتى لو انتهى خيط العمال بعد 5 ثوانٍ. لذا ، بدلاً من النوم ، اطلب من الخيط الرئيسي القيام بوقت 10 ثوانٍ الانتظار على إشارة ، والتي ينشرها خيط العمال عند الانتهاء.

مثل النوم ، يمكن أن يكتمل الانتظار المحدد في وقت مبكر بسبب الإشارة ، لذا تأكد من إعادة إعادة توقيت الانتظار على Eintr. حالاتك المهمة هي eIntr (انتظر مرة أخرى) ، والنجاح (انضم إلى موضوع العامل - لا حاجة إلى الإلغاء لأنها قد نشرت semaphore) ، etimedout (خذ القفل ، الإلغاء ، الانضمام) ، وإذا أردت ، أخطاء أخرى. لا توجد أخطاء أخرى مدرجة sem_timedwait هذا يجب أن يؤثر عليك ، رغم ذلك.

هناك فكرة أخرى تتمثل في منع SIGALRM عبر "منطقتك الآمنة" ، والتي ستكون أبسط إلا أنه (أ) لا يمكنني أبدًا أن أتذكر كيفية عمل I/O بأمان مع تعطيل الإشارات ، و (ب) يمكن أن يكون موضوع العمال الخاص بك على الأرجح "في وقت واحد" "من خلال معالج الإشارة (إما متزامنًا حقًا أو على ما يبدو بسبب ما يبعث على الاستبدال) ، وهذا يعني أنه يمكن أخذ الإشارة ، ثم يقوم العامل بتعطيل الإشارات ويدخل المنطقة الحرجة ، ثم يقوم معالج الإشارة بإلغاءها. إذا لم يرد أحد على أنه يمكن أن يتذكر التفاصيل بالفعل ، فإليك بعضًا معلومات عن حظر الإشارات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top