一,三种时间结构

time_t://seconds

 

struct timeval {

long tv_sec; /* seconds */

long tv_usec; /* microseconds */

};

 

struct timespec {

time_t tv_sec; /* seconds */

long tv_nsec; /* nanoseconds */

};

二,setitimer()

现在的系统中很多程序不再使用alarm调用,而是使用setitimer调用来设置定时器,用getitimer来得到定时器的状态,

这两个调用的声明格式如下:

#include <sys/time.h>

int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);

参数:

  • 第一个参数which指定定时器类型
  • 第二个参数是结构itimerval的一个实例,结构itimerval形式
  • 第三个参数可不做处理。

返回值:成功返回0失败返回-1

该系统调用给进程提供了三个定时器,它们各自有其独有的计时域,当其中任何一个到达,就发送一个相应的信号给进程,并使得计时器重新开始。三个计时器由参数which指定,如下所示:

TIMER_REAL:按实际时间计时,计时到达将给进程发送SIGALRM信号。

ITIMER_VIRTUAL:仅当进程执行时才进行计时。计时到达将发送SIGVTALRM信号给进程。

ITIMER_PROF:当进程执行时和系统为该进程执行动作时都计时。与ITIMER_VIR-TUAL是一对,该定时器经常用来统计进程在用户态和内核态花费的时间。计时到达将发送SIGPROF信号给进程。

定时器中的参数value用来指明定时器的时间,其结构如下:

struct itimerval {

        struct timeval it_interval; /* 第一次之后每隔多长时间 */

        struct timeval it_value; /* 第一次调用要多长时间 */

};

该结构中timeval结构定义如下:

struct timeval {

        long tv_sec; /* 秒 */

        long tv_usec; /* 微秒,1秒 = 1000000 微秒*/

};

在setitimer 调用中,参数ovalue如果不为空,则其中保留的是上次调用设定的值。定时器将it_value递减到0时,产生一个信号,并将it_value的值设定为it_interval的值,然后重新开始计时,如此往复。当it_value设定为0时,计时器停止,或者当它计时到期,而it_interval 为0时停止。调用成功时,返回0;错误时,返回-1,并设置相应的错误代码errno:

EFAULT:参数value或ovalue是无效的指针。

EINVAL:参数which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一个。

示例一:

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0) void handler(int sig)
{
printf("recv a sig=%d\n", sig);
} int main(int argc, char *argv[])
{
if (signal(SIGALRM, handler) == SIG_ERR)
ERR_EXIT("signal error"); struct timeval tv_interval = {1, 0};
struct timeval tv_value = {5, 0};
struct itimerval it;
it.it_interval = tv_interval;
it.it_value = tv_value;
setitimer(ITIMER_REAL, &it, NULL); for (;;)
pause();
return 0;
}

结果:

可以看到第一次发送信号是在5s以后,之后每隔一秒发送一次信号

示例二:获得产生时钟信号的剩余时间

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0) int main(int argc, char *argv[])
{
struct timeval tv_interval = {1, 0};
struct timeval tv_value = {1, 0};
struct itimerval it;
it.it_interval = tv_interval;
it.it_value = tv_value;
setitimer(ITIMER_REAL, &it, NULL); int i;
for (i=0; i<10000; i++); //第一种方式获得剩余时间
struct itimerval oit;
setitimer(ITIMER_REAL, &it, &oit);//利用oit获得剩余时间产生时钟信号
printf("%d %d %d %d\n", (int)oit.it_interval.tv_sec, (int)oit.it_interval.tv_usec, (int)oit.it_value.tv_sec, (int)oit.it_value.tv_usec);
//第二种方式获得剩余时间
//getitimer(ITIMER_REAL, &it);
//printf("%d %d %d %d\n", (int)it.it_interval.tv_sec, (int)it.it_interval.tv_usec, (int)it.it_value.tv_sec, (int)it.it_value.tv_usec); return 0;
}

结果:

用第一种方式:

用第二种方式:利用getitimer在不重新设置时钟的情况下获取剩余时间

剩余时间是指:距离下一次调用定时器产生信号所需时间,这里由于for循环不到一秒就执行完,定时器还来不及产生时钟信号,所以有剩余时间

示例三:每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h> void sigroutine(int signo)
{
switch (signo) {
case SIGALRM:
printf("Catch a signal -- SIGALRM\n ");
break;
case SIGVTALRM:
printf("Catch a signal -- SIGVTALRM\n ");
break;
}
return;
} int main()
{ struct itimerval value,value2;
printf("process id is %d\n ",getpid()); signal(SIGALRM, sigroutine); signal(SIGVTALRM, sigroutine); value.it_value.tv_sec = 1; value.it_value.tv_usec = 0; value.it_interval.tv_sec = 1; value.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &value,NULL); value2.it_value.tv_sec = 0; value2.it_value.tv_usec = 500000; value2.it_interval.tv_sec = 0; value2.it_interval.tv_usec = 500000; setitimer(ITIMER_VIRTUAL, &value2,NULL); for (;;) ; }

