Linux time system

来源:互联网 发布:非编软件是什么意思 编辑:程序博客网 时间:2024/06/06 12:35

Linux time system

Linux中跟时间有关的函数变量有很多,但是对开发者来说无非就是用了计时/延时/挂起/获取时间等,下面列出自己所使用过的一些时间接口,供大家理解使用。

jiffies

在内核代码中,到处充斥着jiffies变量,jiffies在include/linux/jiffies.h中定义,在linux启动的时候会将jiffies清0,当系统完成对时钟中断的初始化后,在每个时钟滴答时jiffies都会被加1,所以在驱动程序开发过程中,使用jiffies变量就已足够所有基于jieffies的时间度量任务。

jiffies的使用通常要配合着宏HZ,宏HZ的定义位于.confg,一般都将其设置为1000,1秒1000次即1ms。
例:

time1 = jiffies + 2 * HZ;则time1表示未来的2秒;time2 = jiffies + 3 * HZ/1000;则time2表示未来的3毫秒;

在jiffies.h还为我们提供了很多接口函数,主要有两类,一类为时间的比较,一类为时间的转化。 下面进行简单说明举例:
1、时间的比较

time_after(a,b);        //如果时间点a在时间点b之后,则返回1time_before(a,b);       //如果时间点a在时间点b之前,则返回1time_after_eq(a,b);     //如果时间点a在时间点b之后或等于b,则返回1time_before_eq(a,b);    //如果时间点a在时间点b之前或等于b,则返回1time_in_range(a,b,c);   //如果时间点a在时间点b和c之间或等于b或c,则返回1

例:

int time_test(){    unsigned long timeout = jiffies + 2 * HZ/1000;  //2ms    do_time_task();    if(time_after(jiffies,timeout))    //如果do_time_task()函数执行超过2ms,则成立        return 1;    return 0;}

2.时间转化
为了方便理解,我们需要将jiffies转化成比较直观的毫秒ms或者是微妙us等形式,jiffies.h里面一个了一些比较直观的转化函数,其实现函数在kernel/time.c里面 如:

unsigned int jiffies_to_msecs(const unsigned long j);unsigned int jiffies_to_usecs(const unsigned long j);unsigned long msecs_to_jiffie(const unsigned int m);unsigned long usecs_to_jiffie(const unsigned int u);

do_gettimeofday

当我们需要得到某一段代码所执行的时间是多少,可以使用do_gettimeofday函数,该函数定义在kernel/time/timekeeping.c中,申明在include/linux/time.h中,do_gettimeofday函数是在内核的函数,如果在应用层实现该这个函数则使用gettimeofday,包含sys/time.h即可,使用方法与do_gettimeofday一样。

举个简单的例子:

int gettimeofday_test(){    struct timeval tv_start;    struct timeval tv_end;    float timeuse;    gettimeofday(&tv_start, NULL);    do_gettimeofday_task();    gettimeofday(&tv_end, NULL);    timeuse = 1000000*(tv_end.tv_sec - tv_start.tv_sec) + tv_end.tv_usec - tv_start.tv_usec;    timeuse /= 1000;    printf("Time-consuming: %f ms\n",  timeuse);    return 0;}

delay

delay函数为死等待,这种函数只能用在短延时上,如微妙甚至纳秒等级的 Linux内核提供了如下短延时接口函数,位于include/linux/delay.h中

void mdelay(usigned long msecs); void udelay(usigned long usecs); void ndelay(usigned long nsecs);

sleep

上面的短延时为忙等待,当为长延时不能为忙等待,需要将任务挂起,这是我们可以使用sleep函数 在kernel/timer.c里面有实现了msleep()函数,也在include/linux/delay.h中申明,其原型如下,

sleep也是我们在写shell脚本时比较经常使用的延时、循环执行命令,直接调用即可使用。

内核定时器timer

如果希望在内核中以一定的时间间隔来执行执行某项任务,如:每隔一秒查询一次button的状态,可以使用内核定时器来实现。内核中已经为我们提供了定时器数据结构timer_list,和定时器的接口函数,位于include/linux/timer.h中。

定时器timer的实现步骤就两步:

  • 初始化定时器,设置定时器的触发时间,指定该定时器的回调函数。
  • 实现定时器回调函数,如果需要循环执行,则需要在该定时器的回调函数中重新启动该定时器。

举个简单的例子:

#define TIMER_FUNC(_fn)  void _fn(unsigned long timer_arg)#define TIMER_INIT(_osdev, _timer, _fn, _arg)        \do {                                                 \        init_timer(_timer);                          \        (_timer)->function = (_fn);                  \        (_timer)->data = (unsigned long)(_arg);      \} while (0)#define TIMER_SET(_timer, _ms)  mod_timer(_timer, jiffies + ((_ms)*HZ)/1000)struct timer_list os_timer_test; static TIMER_FUNC(timer_test_func){    TIMER_SET(&os_timer_test, 1000);   //重新设置该定时器}int timer_test(){    TIMER_INIT(NULL, &os_timer_test, timer_test_func, &os_timer_test);    //初始化定时器,绑定回调函数    TIMER_SET(&os_timer_test, 1000);   //1s    return 0;}

系统时间date

date主要用来显示和设定系统的日期与时间,通常会在shell中使用到data命令

1.data的显示

最直接的方式即输入date,如下:

# date Thu Dec 15 14:28:19 GMT 2016

这种方式会将信息以一定的格式显示出来,星期、月份、日期、时:分:秒、时区、年份
如果我们需要得到更具体的信息可以通过”data +%$”来获取,如:

# date +%H    //小时14# date +%m    //月份12# date +%y    //年份16

具体指令如下:

命令 含义 %H 小时(00..23) %I 小时(01..12) %k 小时(0..23) %l 小时(1..12) %M 分钟(00..59) %p 显示本地 AM 或 PM %r 直接显示时间 (12 小时制,格式为 h : m : s [AP]M) %s 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数 %S 秒(00..61) %T 直接显示时间 (24 小时制) %X 相当于 %H:%M:%S %Z 显示时区 %a 星期几 (Sun..Sat) %A 星期几 (Sunday..Saturday) %b 月份 (Jan..Dec) %B 月份 (January..December) %c 直接显示日期与时间 %d 日 (01..31) %D 直接显示日期 (mm/dd/yy) %h 同 %b %j 一年中的第几天 (001..366) %m 月份 (01..12) %U 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形) %w 一周中的第几天 (0..6) %W 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形) %x 直接显示日期 (mm/dd/yy) %y 年份的最后两位数字 (00.99) %Y 完整年份 (0000..9999)

