-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlinux_timer.txt
99 lines (45 loc) · 2.79 KB
/
linux_timer.txt
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
linux timer
时间基准:让系统可以从规定时间开始计时,DOS的时间基准是1980年1月1日,Unix和Minux,Linux的时间基准是1970年1月1日0点
jiffies:无符号"32位变量",用来记录系统自启动以来所经过的时钟滴答数"tik-tok"
xtime:可以理解为Linux中的墙上时间,记录的是自1970年1月1日到当前时刻所经历的纳秒数
jiffies与xtime区别:在系统休眠后jiffies不计数,但是xtime不受影响
jiffies的不断循环,最大支持时间(2^32-1)/100/3600/24 = 497.1天? 100是HZ值,HZ是每秒的时钟中断次数,1s=jiffies/HZ
不同区间内时间点大小不同
为解决jiffies的绕回问题,提供了以下的宏:
#define time_after(a,b) (typecheck(unsigned long, a)&&typecheck(unsigned long, b)&&((long)((b) - (a)) < 0))
使用time_after时,延时不能超过 2^31-1个tick
为满足延时需要还可以使用jiffies_64;time_after64();
用户空间--timer_lib-()-timer用户空间接口---定时器\TimeKeeping---Tickdevice---通用clockEvent\通用clockSource模块-()-clock_source_driver-()-CPU_local_timer/global counter
定时器以时间轮划分为5个段,tv1数组长度为256,tv2-tv5都是64的长度,tv5位最高,tv1最低
1.添加定时器
struct timer_list timer;
......
init_timer(&timer);
timer.function = _function;
timer.expires = _expires;
timer.data = _data;
* add_timer(&timer);
......
2.到期处理
每次jiffies中,判断timer_jiffies中对应tv1-tv4区间值是否变为了0,若有为0的值表示有区间发生进位,取出上一个区间对应的定时器tv*.vec[i]重新添加到链表中去
? -->tv2.vec[0x01]=timer_2
手机中的RTC(实时时钟)时间: "busybox date" "busybox hwclock -r"
RTC不受系统关闭影响
* RTC更新xtime流程:略
/dev/rtc0 ---> (init xtime) ---> kernel xtime
/data/time/ats_* time_daemon
kernel xtime ---> (set xtime) ---> /data/time/ats_*
/dev/rtc0 time_daemon
xtime的休眠与唤醒
static struct clocksource clocksource_counter = {
.name = "arch_sys_counter",
.rating = 400,
.read = arch_counter_read,
.mask = CLOCKSOURCE_MASK(56),
.flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
};
休眠:timekeeping_suspend()--->timekeeping_forward_now()--->timekeeping_update()
休眠命令发出,读取休眠此刻的时间,将此时间计入到cycle_last里,作为下一次唤醒时时间变化的参考值
cycle_now=clock->read(clock);tk->cycle_last=cycle_now
唤醒:timekeeping_resume()--->cycle_now=clock->read(clock);cycle_delta=cycle_now-clock->cycle_last--->__timekeeping_inject_sleeptime()--->timekeeping_update()
读取当前时间减去休眠时保存的最后时间,差值加入到总共的sleep时间,更新时间表