linux上点时间延时,Linux上时间和定时器

Linux下时间和定时器

http://blog.chinaunix.net/u1/35065/showart_1870601.html重点读了第三种方法。文章写得很好,加了一点点注释可参考http://linux.die.net/man/3/timer_settime

http://linux.die.net/man/2/setitimer

http://opengroup.org/onlinepubs/007908799/xsh/timer_settime.html

秒---毫秒---微秒---纳秒(数量级:1000)

一、问题的提出我们开发程序时,经常会遇到时间和定时器的问题,为了更好的使用时间和定时器,现在列举一个一些时间结构体、函数和定时器。

二、解决思路1.时间类型1) time_t是一个长整型,一般用来表示用1970年以来的秒数。

2)struct timeval有两个成员,一个是秒,一个是微妙。

struct timeval

{

long tv_sec;        /* seconds */

long tv_usec;   /* microseconds */

};

3) struct timespec有两个成员,一个是秒,一个是纳秒。

struct timespec

{

time_t tv_sec;          /* seconds */

long    tv_nsec;        /* nanoseconds */

};

4) struct tm是直观意义上的时间表示方法

struct tm

{

int     tm_sec;         /* seconds */

int     tm_min;         /* minutes */

int     tm_hour;        /* hours */

int     tm_mday;         /* day of the month */

int     tm_mon;         /* month */

int     tm_year;        /* year */

int     tm_wday;         /* day of the week */

int     tm_yday;        /* day in the year */

int     tm_isdst;        /* daylight saving time */

};

5)

struct timeb

{

time_t    time;            //从1970来经过的秒数unsigned short millitm; //毫秒short     timezone;        //时区short     dstflag;//为日光节约时间的修正值,如果为非0代表启用日光节约修正};

6)

struct timezone

{

int tz_minuteswest;//和格林尼治时间相差多少分int tz_dsttime;//日光节约时间的状态};

日光节约时间:夏时制。

2.时间函数1) char *asctime(const struct tm *timeptr)

将时间和日期以字符串格式显示。

2)clock_t clock(void)

取得进程占用cpu的大约时间。

3)char *ctime(const time_t *timep)

将时间和日期以字符串格式显示。

4) double difftime(time_t time1, time_t time0)

计算时间time1和time0间的差距。

5) int ftime(struct timeb *tp)

取得目前的时间和日期。

6) int gettimeofday(struct timeval *tv, struct timezone *tz)

取得目前的时间。

7)strcut tm *gmtime(const time_t *timep)

time_t结构时间转tm结构时间,tm为UTC时区。

8) struct tm *localtime(const time_t *timep)

将time_t结构时间转tm结构时间,tm是当地时区。

9)time_t mktime(struct tm *timeptr)

将tm结构时间转换为time_t。

10) int settimeofday(const struct timeval *tv, const struct timezone *tz)

设置时间为tv,设置时区为tz。

11) size_t strftime(char *s, size_t max, const char *format, const struct tm *tm)

将参数tm的时间结构依照参数format所指定的字符串格式做转换,转换后的字符串将复制到参数s所指的字符串数组中,该字符串的最大长度为参数max所控制。

12) time_t time(time_t *t)

取得目前的时间,时间按照UTC。

13) void tzset(void)

从环境变量TZ取得目前当地的时间。

3.延迟函数主要的延迟函数有:sleep(),usleep(),nanosleep(),select(),pselect().

1) unsigned int sleep(unsigned int seconds)

延时seconds秒。

2) void usleep(int micro_seconds)

延时micro_seconds微妙

3) int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)

延时的时间为rqtp,如果nansleep被信号中断,且rmtp不为NULL,则rmtp指定的位置上包含的就是剩余时间。

4) int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

如果将readfds, writefds, exceptfds置为NULL,timeout为非零,则延时timeout。

5) int pselect(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec tsptr, const sigset_t *sigmask)

