2012-01-25 79 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

非常感谢,您的帮助一直很珍贵 –