2.data的设置
既然读取到了时钟发现错误时就需要修改,修改的方式有很多,这边就不想弄的那么复杂,用一个最直观简单的格式,如下:

# date -s "2016-12-15 14:43:33"Thu Dec 15 14:43:33 GMT 2016

RTC时钟hwclock

linux系统时钟有两个,一个是硬件时钟,一般就是RTC时钟,另一个是系统时钟,即上面使用date时得到的信息,它是linux系统Kernel时间。当Linux启动时,系统Kernel会去读取硬件时钟的设置,然后系统时钟就会独立于硬件运作。

硬件时钟可以通过hwclock来获取,如下:

# hwclock Thu Dec 15 11:12:07 2016  0.000000 seconds

当我们修改了系统时钟后,想将系统时间同步到硬件时钟可以通过hwclock -w命令实现,如下:

# date -s "2016-12-15 15:40:00"Thu Dec 15 15:40:00 GMT 2016# hwclock Thu Dec 15 11:24:25 2016  0.000000 seconds# hwclock -w# hwclock Thu Dec 15 15:40:23 2016  0.000000 seconds

busybox里面也实现从硬件时钟同步到系统时钟的命令hwclock -s,但这个指令一般很少用,因为kernel一启动系统时钟就是读取硬件的时钟,所以两则已经相等了,我们发现系统时钟不对时,则会去修改系统时钟再同步到硬件时钟。

注:以上内容都是本人在学习过程积累的一些心得,难免会有参考到其他文章的一些知识,如有侵权,请及时通知我,我将及时删除或标注内容出处。文章只是起一个引导作用,详细的数据解析内容还请查看Linux相关教程,感谢您的查阅。

0 0
原创粉丝点击