首页 > 代码库 > Linux编程定时执行某函数

Linux编程定时执行某函数



前言:

linux中信号提供了软中断的作用。提供了一种处理异步时间的方法 ,  可以通过信号合理的安排异步任务。

linux定义了以下主要的系统信号:

名称                        默认动作                        说明
 
SIGHUP                   终止进程                        终端线路挂断
SIGINT                   终止进程                        中断进程
SIGQUIT                 建立CORE文件                 终止进程,并且生成core文件
SIGILL                    建立CORE文件                非法指令
SIGTRAP                 建立CORE文件                 跟踪自陷
SIGBUS                  建立CORE文件                总线错误
SIGSEGV                建立CORE文件                段非法错误
SIGFPE                  建立CORE文件                浮点异常
SIGIOT                  建立CORE文件                 执行I/O自陷
SIGKILL                 终止进程                      杀死进程
SIGPIPE                终止进程                      向一个没有读进程的管道写数据
SIGALARM             终止进程                     计时器到时
SIGTERM              终止进程                       软件终止信号
SIGSTOP              停止进程                     非终端来的停止信号
SIGTSTP              停止进程                      终端来的停止信号
SIGCONT              忽略信号                    继续执行一个停止的进程
SIGURG                忽略信号                       I/O紧急信号
SIGIO                  忽略信号                       描述符上可以进行I/O
SIGCHLD              忽略信号                    当子进程停止或退出时通知父进程
SIGTTOU              停止进程                      后台进程写终端
SIGTTIN               停止进程                         后台进程读终端
SIGXGPU               终止进程                       CPU时限超时
SIGXFSZ              终止进程                        文件长度过长
SIGWINCH           忽略信号                     窗口大小发生变化
SIGPROF             终止进程                       统计分布图用计时器到时
SIGUSR1             终止进程                   用户定义信号1
SIGUSR2             终止进程                   用户定义信号2
SIGVTALRM        终止进程                     虚拟计时器到时

应用:

下面我们应用SIGALARM,设置每秒执行一次的动作:

    struct itimerval oneSec;

     signal(SIGALRM, Demo_updateTime);
        oneSec.it_value.tv_sec = 1;
        oneSec.it_value.tv_usec = 0;
        oneSec.it_interval.tv_sec = 1;
        oneSec.it_interval.tv_usec = 0;
        setitimer(ITIMER_REAL, &oneSec, NULL);

Demo_updateTime()函数就是注册的每秒执行一次的函数。

 switch(signo){
        case SIGALRM:
            time(&timeval) ;

            localtime_r(&timeval, &tmCur) ;

            //update date only once one day
            if(tmOld.tm_mday != tmCur.tm_mday)
            {
                char temp[40];

                //get day of week from this call only.
                ctime_r(&timeval, temp);

                sprintf(osdStr,"%04d-%02d-%02d ",tmCur.tm_year+1900,
                        tmCur.tm_mon+1,tmCur.tm_mday);

                strncat(osdStr,temp,3);

            }


实现精度较高的定时功能的话,就要使用setitimer函数。

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
which为定时器类型,setitimer支持3种类型的定时器:
ITIMER_REAL: 以系统真实的时间来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL: -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF: 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
setitimer()调用成功返回0,否则返回-1。
struct itimerval {

struct timeval it_interval;

struct timeval it_value;

};

struct timeval {

long tv_sec;

long tv_usec;

};
需要signal.h和sys/time.h
it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定 it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;两者都清零,则会清除定时器。
tv_sec提供秒级精度,tv_usec提供微秒级精度,以值大的为先,注意1s = 1000000us。
ovalue用来保存先前的值,常设为NULL。

      如果不需要这么高的精度,可用用alarm()函数:

ALARM介绍

alarm也称为闹钟函数alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替

所需头文件
  #include<unistd.h>


函数原型
  unsigned int alarm(unsigned int seconds)


函数参数
  seconds:指定秒数


函数返回值
  成功:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。
  出错:-1