linux下的时钟编程

linux下的时钟编程
2014-07-29 22:05:26
标签: linux  c  time
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://forlinux.blog.51cto.com/8001278/1532519


1.时钟相关的API函数原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <unistd.h>
unsigned  int  sleep(unsigned  int  seconds);
unsigned  int  alarm(unsigned  int  seconds);
int  usleep(useconds_t usec);
#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);
            struct  itimerval {
                struct  timeval it_interval;  /* next value */
                struct  timeval it_value;     /* current value */
            };
 
            struct  timeval {
                time_t       tv_sec;          /* seconds */
                suseconds_t tv_usec;         /* microseconds */
            };

2.sleep的实现

    sleep其实大家应该都不陌生,很多语言中都有相应的实现,其作用就是设置一个时延,等待时延,挂起进程。等待时间到达了就恢复进程的运行。在linux中sleep的是实现是使用alarm这个API函数来实现的。实现步骤如下:

一:为SIGALRM设置一个处理函数(SIGALRM是一个时钟信号,时间到了内核就会向进程发送SIGALRM信号)

二:.调用alarm(num_seconds);设置定时器

三:调用pause挂起进程。

这就是一个sleep函数的处理过程,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
 
void  wakeup( int );
void  do_thing();
int  main (  int  argc,  char  *argv[] )
{
         printf ( "about to sleep for seconds\n" );
         signal (SIGALRM,wakeup);
         alarm(4);
         pause();
         printf ( "Morning so son?\n" );
         return  EXIT_SUCCESS;
}
         /* ----------  end of function main  ---------- */
 
void  wakeup( int  signum)
{
 
                 printf ( "Alarm received from kernel\n" );
}

    alarm是一个linux下的计时器,它的第一个用途就是用来作为时延,另一个用途是调度一个在将来某个时刻发生的动作同时做些其他事情。

通过alarm设置计时器,然后继续做别的事情,当计时器到达0,信号发送,处理函数被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
 
void  do_thing();
int  main (  int  argc,  char  *argv[] )
{
         printf ( "about to sleep for seconds\n" );
         signal (SIGALRM,do_thing);
         alarm(4);
         while (1){
                 sleep(2);
                 printf ( "继续执行\n" );
         }
         return  EXIT_SUCCESS;
}
         /* ----------  end of function main  ---------- */
 
void  do_thing()
{
         printf ( "4秒后执行的\n" );
}

sleep,alarm都只能处理秒级的时延和计时器。在linux中提供了ulseep函数提供一个精度更高的时延


3.进程的三个计时器

每一个进程都有三个计时器,分别是:

ITIMER_REAL 用来真实时间的。如果手表记录一样。当这个计时器时间用尽就会发送SIGLRM消息

ITIMER_VIRTUAL 这个计时器只有在用户运行在用户态的时候才计时

ITIMER_PROF 这个计时器用于进程运行在用户态或由该进程调用而陷入核心态时计时。

三个计时器,难道计算机又三个时钟嘛?其实不然,计算机只有一个时钟。其工作方式是每个进程都有自己的计数器,cpu每隔一个时间片就遍历一下所有进程为每一个进程的计时器做递减。


4.间隔计时器编程

间隔计时器和普通的计时器不同,这个计时器有两个值,一个是初始时间间隔,另外一个是重复间隔设置。下面是一个间隔计时器的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<sys/time.h>
#include<signal.h>
#include<stdlib.h>
void  countdown( int );
int  set_ticker( int );
int  main (  int  argc,  char  *argv[] )
{
 
         //设置信号处理函数
         signal (SIGALRM,countdown);
         //设置计时器
         if (set_ticker(500) == -1)
                 perror ( "set_ticker:" );
         else
            //进程继续运行
                 while (1)
                 done_other_thing();
         return  EXIT_SUCCESS;
}
         /* ----------  end of function main  ---------- */
 
 
void  done_other_thing()
{
         sleep(1);
         printf ( "*****\n" );
}
 
 
void  countdown ( int  signum)
{
         static  int  num=10;
         printf ( "%d.." ,num--);
         fflush (stdout);
         if (num<0){
                 printf ( "DONE! \n" );
                 exit (0);
         }
}
         /* -----  end of function countdown  ----- */
int  set_ticker( int  n_msecs)
{
         struct  itimerval new_timeset;
         long  n_sec,n_usecs;
         n_sec = n_msecs / 1000;
         n_usecs = (n_msecs % 1000) *1000L;
         new_timeset.it_interval.tv_sec = n_sec;
         new_timeset.it_interval.tv_usec = n_usecs;
         new_timeset.it_value.tv_sec = n_sec;
         new_timeset.it_value.tv_usec = n_usecs;
         return  setitimer(ITIMER_REAL,&new_timeset,NULL);
}

    上面的运行过程如下:首先设置了信号处理函数countdown,然后设置了计时器,初始值是500毫秒也就是500毫秒后计时器时间到,重复间隔也是500。初始500毫秒到达后,又会重新设置计时器为500毫秒。设置好计时器后程序继续向下运行做其他时间了。500毫秒到了后就会出发countdown函数。这个函数会打印数字,并递减静态变量num的值,重复执行十次后num的值就小于0了。然后再次出发countdown的时候就退出整个程序了。

本文出自 “专注linux” 博客,请务必保留此出处http://forlinux.blog.51cto.com/8001278/1532519

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值