Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1728768
  • 博文数量: 98
  • 博客积分: 667
  • 博客等级: 上士
  • 技术积分: 1631
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-27 15:59
个人简介

一沙一世界 一树一菩提

文章分类

全部博文(98)

文章存档

2021年(8)

2020年(16)

2019年(8)

2017年(1)

2016年(11)

2015年(17)

2014年(9)

2013年(4)

2012年(19)

2011年(1)

2009年(4)

分类: LINUX

2012-08-10 15:07:17

在调试系统时间的过程当中,共计有2篇文章,感觉挺好。这个文章对于我而言,看点在date和hwclock的调用过程。可以明白系统时间,硬件时间和localtime的关系上。尽管我用的是uclibc,没有localtime,用的是TZ,但是个人感觉还是很有参考价值的。所以ctrl+c,ctrl+v。《Linux的硬件时间及系统时间》


一)概述:


事实上在Linux中有两个时钟系统,分别是系统时间和硬件时间
UTC是协调世界时(Universal Time Coordinated)英文缩写,它比北京时间早8个小时.


二)date
date可以打印/设定系统时间.
打印系统时间时,date命令会通过调用clock_gettime函数获取时间,同时会通过localtime文件(时区文件)计算出本地的时间.
设定系统时间时,date命令会通过读取localtime文件(时区文件)确定本地的时区,再调用clock_settime函数计算出本地的时间.


三)hwclock
hwclock可以打印/设定硬件时钟.

通过strace我们可以跟踪hwclock执行时打开的文件,如下:
strace -e trace=open hwclock -r 
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/libaudit.so.1", O_RDONLY)    = 3
open("/lib/libc.so.6", O_RDONLY)        = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 4
open("/dev/rtc", O_RDONLY|O_LARGEFILE)  = 4
open("/etc/adjtime", O_RDONLY|O_LARGEFILE) = 5
open("/usr/share/zoneinfo/Universal", O_RDONLY) = 5
open("/etc/localtime", O_RDONLY)        = 5
open("/usr/share/locale/locale.alias", O_RDONLY) = 5
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/util-linux-ng.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
Mon 17 Oct 2011 02:29:49 AM CST  -0.567399 seconds

注:
1)hwclock首先打开了/dev/rtc,读取硬件时钟.
2)打开/etc/adjtime文件,通过先前的记录来估算硬件时钟的偏差,并用来校正目前的时间.
3)打开/etc/localtime时区文件,将硬件时间转换为当前时区对映的时间.

下面介绍hwclock常用的几个参数:
-s(--hctosys)从硬件时钟读取时间更新到系统时钟.
-w(--systohc)将系统时钟时间写入硬件时钟.
--debug显示hwclock执行时详细的信息,例如:
hwclock -r --debug
hwclock from util-linux-ng 2.17.2
Using /dev interface to clock.
Last drift adjustment done at 1318866683 seconds after 1969
Last calibration done at 1318866683 seconds after 1969
Hardware clock is on UTC time
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
...got clock tick
Time read from Hardware Clock: 2011/10/17 15:51:32
Hw clock time : 2011/10/17 15:51:32 = 1318866692 seconds since 1969
Mon 17 Oct 2011 11:51:32 PM CST  -0.117361 seconds

--set --date=<日期与时间>设定硬件时钟,如下:
读取硬件时间,现在是11:54(PM)
hwclock -r
Mon 17 Oct 2011 11:54:47 PM CST  -0.003885 seconds

设定硬件时间为12:54(PM)
hwclock --set --date=12:54

再次读取硬件时间,发现时间已经变为12:54(PM)
hwclock -r
Mon 17 Oct 2011 12:54:03 PM CST  -0.027942 seconds

注:
最后要说明的是hwclock输出的是带有AM/PM表示方式的硬件时间.
我们可以通过hwclock --localtime将硬件时间转换为utc时间.
如下:
hwclock --localtime
Mon 17 Oct 2011 05:00:49 PM CST  -0.478863 seconds

hwclock 
Tue 18 Oct 2011 01:00:52 AM CST  -0.821415 seconds



四)AM与PM
AM是上午,PM是下午,例如:
01:30:56 AM表示24小时制的凌晨01:30:56
01:30:56 PM表示24小时制的下午13:30:56

