我正在开发一个简单的软件,检查我是否能够使用我所研究的POSIX定时器和信号编程。
我正在尝试做一个简单的程序,启动一个计时器,并发出一定数量的纳秒信号
下面的程序不好用,所以我写了一些关于我的代码的评论,这样你就可以检查我是否正确学习了。
您可以在页面底部找到完整的代码列表。
各种各样的指纹,如
prinf("1\n")are to check where the program exits prematurely.I putted
struct sigevent sigeventStructas 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/