如果将readfds, writefds, exceptfds置为NULL,tsptr为非零,则延时tsptr。

3.定时器1) unsigned int alarm(unsigned int seconds)

设置一个定时器,在seconds秒后超时,当定时器超时时,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程,如果设置了SIGALRM信号处理函数,则会执行该信号处理函数。

每个进程只能有一个闹钟时钟。如果在调用alarm时,以前已为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟时钟的余留值作为本次alarm函数调用的值返回,以前登记的闹钟时钟则被新值代替。

例子:

void sigalrm_fn(int sig)

{

printf("alarm!\n");

alarm(2);

return;

}

int main(void)

{

signal(SIGALRM, sigalrm_fn);

alarm(1);

while(1) pause();

}

2) POSIX:XSI间隔定时器

int getitimer(int which, struct itimerval *value);

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

struct itimerval

{

struct timeval it_interval; /*计时器重启动的间歇值*/

struct timeval it_value;    /*计时器安装后首先启动的初始值*/

};

getitimer()用计时器的当前值填写value指向的结构体。setitimer()将value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。

which:间歇计时器类型,有三种选择:

l         ITIMER_REAL //数值为0,计时器的值实时递减,发送的信号是SIGALRM。

l         ITIMER_VIRTUAL //数值为1,进程执行时递减计时器的值(虚拟时间),发送的信号是SIGVTALRM。

l         ITIMER_PROF //数值为2,虚拟时间和进程的系统时间递减,发送的信号是SIGPROF。

itimerval结构中的it_value是减少的时间,当这个值为0的时候就发出相应的信号了.然后再将it_value设置为it_interval值.也就是先处理it_value中设置的值,为0后发送信号(根据which来判断发送什么信号),之后都是根据it_interval的值发送信号。若it_value和it_interval都为0,也就没有相应的信号产生了。

和alarm()一样,由于信号的限制,POSIX:XSI间隔定时器对于每个进程来说最多只有3个定时器。

例子:

void sigroutine(int signo)

{

switch (signo)

{

case SIGALRM:

printf("Catch a signal -- SIGALRM \n");

signal(SIGALRM, sigroutine);

break;

case SIGVTALRM:

printf("Catch a signal -- SIGVTALRM \n");

signal(SIGVTALRM, sigroutine);

break;

}

return;

}

int main()

{

struct itimerval value, ovalue, value2;

sec = 5;

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, &ovalue);

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, &ovalue);

for(;;)

;

}

3)POSIX:TMR间隔定时器

int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)

进程可以通过调用timer_create()创建特定的定时器,定时器是每个进程自己的,不是在fork时继承的。timer_create的参数clock_id说明定时器是基于哪个时钟的,*timerid装载的是被创建的定时器的ID。timer_create函数创建了定时器,并将他的ID放入timerid指向的位置中。参数evp指定了定时器到期要产生的异步通知。如果evp为NULL,那么定时器到期会产生默认的信号,对CLOCK_REALTIMER来说,默认信号就是SIGALRM。对那些定时器到期时要产生除默认信号之外的其它信号的定时器来说,程序必须将evp->sigev_signo设置为期望的信号码。struct sigevent结构中的成员evp->sigev_notify说明了定时器到期时应该采取的行动。通常,这个成员的值为SIGEV_SIGNAL,这个值说明在定时器到期时,会产生一个信号。程序可以将成员evp->sigev_notify设为SIGEV_NONE来防止定时器到期时产生信号。

如果几个定时器产生了同一个信号,处理程序可以用evp->sigev_value来区分是哪个定时器产生了信号。要实现这种功能,程序必须在为信号安装处理程序时,使用struct sigaction的成员sa_flags中的标志符SA_SIGINFO。

clock_id的取值为以下:

CLOCK_REALTIME :Systemwide realtime clock.

CLOCK_MONOTONIC:Represents monotonic time. Cannot be set.

CLOCK_PROCESS_CPUTIME_ID :High resolution per-process timer.

