zoukankan      html  css  js  c++  java
  • kernel笔记——定时器与时间管理

    内核中时钟主要完成以下作用:

    • 记录系统运行时间
    • 完成时间相关的统计功能,如cpu占用率等
    • 定时功能,设定某个进程一段时间后完成某项任务 

    为实现以上功能,硬件以及内核提供了不同类型的时钟。

    RTC

    实时时钟(real time clock,RTC),又叫硬件时钟、墙上时钟。RTC记录的是00:00:00 GMT,1 January 1970到当前经历的时间。

    开机时,内核读取RTC时间,关机时内核更新RTC时间,系统运行的过程中不操作RTC。关机后依靠RTC记录时间,其由主板上的电池供电。

    内核读取到的RTC时间,保存在xtime变量中,xtime是timespec结构类型的变量,在中定义:

    struct timespec {
    __kernel_time_t tv_sec; /* seconds */
    long tv_nsec;           /* nanoseconds */
    };

    从结构定义中可以看到,xtime精度为纳秒。每次时钟中断触发时,中断处理函数将调用update_wall_time函数更新xtime。

    c库中的gettimeofday/settimeofday,就是基于xtime,获取或设置基准时间(00:00:00 GMT,1 January 1970)到当前的时间间隔。

    RTC设备在linux中用/dev/rtc表示,可以通过hwclock查询RTC时间、将RTC时间与系统时间相互同步。

    定时器

    周期性发生的事件由定时器(timer)触发,定时器是PIT(programmable interval timer)或TSC(time stamp counter)或其他类型的硬件芯片,时钟中断由定时器产生。

    一个定时器对应于一个时钟源,时钟源在内核中由clocksource结构表示,该结构定义了时钟源名称、读取时钟源方法、开启/关闭时钟源方法等内容。

    一个时钟事件由clock_event_device结构表示,该结构包含了时钟事件名称、时钟时间处理方法(event_handler)等字段。

    时钟中断发生的时间间隔称为节拍(tick),节拍在内核编译阶段设定:

    linux # zcat /proc/config.gz | grep CONFIG_HZ
    CONFIG_HZ_250=y
    CONFIG_HZ=250

    以上设定节拍为250HZ,即每4ms发生一次时钟中断,每秒发生250次。jiffies是一个全局变量,它记录了自系统启动以来产生的节拍数。

    每个cpu有各自的定时器,本地时钟中断发生时,由中断处理函数完成更新进程时间片、计算进程用户用时/系统用时等任务。update_process_times函数在本地时钟中断发生时被调用,该函数调用account_process_tick更新进程的用户态/内核态占用率,调用run_local_timers执行软时间中断,调用scheduler_tick更新当前进程的时间片。

    单次触发

    相比时钟中断提供4ms的计时精度,单次触发(one-shot)时钟提供更高的定时器精度。

    高精度的时间由hrtimer结构表示,nanosleep函数的底层实现就用到了hrtimer以及相关操作函数。系统调用nanosleep的实现如下:SYSCALL_DEFINE2(nanosleep, …) -> hrtimer_nanosleep() -> do_nanosleep() -> hrtimer_start_expires()。超时的hrtimer事件由hrtimer_wakeup处理,hrtimer_wakeup调用wake_up_process唤醒相应进程。

    suse11相比suse10提供了这种单次触发的时钟,由于其时间精度更高,poll、select、sleep等调用超时返回的频率更高,而cpu占用率、进程资源占用率等统计数据变得更精确。

    以下为suse11、suse10下usleep命令对比的例子,在两个系统上执行strace -Ttt usleep 1,跟踪输出中与usleep对应的系统调用如下:

    //suse11
    11:38:44.836889 nanosleep({0, 1000}, {0, 0}) = 0 <0.000061>
    11:38:44.836986 exit_group(0) = ?
    //suse10
    05:41:21.406039 nanosleep({0, 1000}, NULL) = 0 <0.000738>
    05:41:21.406838 exit_group(0) = ?

    从以上对比例子可看出,同样调用usleep休眠1微秒,suse11下usleep实际执行效果更接近1微秒设定值。

    clockchips.h文件中定义了定时器事件与单次触发事件相应的宏:

    #define CLOCK_EVT_FEAT_PERIODIC 0x000001
    #define CLOCK_EVT_FEAT_ONESHOT 0x000002

    Reference: Chapter 11 - Timers and Time Management, Linux kernel development.3rd.Edition

  • 相关阅读:
    (引)spring学习笔记1.什么是控制反转
    Arduino 各种模块篇 步进电机 step motor 舵机 servo 直流电机 总复习
    Raspberry Pi Wireless Adaptor
    Pyramid 使用总结1
    Arduino 各种模块篇 人体红外感应模块 proximity sensor
    Pyramid 使用总结2
    Webcam Streaming Desktop Recording on Linux for ubuntu or its destros
    Arduino 各种模块篇 步进电机 step motor( 不用库,不用shield, 纯)
    Arduino 各种模块篇 motor shield 电机扩展板(舵机、直流电机、步进电机party)
    转载 stepper motors
  • 原文地址:https://www.cnblogs.com/felixzh/p/9047689.html
Copyright © 2011-2022 走看看