结果:

可知确实是没两次SIGVTALRM一次SIGALRM

linux系统编程之信号(八):三种时间结构及定时器setitimer()详解的更多相关文章

  1. linux系统编程之信号(三):信号安装、signal、kill,arise讲解

    一,信号安装 如果进程要处理某一信号,那么就要在进程中安装该信号.安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号:该信号被传递给进程时,将执行何种操作. li ...

  2. linux系统编程之信号(七)

    今天继续学习信号,主要是学习关于时间和定时器相关的函数的使用,关于这个实际上有很多内容,这里先简要进行说明,等之后再慢慢进行相关深入,也主要是为接下来要做的一个综合linux系统编程的例子做准备,好了 ...

  3. linux系统编程之信号(一)

    今天起,开始新的知识的学习,对于上个系列进程的学习还差一个理论上的总结,这个会下次补回来,以便通过实践之后,再用理论将其巩固一下,好了,话不多说,开始进入这个主题的学习----信号,很重要,但不是太容 ...

  4. linux系统编程之信号(一):中断与信号

    一,什么是中断? 1.中断的基本概念 中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被 ...

  5. linux系统中,文件的三种特殊权限

    背景介绍 在linux系统中,我们熟知有rwx三种权限,对应所有者,同组用户,其他用户三种用户的权限,一共9个位来指定一个文件的权限情况,通过chmod xxx 来更改权限属性,其中xxx是已八进制表 ...

  6. linux系统root密码忘了怎么办 三种方法快速找回root密码

    linux root密码找回方法一 第1步:在系统进入单用户状态,直接用passwd root去更改. 第2步:用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法如下: ...

  7. linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)

        对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个阶段: 信号诞生 信号在进程中注册 信号在进程中的注销 信号处理函数执行 1    信号诞生     信号事件 ...

  8. linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程

    本节目标: 复制进程映像 fork系统调用 孤儿进程.僵尸进程 写时复制 一,进程复制(或产生)      使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文.进程堆栈. ...

  9. linux系统编程之信号(二)

    经过了漫长的间歇,对于c语言的学习也被中断了很久,现实确实有很多的无耐,计划中的事情总会被打乱,但不管怎样,学习的道路是不能休止的,所以经过了一断温习后现在继续学习C语言,话不多说,进入正题: 信号分 ...

随机推荐

  1. Linux下搭建gtk+2.0开发环境

    1.执行如下命令,检查系统是否已安装gtk+ pkg-config --list-all |grep gtk 若命令提示如下,则系统已安装gtk+,否则未安装. 2.若未安装,则执行如下命令进行安装 ...

  2. ubuntu16.04 LTS Server 安装mysql phpmyadmin apache2 php5.6环境

    1.安装apache sudo apt-get install apache2 为了测试apache2是否正常,访问http://localhost/或http://127.0.0.1/,出现It W ...

  3. 如何用Mockplus快速做一个手风琴菜单?

    手风琴菜单是一种比较常用的菜单形式,利用原型工具来做这种菜单通常要用到中继器.即使是功能强大的Axure,想实现该效果也比较麻烦.但如果你对Mockplus有所了解,你一定知道,利用Mockplus的 ...

  4. 编写JavaScript 代码的5个小技巧

    1.Array.includes 与条件判断 一般我们判断或用 || // condition function test(fruit) { if (fruit == "apple" ...

  5. tomcat 启动报 找不到 StrutsPrepareAndExecuteFilter。。

    <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://w ...

  6. 使用dos 作为中介实现cpython 和c# 交互

    最近在使用python 处理一些图形的东西. 实现:对一些512 的图进行像素遍历RGBA 变量, 查询通道不是 255 255 255 颜色 的矩阵,进行切图到空白 之前使用c#进行 确实快10 倍 ...

  7. 乞丐版servlet容器第4篇

    6. NIOConnector 现在为Server添加NIOConnector,添加之前可以发现我们的代码其实是有问题的.比如现在的代码是无法让服务器支持同时监听多个端口和IP的,如同时监听 127. ...

  8. shell的一些简单用法

    一 BASH的属性 BASH中会存储一些自身属性的参数,启用或关闭某一项功能 例如控制* .字符是否为通配 查看参数 set -o 关闭noglob参数 set -o noglob ls * ls: ...

  9. 2018.09.29 bzoj3156: 防御准备(斜率优化dp)

    传送门 斜率dp经典题目. 然而算斜率的时候并没有注意到下标的平方会爆int于是咕咕*2. 这道题我用了两个数组来表示状态. f[i]f[i]f[i]表示最后i个位置倒数第i个放木偶的最优值. g[i ...

  10. 2018.09.26洛谷P1084 疫情控制(二分+倍增)

    传送门 好题啊. 题目要求的最大值最小,看到这里自然想到要二分答案. 关键在于怎么检验. 显然对于每个点向根走比向叶节点更优. 因此我们二分答案之后,用倍增将每个点都向上跳到跳不动为止. 这时我们ch ...