2017-03-08 9 views
0

私はsigactionハンドラを持つCプログラムを書いています。 SIGALRMがしばらく来ていない場合は、itimervalもあります。シグナルハンドラの印刷時間の経過は?

ハンドラは、無限ループの総数は時間が

  • 出口(1)が経過
  • 印刷を完了

    1. 印刷をすべきです。

    シグナルハンドラがカスタマイズされたパラメータを受け取っていないことに気づいたので、グローバルループカウンタがあります。
    私の問題は次のとおりです。どのように時間が経過していますか?タイマーからその情報を取得できますか?タイマーの使い方を完全に理解していません。
    また、コードは、終了前にfprintf呼び出しの後に1つの余分な整数(ループから)を出力しています。それを修正するには?

    コード:

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <time.h> 
    #include <signal.h> 
    #include <unistd.h> 
    #include <sys/time.h> 
    
    int count = 0; 
    
    void handler (int code) { 
        fprintf(stderr, "Reads completed: %d \n", count); 
        exit(1); 
    } 
    
    int main(int argc, char const *argv[]) 
    { 
        if (argc != 3) { 
         fprintf(stderr, "Usage: time_reads FILENAME TIMER\n"); 
         exit(1); 
        } 
    
        FILE *fp; 
        fp = fopen(argv[1], "rb"); 
        if (fp == NULL) { 
         fprintf(stderr, "Fail to open file\n"); 
         exit(1); 
        } 
    
        int i; 
        srand(time(NULL)); 
    
        struct sigaction sa; 
        sa.sa_handler = handler; 
        sa.sa_flags = 0; 
        sigemptyset(&sa.sa_mask); 
        sigaction(SIGALRM, &sa, NULL); 
    
        struct itimerval timer; 
        timer.it_value.tv_sec = strtol(argv[2], NULL, 10 ); 
        timer.it_value.tv_usec = 0; 
        timer.it_interval.tv_sec = 0; 
        timer.it_interval.tv_usec = 0; 
    
        if (setitimer(0, &timer, NULL) < 0) { 
         fprintf(stderr, "Fail to set timer\n"); 
         exit(1);  
        } 
    
        while(1) { 
         fseek(fp, (rand() % 100) * sizeof(int), SEEK_SET); 
         fread(&i, sizeof(int), 1, fp); 
         printf("%d\n", i); 
         count++; 
        } 
    
        fclose(fp); 
    
        return 0; 
    } 
    
  • +0

    注:シグナルハンドラからprintf()(およびfriends)を呼び出さないでください。信号には安全ではありません。 – wildplasser

    +0

    @wildplasserそれを思い出させてくれてありがとう、しかし、私の割り当てからそうするように頼んだので、私はそれを呼び出さなければならない。 –

    +0

    シグナルハンドラが終了すると、プログラム全体が終了することに注意してください。これを複数回実行したい場合は、シグナルハンドラが 'exit()'を呼び出さずに、戻る必要があります。経過時間の測定:開始時間を記録する。ハンドラで、現在の時刻を見つけます。差を計算してフォーマットします。 –

    答えて

    0

    経過時間を印刷するためには、ハンドラはタイマーへのアクセス権を持っている必要があります。これを行う簡単な方法は、タイマーをカウンタのようにグローバル変数にすることです。余分な整数が出力されるのは、printf()の呼び出しの途中でシグナルがループを中断したためです。ループのprintf()は、ループハンドラの総数がシグナルハンドラによって出力されるため、削除する必要があります。

    +0

    ループ内のprintf()は削除する必要がありますか?いいえ!それは単にプログラムの目的を変えるだけです。答える前に注意深く検討してください。 –

    +0

    私の間違いは、ファイルからデータを印刷するためにprintf()が必要なようです。この場合、printf()の呼び出し中にハンドラがメインループを中断しないようにする方法はありません。これは、ハンドラがすでに経過した時間を印刷した後で、最終的な整数が出力されることがあります。代わりの方法は、ハンドラにブール値を設定させ、ブール値が変化したときにループを正常に終了させることです。この場合、経過した時間は、ループの後のmain関数によって最後に終了する前に出力されます。 –