我们可以用date命令在获取系统时间时,是AM还是PM,如下:
date +%r
01:34:17 AM



五)时区与时间
只有设定了正确时区的前提下,才能正确的得出本地的时间.
例如:
如果我们在中国大陆,但选择了美国的时区,通过ntpdate同步时,也得到的是美国当前时间.
时间文件是/etc/localtime,/usr/share/zoneinfo/目录下存放了所有的时区文件.

我们使用的中国上海的时区文件,文件格式如下:
file /etc/localtime 
/etc/localtime: timezone data, version 2, 3 gmt time flags, 3 std time flags, no leap seconds, 17 transition times, 3 abbreviation chars

有的人说也要设置/etc/sysconfig/clock文件,实际上这不是必须的,如下:
more /etc/sysconfig/clock 
# The time zone of the system is defined by the contents of /etc/localtime.
# This file is only for evaluation by system-config-date, do not rely on its
# contents elsewhere.
ZONE="Asia/Shanghai"



六)RTC
Real time clock(RTC):实时时钟是用来持久存放系统时间的设备,即便系统关闭后,它也可以靠主板上的微电池提供的电力保持系统定时.

查看rtc的详细信息,如下:
cat /proc/driver/rtc 
rtc_time        : 17:16:08
rtc_date        : 2011-10-16
alrm_time       : 17:12:39
alrm_date       : ****-**-**
alarm_IRQ       : no
alrm_pending    : no
24hr            : yes
periodic_IRQ    : no
update_IRQ      : no
HPET_emulated   : no
DST_enable      : no
periodic_freq   : 1024
batt_status     : okay
注:这里的rtc_time时间是utc时间.

ls -l /sys/class/rtc/rtc0/
total 0
-r--r--r--. 1 root root 4096 Oct 18 00:00 date
-r--r--r--. 1 root root 4096 Oct 18 00:00 dev
lrwxrwxrwx. 1 root root    0 Oct 18 00:00 device -> ../../../00:04
-r--r--r--. 1 root root 4096 Oct 18  2011 hctosys
-rw-r--r--. 1 root root 4096 Oct 18 00:00 max_user_freq
-r--r--r--. 1 root root 4096 Oct 18 00:00 name
drwxr-xr-x. 2 root root    0 Oct 18 00:00 power
-r--r--r--. 1 root root 4096 Oct 18 00:00 since_epoch
lrwxrwxrwx. 1 root root    0 Oct 18  2011 subsystem -> ../../../../../class/rtc
-r--r--r--. 1 root root 4096 Oct 18 00:00 time
-rw-r--r--. 1 root root 4096 Oct 18  2011 uevent
-rw-r--r--. 1 root root 4096 Oct 18 00:00 wakealarm

从rtc中获取的日期信息
cat /sys/class/rtc/rtc0/date
2011-10-17

从rtc中获取的时间信息
cat /sys/class/rtc/rtc0/time 
16:27:56

rtc设备的主设备号和从设备号
cat /sys/class/rtc/rtc0/dev
254:0

非特权用户可以从这个rtc中请求的最大中断率
cat /sys/class/rtc/rtc0/max_user_freq 
64

从1970-01-01 00:00:00开始的时间累计(秒数)
cat /sys/class/rtc/rtc0/since_epoch 
1318868801
注:可以用date +%s来获取系统的时间.


七)总结:
我们可以通过date命令获取系统的时间,系统时间是由可编程定时/计数器产生的输出脉冲触发中断而产生的.每一个输出脉冲也叫做一个时间滴答.
在操作系统中可以通过修改grub中的内核引导参数(tick_divider)来调整时钟中断频率,例如:
我们将tick_divider=10,也就是100Hz,那么每秒就有100次时间滴答,每个时钟滴答就是10毫秒(10ms).相应的系统时间就会每10ms增1.
内核通过通过变量jiffy来记录系统启动后产生的时间滴答的总数.
tick_divider可使用下列值:
2=500 Hz
4=250 Hz
5=200 Hz
8=125 Hz
10= 100 Hz
只限于X86和X86_64架构,不支持Xen.
阅读(7875) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~