我正在开发一个简单的软件,检查我是否能够使用我所研究的POSIX定时器和信号编程。
我正在尝试做一个简单的程序,启动一个计时器,并发出一定数量的纳秒信号
下面的程序不好用,所以我写了一些关于我的代码的评论,这样你就可以检查我是否正确学习了。
您可以在页面底部找到完整的代码列表。
各种各样的指纹,如

prinf("1\n")
are to check where the program exits prematurely.I putted
struct sigevent sigeventStruct
as structure for expirations events generated by the timer.First parameter is setted to SIGEV_SIGNAL so this is the kind of signal it will emit. ///The various memset you can read in code listing are to zero initialized structures.
if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)

is to create a POSIX timer. POSIX MONOTONIC CLOCK is the kind of timer, &sigeventStruct is the pointer to the structure that describes how it is the event generated by the timer expiration. &timer1 is the pointer to the name of the specific timer.

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

with this procedure, the timer is armed, so you can make it generate expirations.timer1 is the name of the timer, 0 is the flags. GAPIL book says: <>&tempoIniziale and &tempoFinale are pointers to itimerspec structs. I have not understood well what is the meaning of &old_timer. In GAPIL book you can read:<>

struct sigaction, oldSigAzione

sigaction structs that will be passed as parameter to sigaction POSIX signal handler

sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione)

SIGEV_SIGNAL is the kind of signals it has to handle, NULL Is where it could be placed a pointer to a const struct sigaction, &oldSigAzione is the pointer to the sigaction struct I mentioned before. Here again I have not understood the difference between these two pointers to sigaction struct.

My question is:why the program exits before printing the number 19 of printf("19\n"); and why does not excecutes the printf("Timer scaduto\n"); inside function void termination_handler(int signum) ?

Here my code:

#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;
}

最佳答案

在对timer_create()的调用中,第一个参数应该是clockid,如CLOCK_MONOTONIC_POSIX_MONOTONIC_CLOCK只是一个宏,可用于在编译时测试系统是否支持CLOCK_MONOTONIC
sigaction()的第一个参数应该是信号号,而不是SIGEV_SIGNAL。在您的例子中,您使用的是信号10,但这不是一个好的选择,因为通常这将是一个预定义的操作系统信号。通常您会使用用户定义的信号,如SIGUSR1或实时信号,如SIGRTMIN,因为这些是为应用程序定义的。另外,调用sigaction()不会设置信号处理程序,因为第二个参数为空。第二个参数应该是指向新信号操作的指针。相反,您使用的是第三个参数,该参数用于返回上一个信号操作。这允许您在保存旧信号操作的同时临时设置新信号操作,然后在完成新操作后,可以将其设置回保存的值。既然你再也不改变它了,你就不需要得到旧的价值。为了更健壮,应该在启动计时器之前设置信号操作,因为程序的执行可能会延迟(例如,如果系统真的陷入困境),计时器可能会在您到达设置信号处理程序的代码点之前过期。
正如R所提到的,printf()不是异步信号安全的,因此不应该从信号处理程序调用它。

关于c - POSIX计时器和POSIX信号处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9008330/

10-14 14:44
查看更多