質問

関数の実行に時間を制限するプログラムを開発しようとしています。以下のコードには、という名前の関数があります。 Inc これにより、多くの反復が行われます (無限ループによってシミュレートされます)。各反復の最初の部分は非常に長く、その後に続く 2 番目の部分はかなり高速になります。

コードの最初の部分で実行をプリエンプトすることは問題ありませんが、2 番目の部分で書き込み操作を実行しているときにアラームが鳴るのは避けたいと考えています。

私の最初のアイデアは、「安全領域」に入る前にアラームを止めて残り時間を節約することでした。そして退出後、保存された時間でアラームをセットします。これを実装する方法がわかりません。誰か助けてくれませんか?代替方法も歓迎です。

#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, 、そして「安全な領域」全体で同じロックを保持します。

残念ながら、シグナル ハンドラーでミューテックスやセマフォを待機することはできません。ただし、アラーム シグナルが 10 秒後に何かを行う唯一の方法ではありません。代わりに、メイン スレッドを 10 秒間スリープ状態にしてから復帰し、ロックを取得し、ワーカー スレッドをキャンセルしてからそれに参加することもできます。

もちろん、これは、ワーカー スレッドが 5 秒後に終了したとしても、メイン スレッドは 10 秒スリープすることを意味します。そのため、スリープする代わりに、メインスレッドにセマフォで 10 秒間の時間を指定して待機させ、終了時にワーカー スレッドがポストします。

スリープと同様に、時間指定された待機はシグナルによって早期に完了する可能性があるため、必ず EINTR で時間指定された待機を再試行してください。重要なケースは、EINTR (再度待機)、成功 (ワーカー スレッドに参加 - セマフォがポストされているためキャンセルする必要はない)、ETIMEDOUT (ロックの取得、キャンセル、参加)、および必要に応じてその他のエラーです。他にエラーはリストされていません sem_timedwait ただし、それはあなたに影響を与えるはずです。

もう 1 つのアイデアは、「安全な領域」全体で SIGALRM をブロックすることです。これは、(a) シグナルを無効にして I/O を安全に実行する方法をまったく覚えていない、(b) ワーカー スレッドが「同時に実行されている可能性がある」という点を除けば、より簡単です。 " シグナル ハンドラーと (実際に同時であるか、プリエンプションにより明らかに同時であるかのどちらか)、シグナルが取得される可能性があることを意味します。その後、ワーカーがシグナルを無効にしてクリティカル領域に入り、その後シグナル ハンドラーがシグナルをキャンセルします。詳細を実際に覚えている人が誰も答えない場合は、以下にいくつか挙げます 信号遮断に関する情報.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top