CLOCK_THREAD_CPUTIME_ID :Thread-specific timer.

CLOCK_REALTIME_HR :High resolution version of CLOCK_REALTIME.

CLOCK_MONOTONIC_HR :High resolution version of CLOCK_MONOTONIC.

struct sigevent

{

int sigev_notify; //notification type

int sigev_signo; //signal number

union sigval   sigev_value; //signal value

void (*sigev_notify_function)(union sigval);

pthread_attr_t *sigev_notify_attributes;

}

union sigval

{

int sival_int; //integer value

void *sival_ptr; //pointer value

}

通过将evp->sigev_notify设定为如下值来定制定时器到期后的行为:

l         SIGEV_SIGNAL:发送由evp->sigev_sino指定的信号到调用进程,evp->sigev_value的值将被作为siginfo_t结构体中si_value的值。

l         SIGEV_NONE:什么都不做,只提供通过timer_gettime和timer_getoverrun查询超时信息。

l         SIGEV_THREAD:以evp->sigev_notification_attributes为线程属性创建一个线程,在新建的线程内部以evp->sigev_value为参数调用evp->sigev_notification_function。

int timer_delete(timer_t timerid);

删除ID为timerid的POSIX:TMR定时器。

int timer_settime(timer_t timerid,int flags,const struct itimerspec *value,struct itimerspec *ovalue);

struct     itimerspec{struct     timespec   it_interval; //定时器周期值struct     timespec   it_value;     //定时器到期值};

timer_settime负责启动或停止timer_create创建的定时器。参数flag说明定时器使用的是相对时间还是绝对时间。相对时间与POSIX:XSI定时器使用的策略类似,而绝对时间的精确度更高。参数vaule指向的值来设置timerid指定的定时器。如果ovalue不为NULL,timer_settime就将定时器以前的值放在ovalue指定的位置上。如果定时器正在运行,那么*ovalue的成员it_value非零,并包含了定时器到期之前剩余的时间。

TIMER_ABSTIME表示绝对时间;如果flag没有设定为TIMER_ABSTIME,则定时器从调用开始在it_value内超时;即value->it_value代表计时器第一次超时的时间。如果设定为TIMER_ABSTIME,该函数表现为时间直到下一次超时被设定为it_value指定的绝对时间和与timerid相联的时钟值的差值。如果已经到了it_value指定的值,那么超时后的处理就会立即执行。定时器的再装由value的it_interval成员值来设定。

int timer_gettime(timer_t timerid,struct itimerspec *value);

获得一个活动定时器的剩余时间。

int timer_getoverrun(timer_t timerid);

有可能一个定时器到期了,而同一定时器上一次到期时产生的信号还处于挂起状态。在这种情况下,其中的一个信号可能会丢失。这就是定时器超限。程序可以通过调用timer_getoverrun来确定一个特定的定时器出现这种超限的次数。定时器超限只能发生在同一个定时器产生的信号上。由多个定时器,甚至是那些使用相同的时钟和信号的定时器,所产生的信号都会排队而不会丢失。

例子:

编译方法:

gcc -o example example.c   -lrt   -lpthread

那个rt库就是POSIX   realtime   extension的库。

#include  

#include  

#include   #include   //不然会出现对memset函数的警告

void

handle   (union sigval   v)

{

time_t   t;

char   p[32];

time   (&t);

strftimep,   sizeof   (p),   "%T",   localtime   (&t));

printf("%s   thread   %lu,   val   =   %d,   signal   captured.\n",   p,   pthread_self(), v.sival_int);

return;

}

int create   (int   seconds,   int   id)

