2017-01-12 5 views
0

epollを使用してtimerfdをチェックアウトし、いくつかのアクションを開始しようとしています。 コードは打撃です:別々timerfdを使用する場合epollを使用しているときにtimerfdを読む準備ができていない

#include <time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/timerfd.h> 
#include <stdint.h> 
#include <unistd.h> 
#include <sys/epoll.h> 

int main(int argc, char const *argv[]) 
{ 
    struct timespec now; 
    clock_gettime(CLOCK_MONOTONIC, &now); 
    int timerfd; 
    timerfd = timerfd_create(CLOCK_MONOTONIC, 0); 
    struct itimerspec new_value; 
    new_value.it_value.tv_sec = 1; 
    new_value.it_interval.tv_sec = 1; 
    timerfd_settime(timerfd, 0, &new_value, NULL); 
    // uint64_t buff; 
    // while(true) { 
    // read(timerfd, &buff, sizeof(uint64_t)); 
    // printf("%s\n", "ding"); 
    // } 

    // code above works fine. 

    struct epoll_event ev, events[10]; 
    int epollfd; 
    epollfd = epoll_create1(0); 
    if (epollfd == -1) { 
     perror("epoll_create1"); 
     exit(EXIT_FAILURE); 
    } 
    ev.events = EPOLLIN; 
    ev.data.fd = timerfd; 

    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev) == -1) { 
     perror("epoll_ctl: timerfd"); 
     exit(EXIT_FAILURE); 
    } 
    int num; 
    printf("start\n"); 
    while(true) { 
     num = epoll_wait(epollfd, events, 10, -1); 
     printf("%d\n", num); 
     uint64_t buff; 
     read(timerfd, &buff, sizeof(uint64_t)); 
     printf("%s\n", "ding"); 
    } 
    return 0; 
} 

、それが正常に動作します。毎秒 "ding"が印刷されます。しかし、epollを追加してtimerfdを観察すると、progromはepoll_waitで永久にブロックされます。 EPOLLETを使用して試しましたが、変更がありました。このコードで何が問題になっていますか?

答えて

3

itimerspecが正しく初期化されていないため、含まれる特定のガベージ値によっては、timerfd_settime()が失敗することがあります。それを検出するために、エラーチェックを実行します。これをデバッグする

if (timerfd_settime(timerfd, 0, &new_value, NULL) != 0) { 
     perror("settime"); 
     exit(-1); 
} 

をもう一つの方法は、straceの下で、あなたのプログラムを実行することです、プログラム、およびあなたは失敗し、もしあれば、システムコールが表示されます。

関連する構造体は次のようになります。

struct timespec { 
    time_t tv_sec; 
    long tv_nsec; 
}; 

struct itimerspec { 
    struct timespec it_interval; 
    struct timespec it_value; 
}; 

あなたは完全にこれらのメンバーの両方を初期化する必要があり、そして、あなたのプログラムが確実に動作します:

new_value.it_value.tv_sec = 1; 
new_value.it_value.tv_nsec = 0; 
new_value.it_interval.tv_sec = 1; 
new_value.it_interval.tv_nsec = 0; 
+0

は、なぜこれがコメントせずにdownvotedでしたか?これはほぼ確実に正解です。 10億を超えるtv_nsecの初期化されていないガーベジは、観測された動作(私がテストしたばかり)を間違いなく引き起こしますが、正しく初期化するとコードが機能します。また、より多くのコードを追加すると、スタックを再シャッフルして、タイマの初期化されていない値を変更する可能性があります。 – Art

+0

この答えは確かに正しい答えです、私は賞金を支払ったのです。しかし、私はコードを書き直すための提案を使用しても、完全に初期化されていないまま読み込みを使用する理由を知りません。なぜ誰に教えていただけますか? – reavenisadesk

+0

@reavenisadeskおそらくその場合、変数にはまだ有効な値だったゴミ値が含まれていて、コードへの小さな変更やゴミは変更され、 'tv_nsec'の有効範囲外になる可能性があります。 – nos

関連する問題