linux下定时器的使用及信号操作



数据结构
  • 定时器结构:
struct itimerval
{
	struct timerval it_value;//Interval for periodic timer,从设置定时器开始到第一次定时器生效的时间
	struct timerval it_interval;//Time until next expiration,定时器生效的时间间隔
}

① 若it_value=0,系统将无视it_interval并终止定时器,因此可利用这一特性disable定时器
② 若it_interval=0,则定时器执行一次后失效

在这里插入图片描述

  • 时间存储结构:
    struct timeval
    {
    	time_t tv_sec;//秒
    	suseconds_t tv_usec;//微秒(microseconds)
    }
    

定时器类型
  • ITIMER_REAL:0,自然定时,计算自然时间,实时衰减;当此计时器到期时,将发送SIGALRM信号。

  • ITIMER_VIRTUAL:1,虚拟空间计时(用户空间),只计算进程占用cpu的时间,进程虚拟时间中的衰减;它只在进程执行时运行;SIGVTALRM信号在到期时发送。

  • ITIMER_PROF,2,运行时计时(用户+内核),计算占用cpu及执行系统调用的时间,进程虚拟时间和系统代表进程运行时的衰减;它被设计用于解释程序执行的统计分析;每次ITIMER_PROF计时器到期时,都会传递SIGPROF信号。

方法
  • 获取系统时间(毫秒级)

    注意,获得的数据从1970.01.01开始算起的

    int gettimeofday(struct timeval *,void *);
    

    如果第二个参数不为NULL,结果不可预料

  • 设置定时器

    //参数1:定时器类型
    //参数2:指定的定时器
    //参数3:调用setitimer之前的旧定时器
    int setitimer(int,const struct itimerval *,struct itimerval *);
    // 成功返回0
    //是把你返回-1
    
  • 获取定时器

    int getitimer(int,struct itimerval*);
    
    //example:
    getitimer(ITIMER_REAL,&value);
    
测试代码
#include<iostream>
#include<sys/time.h>
#include<signal.h>

using namespace std;

void testFun(int a)
{
	cout<<"Hello,Linux timer~"<<endl;
}

int main()
{

    struct timeval curtime;
    gettimeofday(&curtime,NULL);
    cout<<"curtime.tv_sec:"<<curtime.tv_sec<<endl;
    cout<<"curtime.tv_usec:"<<curtime.tv_usec<<endl;
    

	struct itimerval timer;
	
	//周期定时器间隔
	timer.it_interval.tv_sec 	= 0;
	timer.it_interval.tv_usec 	=1000*500;//0.5s=500ms=500*1000us
	//从设置定时器开始到第一次定时器生效的时间
	timer.it_value.tv_sec 		=1;//1秒
	timer.it_value.tv_usec 		=0;

	setitimer(ITIMER_REAL, &timer, NULL);
	signal(SIGALRM, testFun); 	
	
	while(1);
	return 0;
}

编译:

g++ timer_test.cpp -o timer_test

在这里插入图片描述

注意:tv_usec的值必须小于1000*1000,当等于1000*1000微秒时,应设置tv_sec=1,否则程序将出现未响应的状态~



sigaction函数

头文件:#include <signal.h>

功能:检查或修改与指定信号相关联的处理动作(可同时两种动作)

//signum:指定要捕获的信号类型
//act:指定新的信号处理方式
//oldact:输出先前信号的处理方式,通常为NULL
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

数据结构:

//sa_handler:函数指针,和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()

//sa_sigaction:是另一个信号处理函数,有三个参数,可获得关于信号的更详细的信息;当 sa_flags 成员的值包含了 SA_SIGINFO 标志时,系统将使用 sa_sigaction 函数作为信号处理函数,否则使用 sa_handler 作为信号处理

//sa_mask:用来指定在信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会被自动放入进程的信号掩码,因此在信号处理函数执行期间这个信号不会再度发生。

//sa_flags:用来设置信号处理的其他相关操作
//			SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
//			SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用(使被信号打断的系统调用自动重新发起)
//			SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号(使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号)
//			SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
//			SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
//			SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。


//sa_restorer:此参数未使用,据说已废弃

 struct sigaction
 {
	  void     (*sa_handler)(int);
	  void     (*sa_sigaction)(int, siginfo_t *, void *);
	  sigset_t  sa_mask;
	  int       sa_flags;
	  void     (*sa_restorer)(void);
 };

测试代码:
        具体看这篇博文→https://www.cnblogs.com/Jacket-K/p/8364874.html

其他结论
  1. 默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的
  2. 对信号的处理是进程中所有的线程共享的














参考文献:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章