{

timer_t   tid;

struct   sigevent   se;

struct   itimerspec   ts,   ots;

memset   (&se,   0,   sizeof   (se));

se.sigev_notify   =   SIGEV_THREAD;

se.sigev_notify_function   =   handle;

se.sigev_value.sival_int   =   id;   //作为handle()的参数

if   (timer_create   (CLOCK_REALTIME,   &se,   &tid)  

{

perror   ("timer_creat");

return   -1;

}

puts   ("timer_create   successfully.");

ts.it_value.tv_sec   =   3;

ts.it_value.tv_nsec   =   0;

ts.it_interval.tv_sec   =   seconds;

ts.it_interval.tv_nsec   =   0;

if   (timer_settime (tid,   TIMER_ABSTIME,   &ts,   &ots)  

{

perror   ("timer_settime");

return   -1;

}

return   0;

}

int   main   (void)

{

create   (3,   1);

create   (5,   2);

for   (;;)

{

sleep   (10);

}

}

三、总结Linux下定时器主要使用上面介绍的三种定时器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

04_SSM整合ActiveMQ支持多种类型消息

接上一篇:企业实战03_SSM整合ActiveMQ支持多种类型消息https://blog.csdn.net/weixin_40816738/article/details/100572104 1、StreamMessage java原始值数据流 2、MapMessage 键值对 3、TextMessage 字符串 4、ObjectMessage 一个序列化的java对象 5、BytesMessage…

​听说,私有云也出新一代了?

戳蓝字“CSDN云计算”关注我们哦!作者 | 孙浩峰自从私有云的概念出现以来,由于其能够较好的解决传统IT 架构、IT 流程的诸如缺乏弹性、IT 架构难以支撑多变的业务环境,交付流程效率低难以及时响应业务需求等诸多问题,获得了蓬勃发…

linux硬盘保护卡,保护卡下安装Linux

保护卡下安装Linux发布时间:2008-03-14 00:29:17来源:红联作者:roina实验室的机房需要安装Linux,所以不得不请技术人员来把原来的保护卡卸载,重新规划硬盘分区,设置保护策略,再重新安装系统。可是就是在安装Linux的时候发生了问题…

实战05_SSM整合ActiveMQ支持多种类型消息

接上一篇:实战04_SSM整合ActiveMQ支持多种类型消息https://blog.csdn.net/weixin_40816738/article/details/100572124 1、StreamMessage java原始值数据流 2、MapMessage 键值对 3、TextMessage 字符串 4、ObjectMessage 一个序列化的java对象 5、BytesMessage 一个…

腾讯云一口气发布四大新品,云原生时代将正式开启

6月25日,在上海召开的KubeCon 2019大会上,腾讯云重磅发布多款适用于企业不同场景的云原生技术产品,包括企业级容器服务平台TKE、容器服务网格、Serverless 2.0、一站式DevOps四大产品。这四款云原生技术产品的发布将助力国内数百万企业“上云…

实战06_SSM整合ActiveMQ支持多种类型消息

接上一篇:企业实战05_SSM整合ActiveMQ支持多种类型消息https://blog.csdn.net/weixin_40816738/article/details/100572129 1、StreamMessage java原始值数据流 2、MapMessage 键值对 3、TextMessage 字符串 4、ObjectMessage 一个序列化的java对象 5、BytesMessage…

linux下远程登录如何退出,Ubuntu 中rdesktop如何切换和退出远程桌面

Ubuntu 中rdesktop如何切换和退出远程桌面原文如下:I use RDP a lot and having to disconnect from my session to switch to another window is not an option. The problem lies somewhere with compiz. What supposed to happen when you hit ctrlaltenter is …

K8S精华问答 | K8S和Openstack发展方向是怎样的?

kubernetes,简称K8S,是用8代替8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应…

实战07_SSM整合ActiveMQ支持多种类型消息

接上一篇:企业实战06_SSM整合ActiveMQ支持多种类型消息https://blog.csdn.net/weixin_40816738/article/details/100572147 1、StreamMessage java原始值数据流 2、MapMessage 键值对 3、TextMessage 字符串 4、ObjectMessage 一个序列化的java对象 5、BytesMessage…

Linux进程核心代码怎么查看,GCOV查看arm-linux代码覆盖率

一、关于gcov工具gcov伴随gcc发布。gcc编译加入-fprofile-arcs -ftest-coverage参数生成二进制程序,执行测试用例生成代码覆盖率信息。1、如何使用gcov用GCC编译的时候加上-fprofile-arcs -ftest-coverage选项,链接的时候也加上。fprofile-arcs参数使gcc…

对于华为,英特尔与微软表示继续提供支持;亚马逊亲证云计算服务出现宕机;中国移动5G套餐曝光,每月都含200G流量……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 小米CC全新系列小王子&小…

Linux 环境 zookeeper集群安装、配置、验证

架构说明: Dubbo 建议使用 Zookeeper 作为服务的注册中心。Zookeeper 集群中只要有过半的节点是正常的情况下,那么整个集群对外就是可用的。正是基于这个特性, 要将 ZK 集群的节点数量要为奇数(2n1: 如 3、 5、 7 个节…

怎么时装linux可用空间变大,[合集]OpenSUSE安装octave时装1G多texliv - 精华区 - 优秀的Free OS(Linux)版 - 北大未名BBS...

发信人: mytbk (LCPU AP|ArchLinux), 信区: Linux标 题: [合集]OpenSUSE安装octave时装1G多texlive发信站: 北大未名站 (2014年01月10日13:17:19 星期五), 站内信件───────────────────────────────────────作者PsySunrise (无良之心)…

基于zookeeper(集群)+LevelDB的ActiveMq高可用集群安装、配置、测试

参考 腾讯云~基于zookeeper(集群)LevelDB的ActiveMq高可用伪集群安装、配置、测试 https://gblfy.blog.csdn.net/article/details/127465602

5G 来了,我们可以做什么?

5G 清风徐来,静待应用花开。这是最好的时代,也是最具挑战的时代。当下就国内而言,随着四张 5G 商用牌照的正式发放,运营商们纷纷扩大并加快了建网的规模与速度;手机厂商们也早已于今年年初相继推出了 5G 手机&#xff…

linux内核之内存管理.doc,linux内核之内存管理.doc

linux内核之内存管理Linux内核之内存管理作者:harvey wang邮箱:harvey.perfect新浪博客地址:/harveyperfect ,有关于减肥和学习英语相关的博文,欢迎交流把linux内存管理分为下面四个层面(一)硬件辅助的虚实地址转换(二…

SpringBoot项目去除druid监控的底部广告

文章目录一、阿里Druid广告的介绍二、引入Druid的Starter依赖三、编写配置类,进行广告的去除四 、启动项目进行测试五、原理说明一、阿里Druid广告的介绍 如果使用的是阿里Druid的数据库连接池,那么会自带一个数据库的监控页面. 但是其页面底部会有阿里的广告,如下图所示,并且…

精简linux操作系统,Tiny Core Linux—仅10多MB的精简Linux 操作系统发行版

Tiny Core Linux是一款很简约的桌面Linux,体积小且可高度可扩展,基于Linux 3.x内核、Busybox、Tiny X、FLTK图形用户界面、JWM窗口管理器。像其他操作系统最少也要几百MB了,Tiny Core Linux不仅体积小,对硬件配置要求也很高&#…

面试官问你MyBatis中有哪些设计模式,把这篇文章发给他

戳蓝字“CSDN云计算”关注我们哦!作者 | 疯狂的蚂蚁来源 | https://dwz.cn/KFgol1De之前总结过一篇Spring中用到了哪些设计模式:《面试官:“谈谈Spring中都用到了那些设计模式?”》,昨晚看到了一篇很不错的一篇介绍MyBatis中都用到了那些设计…

Linux 启动mysql提示表不存在

编辑my.cnf 设置大小写敏感配置在 vim /etc/my.cnf #添加lower_case_table_names1,忽略大小写 #重启MYSQL服务 service mysql restart,