Ger*_*llo 1 c posix signals timer
我正在开发一个简单的软件来检查我是否能够使用我研究的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是它必须处理的信号类型,NULL是可以放置指向const结构sigaction的指针,而oldSigAzione是指向前面提到的sigaction结构的指针.在这里,我还没有理解这两个指向sigaction struct的指针之间的区别.
我的问题是: 为什么程序在打印printf的数字19之前退出("19 \n"); 为什么不考虑printf("Timer scaduto \n"); inside函数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;
}
Run Code Online (Sandbox Code Playgroud)
在调用中timer_create(),第一个参数应该是一个clockid,如CLOCK_MONOTONIC. _POSIX_MONOTONIC_CLOCK只是一个宏,您可以使用它来在编译时测试系统是否支持CLOCK_MONOTONIC.
第一个参数sigaction()应该是信号编号,而不是SIGEV_SIGNAL.在您的情况下,您使用信号10,但这不是一个好的选择,因为通常这将是预定义的OS信号之一.通常您会使用用户定义的信号SIGUSR1或类似的实时信号SIGRTMIN,因为这些信号被定义为供应用程序使用.你的调用sigaction()也没有设置信号处理程序,因为第二个参数是NULL.第二个参数应该是指向新信号操作的指针.而是使用第三个参数,用于返回先前的信号操作.这允许您临时设置新的信号操作,同时保存旧的信号操作,然后当您完成新操作后,您可以将其设置回保存的值.由于您再也不会更改它,因此您无需获取旧值.同样要强健,应该在启动定时器之前设置信号动作,因为程序的执行可能会延迟(例如,如果系统真的陷入困境),并且计时器可能会在您到达代码中的点之前到期信号处理程序.
正如R所提到的那样,printf()不是异步信号安全的,因此不应该从信号处理程序中调用它.
| 归档时间: |
|
| 查看次数: |
7264 次 |
| 最近记录: |