2012-01-25 127 views
1

我正在開發一個簡單的軟件來檢查我是否能夠使用我研究的POSIX定時器和信號進行編程。POSIX定時器和POSIX信號處理

我試圖做一個簡單的程序,啓動一個定時器,發出的信號一定量的納秒

下面的程序無法正常工作,所以我寫了一篇關於我的代碼一些評論,所以你可以檢查我正確研究與否。 您可以在頁面底部找到完整的代碼清單。

prinf("1\n")
這樣的各種打印件將檢查程序提前退出的位置。 我把
struct sigevent sigeventStruct
作爲定時器生成的到期事件的結構。 第一個參數設置爲SIGEV_SIGNAL,因此這是它將發出的信號種類。 /// 您可以在代碼清單中讀取的各種memset都是零初始化結構。

if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)

是創建一個POSIX計時器。 POSIX MONOTONIC CLOCK是一種定時器,& sigeventStruct是指向描述它是如何由定時器過期生成的事件的結構的指針。 & timer1是指向特定計時器名稱的指針。

if(timer_settime(timer1, NULL, &tempoIniziale, &tempoFinale) == -1)

用這個程序,定時器是裝備的,所以你可以使它生成到期。 timer1是定時器的名稱,0是標誌。 GAPIL書說:<> & tempoIniziale和& tempoFinale是指向itimerspec結構的指針。我還沒有很好地理解& old_timer的含義。在GAPIL書,你可以閱讀:將作爲參數傳遞 <>

struct sigaction, oldSigAzione

的sigaction結構針對sigaction POSIX信號處理

sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione)

SIGEV_SIGNAL是一種信號,它具有處理,空IS在那裏它可以放置一個指向const struct sigaction的指針,& oldSigAzione是指向我前面提到的sigaction結構的指針。在這裏,我還沒有理解這兩個指向sigaction結構的指針之間的區別。

我的問題是: 爲什麼程序在打印printf(「19 \ n」)的19號之前退出;爲什麼不執行printf(「Timer scaduto \ n」);裏面的函數void termination_handler(int signum)?

這裏我的代碼:

#include <string.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <time.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/fcntl.h> 
#include <sys/wait.h> 
#include <stdbool.h> 

void termination_handler(int signum) 
{ 
    printf("Timer scaduto\n"); 
} 

int main() 
{ 
    printf("Start\n"); 
    printf("1\n"); 
    struct sigevent sigeventStruct; // sigevent struct that will be used by timer1 timer 
    printf("2\n"); 
    memset(&sigeventStruct, 0, sizeof sigeventStruct); // zero initialize struct 
    printf("3\n"); 
    sigeventStruct.sigev_notify = SIGEV_SIGNAL; // kind of notification of timer1 expiration 
    printf("4\n"); 
    sigeventStruct.sigev_signo = 10; 
    printf("5\n"); 

    timer_t timer1; // create a timer identifier 
    printf("6\n"); 
    if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1) 
    { 
     printf("Errore timer_create: %s\n", strerror(errno)); 
    } 

    printf("7\n"); 
    struct itimerspec tempoIniziale; 
    printf("8\n"); 
    memset(&tempoIniziale, NULL, sizeof tempoIniziale); // zero initialize struct 
    printf("9\n"); 
    tempoIniziale.it_value.tv_nsec = 100000000; 
    //tempoIniziale.it_interval.tv_nsec = 10000; 
    printf("10\n"); 


    if(timer_settime(timer1, 0, &tempoIniziale, NULL) == -1) // timer armed 
    { 
     printf("Errore timer_settime: %s\n", strerror(errno)); 
    } 
    printf("11\n"); 
    for(int i = 0; i< 10; i++) 
    { 
     printf("ciclo %d\n", i); 
    } 

    struct sigaction oldSigAzione; 
    printf("12\n"); 
    memset(&oldSigAzione, 0, sizeof oldSigAzione); 
    printf("13\n"); 
    oldSigAzione.sa_handler = termination_handler; 
    printf("14\n"); 
    sigemptyset (&oldSigAzione.sa_mask); 

    printf("15\n"); 
    oldSigAzione.sa_flags = 0; 

    printf("16\n"); 
    sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione); 
    printf("17\n"); 
    if(oldSigAzione.sa_handler == SIG_IGN) 
    { 
     printf("Segnale ignorato\n"); 
    } 
    printf("18\n"); 
    for(int i = 0; i < 1000000000000; i++) 
    { 

    } 
    printf("19\n"); 
    printf("number of expirations %d\n", timer_getoverrun(timer1)); 
    return 0; 
} 
+1

空的for循環不是延遲的方式。一個現代編譯器將它編譯成完全沒有代碼。試試'sleep' ... –

+1

另外,'printf'不是異步信號安全的。你不能在信號處理程序中使用它,除非你避免在代碼中可能被信號中斷的所有對異步信號不安全函數的調用。 –

回答

5

在調用timer_create(),第一個參數應該是一個clockid如CLOCK_MONOTONIC_POSIX_MONOTONIC_CLOCK只是一個宏,您可以在編譯時使用它來測試系統是否支持CLOCK_MONOTONIC

sigaction()的第一個參數應該是信號編號,而不是SIGEV_SIGNAL。在你的情況下,你正在使用信號10,但這不是一個好的選擇,因爲通常這將是預定義的OS信號之一。通常,您會使用用戶定義的信號,如SIGUSR1或實時信號,如SIGRTMIN,因爲這些信號是爲應用程序定義的。另外您致電sigaction()不會設置信號處理程序,因爲第二個參數爲NULL。第二個參數應該是一個指向你的新信號動作的指針。相反,您正在使用用於返回前一個信號動作的第三個參數。這允許您暫時設置一個新的信號動作,同時保存舊的信號動作,然後當您完成新動作時,可以將其設置回保存的值。既然你永遠不會再改變它,你沒有任何需要獲得舊的價值。爲了保證穩定性,在啓動定時器之前應設置信號動作,因爲程序的執行可能會延遲(例如,如果系統真的陷入停滯狀態),並且定時器可能會在到達代碼中設置的位置之前到期信號處理程序。

而且正如R提到的,printf()不是異步信號安全的,所以它不應該從你的信號處理程序中調用。

+0

非常感謝,您的幫助一直很珍貴 –