Linux时间子系统之(十三):Tick Device layer综述

作者:linuxer 发布于:2015-3-26 18:50 分类:时间子系统

一、前言

时间子系统中的tick device layer主要涉及kernel/time/tick-*相关的文件,本文的主要内容就是从high level层次(不纠缠在具体的每行代码)描述tick device layer的运作逻辑。

如果说每个.c文件是一个模块的话,我们可以首先简单描述tick device layer的各个模块。tick-common.c描述了tick device的一些通用操作,此外,该文件还包括了周期性tick的代码。想要让系统工作在tickless mode(更准确应该是Dynamic tick模块,也就是说根据系统的当前运行状况,动态的启停周期性tick)需要两个模块的支持,分别是tick-oneshot.c和tick-sched.c。tick-oneshot.c主要是提供和tick device的one shot mode相关的操作接口函数。从字面上看,tick-sched.c是和tick的调度相关,所谓tick的调度包括两个方面,一方面是在系统正常运行过程中,如何产生周期性的tick event,另一方面是在系统没有任务执行,进入idle状态的时候,如何停止周期性的tick,以及恢复的时候如何更新系统状态(例如:jiffies等)。tick-broadcast.c和tick-broadcast-hrtimer.c是和tick broadcast相关,本文不会涉及这部分的内容,会有专门的文档描述它。

本文的第二章描述了关于tick device概述性的内容,随后在第三章描述了tick device layer是如何初始化的,由于tick device开始总是工作在periodic mode,因此,本章也就顺便描述了周期性tick的运作。如果硬件以及系统配置允许,系统中的tick device会切换one shot mode,从而进入tickless mode,因此第四章描述了在配置了高精度timer的情况下,dynamic tick如何运作之机理,第五章和第四章类似,只不过描述的是没有配置高精度timer的情况。

 

二、tick device概述以及软件结构

虽然在periodic tick文档中对tick device有一些描述,不过这里再复习一次,这次不再细述数据结构而是从较高的层面来描述tick device的软件结构。

1、什么是tick

想要理解什么是tick device,什么是tickless kernel,首先当然要理解什么是tick?要理解什么是tick,首先要理解OS kernel是如何运作的。系统中有很多日常性的事情需要处理,例如:

---更新系统时间

---处理低精度timer

---处理正在运行进程的时间片信息

系统在处理这些事情的时候使用了轮询的方式,也就是说按照固定的频率去做这些操作。这时候就需要HW的协助,一般而言,硬件会有HW timer(称之system timer)可以周期性的trigger interrupt,让系统去处理上述的日常性事务。每次timer中断到来的时候,内核的各个模块就知道,一个固定的时间片已经过去。对于日常生活,tick这个概念是和钟表关联的:钟表会发出周期性的滴答的声音,这个声音被称为tick。CPU和OS kernel扩展了这个概念:周期性产生的timer中断事件被称为tick,而能够产生tick的设备就称为tick device。

如何选择tick的周期是需要在power comsuption、时间精度以及系统响应时间上进行平衡。我们考虑系统中基于tick的低精度timer模块,选择较高的tick频率会提高时间精度,例如对于,10ms的tick周期意味着低精度timer的时间精度就是10ms,设定3ms的低精度timer没有任何意义。为了提高时间精度,我们可以提高tick的频率,例如可以提升到1ms的tick,但是,这时更多的CPU的时间被花费在timer的中断处理,实际上,当系统不繁忙的时候,并不是每一个tick都是那么有意义,实际上大部分的tick到来的时候,OS kernel往往只是空转,实际上并有什么事情做,这对系统的power consumption是有害的。对于嵌入式设备,周期性的tick对power consumption危害更大,因为对于嵌入式设备,待机时间是一个很重要的指标,而周期性tick则意味着系统不可能真正的进入idle状态,而是会周期性的被wakeup,这些动作会吃掉电池的电量。同理,对于调度器而言亦然。如果设定10ms的tick,分配每个进程的时间片精度只是10ms,调度器计算每个进程占用CPU的时间也只能是以10ms为单位。为了提高进程时间片精度,我们可以提高tick的频率,例如可以提升到1ms的tick,但是,这时更多的CPU的时间被花费在进程上下文的切换上,但是,对应的好处是系统的响应时间会更短。

2、什么是tickless?

tickless本质上上是去掉那个烦恼的滴答声音。我睡觉的时候不怕噪音,但是非常怕有固定周期的滴答声音,因此我需要一块tickless的钟表。对于OS kernel而言,tickless也就是意味着没有那个固定周期的timer interrupt事件,可是,没有那个固定的tick,OS kernel如何运转呢?我们还是选取上一节中的三个主题,进行逐一分析。

首先看看如何处理timer。各种驱动和内核模块(例如网络子系统的TCP模块)都有timer的需求,因此,时间子系统需要管理所有注册到系统的timer。对于有tick的系统,在每个tick中scan所有的timer是一个顺理成章的想法,如果检查到timer超期(或者即将超期)系统会调用该timer的callback函数。当然,由于要在每个tick到来的时候检查timer,因此效率非常重要,内核有一些有意思的设计,有兴趣的读者可以看看低精度timer的的scan过程。没有tick怎么办?这时候需要找到所有timer中最近要超期的timer,将其时间值设定到实际的HW timer中就OK了,当然,这时候需要底层的HW timer支持one shot,也就是说,该timer的中断就来一次,在该timer的的中断处理中除了处理超期函数之外,还需要scan所有timer,找到最近要超期的timer,将其时间值设定到实际的HW timer中就OK了,然后不断的重复上面的过程就OK了。假设系统中注册了1200ns, 1870ns, 2980ns, 4500ns, 5000ns和6250ns的timer,在一个HZ=1000的系统上,timer的超期都是在规则的tick时间点上,对于tickless的系统,timer的中断不是均匀的,具体如下图所示:

timerline

我们再来看看更新系统时间。对于有tick的系统,非常简单,在每个tick到来的时候调用update_wall_time来更新系统时间,当然,由于是周期性tick,这时候每次都是累加相同的时间。对于tickless的系统,我们可以选择在每个timer超期的中断中调用update_wall_time来更新系统时间,不过,这种设计不好,一方面,如果系统中的timer数目太多,那么update_wall_time调用太频繁,而实际上是否系统需要这么高精度的时间值呢?更重要的是:timer中断到来是不确定的,和系统中的timer设定相关,有的时间段timer中断比较频繁,获取的系统时间精度比较高,有的时间段,timer中断比较稀疏,那么获取的系统时间精度比较低。

最后,我们来看调度器怎么适应tickless。我们知道,除非你是一个完全基于优先级的调度器,否则系统都会给进程分配一个时间片(time slice),当占用CPU的时间片配额使用完了,该进程会挂入队列,等待调度器分配下一个时间片,并调度运行。有tick当然比较简单,在该tick的timer中断中减去当前进程的时间片。没有tick总是比较麻烦,我能想到的方法是:假设我们给进程分配40ms的时间片,那么在调度该进程的时候需要设定一个40ms的timer,timer到期后,调度器选择另外一个进程,然后再次设定timer。当然,如果没有进程优先级的概念(或者说优先级仅仅体现在分配的时间片比较多的情况下),并且系统中处于runnable状态的进程较少,整体的运作还是OK的。如果有优先级概念怎么办?如果进程执行过程中被中断打断,切换到另外的进程怎么办?如果系统内的进程数目很多如何保证调度器的性能?算了,太复杂了,还是有tick比较好,因此实际中,linux kernel在有任务执行的时候还是会启动周期性的tick。当然,世界上没有绝对正确的设计,任何优雅的设计都是适用于一定的应用场景的。其实自然界的规律不也是这样吗?牛顿的定律也不是绝对的正确,仅仅适用于低速的场景,当物体运动的速度接近光速的时候,牛顿的经典力学定律都失效了。

3、内核中的tickless

本节我们主要来看看内核中的tickless的情况。传统的unix和旧的linux(2000年初之前的)都是有tick的(对于新的内核,配置CONFIG_HZ_PERIODIC的情况下也是有tick的),新的linux kernel中增加了tickless的选项:

---CONFIG_NO_HZ_IDLE

---CONFIG_NO_HZ_FULL

CONFIG_NO_HZ_IDLE是说在系统dile的时候是没有tick的,当然,在系统运行的时候还是有tick的,因此,我们也称之dynamic tick或者NO HZ mode。3.10版本之后,引入一个full tickless mode,听起来好象任何情况下都是没有tick的,不过实际上也没有那么强,除了CPU处于idle的时候可以停下tick,当CPU上有且只有一个进程运行的时候,也可以停下周期性tick,其他的情况下,例如有多个进程等待调度执行,都还是有tick的。这个配置实际上只是对High-performance computing (HPC)有意义的,因此不是本文的重点。

4、tick device概述

Tick device是能够提供连续的tick event的设备。目前linux kernel中有periodic tick和one-shot tick两种tick device。periodic tick可以按照固定的时间间隔产生tick event。one-shot tick则是设定后只能产生一次tick event,如果要连续产生tick event,那么需要每次都进行设定。

每一个cpu都有属于自己的tick device。定义为tick_cpu_device。每一个tick device都有自己的类型(periodic或者one-shot),每一个tick device其实就是一个clock event device(增加了表示mode的member),不同类型的tick device有不同的event handler。对于periodic类型的tick设备,其clock event device的event handler是tick_handle_periodic(没有配置高精度timer)或者hrtimer_interrupt(配置了高精度timer)。对于one-shot类型的tick设备,其clock event device的event handler是hrtimer_interrupt(配置了高精度timer)或者tick_nohz_handler(没有配置高精度timer)。

Tick Device模块负责管理系统中的所有的tick设备,在SMP环境下,每一个CPU都自己的tick device,这些tick device中有一个被选择做global tick device,该device负责维护整个系统的jiffies以及更新哪些基于jiffies进行的全系统统计信息。

 

三、kernel如何初始化tick device layer以及周期性tick的运作?

如果把tick device的逻辑当初一个故事,那么故事的开始来自clockevent device layer。每当底层有新的clockevent device加入到系统中的时候,会调用clockevents_register_device或者clockevents_config_and_register向通用clockevent layer注册一个新的clockevent设备,这时候,会调用tick_check_new_device通知tick device layer有新货到来。如果tick device和clockevent device你情我愿,那么就会调用tick_setup_device函数setup这个tick device了。一般而言,刚系统初始化的时候,所有cpu的tick device都没有匹配clock event device,因此,该cpu的local tick device也就是global tick device了。而且,如果tick device是新婚(匹配之前,tick device的clock event device等于NULL),那么tick device的模式将被设定为TICKDEV_MODE_PERIODIC,即便clock event有one shot能力,即便系统配置了NO HZ。好吧,反正无论如何都需要从周期性tick开始,那么看看如何进行周期性tick的初始化的。

tick_setup_periodic函数用来设定一个periodic tick device。当然,最重要的设定event handler,对于周期性tick device,其clock event device的handler被设定为tick_handle_periodic。光有handler也不行,还得kick off底层的硬件,让其周期性的产生clock event,这样才能推动系统的运作(这是通过调用clockevent device layer的接口函数完成的)。

最后,我们思考一个问题:系统启动过程中,什么时候开始有tick?多核系统,BSP首先启动,在其初始化过程中会调用time_init,这里会启动clocksource的初始化过程。这时候,周期性的tick就会开始了。在某个阶段,其他的processor会启动,然后会注册其自己的local timer,这样,各个cpu上的tick就都启动了。

 

四、设置了高精度timer的情况下,dynamic tick如何运作?

1、软件层次

下面的这幅图是以tick device为核心,描述了该模块和其他时间子系统模块的交互过程(配置高精度timer和dynamic tick的情况):

dtick

上图中,红色边框的模块是per cpu的模块,所谓per cpu就是说每个cpu都会维护属于一个自己的对象。例如,对于tick device,每个CPU都会维护自己的tick device,不过,为了不让图片变得太大,上图只画了一个CPU的情况,其他CPU的动作是类似。为何clock event没有被涂上红色的边框呢?实际上clock event device并不是per cpu的,有些per cpu的local timer,也有global timer,如果硬件设计人员愿意的话,一个CPU可以有多个local timer,系统中所有的timer硬件被抽象成一个个的clock event device进行系统级别的管理,每个CPU并不会特别维护一个属于自己的clock event device。弱水三千,只取一瓢。每个CPU只会在众多clock event device中选取那个最适合自己的clock event device构建CPU local tick device。

tick device系统的驱动力来自中断子系统,当HW timer(tick device使用的那个)超期会触发中断,因此会调用hrtimer_interrupt来驱动高精度timer的运转(执行超期timer的call back函数)。而在hrtimer_interrupt中会扫描保存高精度timer的红黑树,找到下一个超期需要设定的时间,调用tick_program_event来设定下一次的超期事件,你知道的,这是我们的tick device工作在one shot mode,需要不断的set next expire time,才能驱动整个系统才会不断的向前。

传统的低精度timer是周期性tick驱动的,但是,目前tick 处于one shot mode,怎么办?只能是模拟了,Tick device layer需要设定一个周期性触发的高精度timer,在这个timer的超期函数中(tick_sched_timer)执行进行原来周期性tick的工作,例如触发TIMER_SOFTIRQ以便推动系统低精度timer的运作,更新timekeeping模块中的real clock。

2、如何切换到tickless

我们知道,开始tick device总是工作在周期性tick的mode,一切就像过去一样,无论何时,系统总是有那个周期性的tick到来。这个周期性的tick是由于硬件timer的中断推动,该HW Timer的中断会注册soft irq,因此,HW timer总会周期性的触发soft irq的执行,也就是run_timer_softirq函数。在该函数中会根据情况将hrtimer切换到高精度模式(hrtimer也有两种mode,一种高精度mode,一种是低精度mode,系统总是从低精度mode开始)。在系统切换到高精度timer mode的时候(hrtimer_switch_to_hres),由于高精度timer必须需要底层的tick device运行在one shot mode,因此,这时会调用tick_switch_to_oneshot函数将该CPU上的tick device的mode切换置one shot(Note:这时候event handler设定为hrtimer_interrupt)。同样的,底层的clock event device也会被设定为one shot mode。一旦进入one shot mode,那个周期性到来的timer中断就会消失了,从此系统只会根据系统中的hrtimer的设定情况来一次性的设定底层HW timer的触发。

3、如何产生周期性tick

虽然tick device以及底层的HW timer都工作在one shot mode,看起来系统的HW timer中断都是按需产生,多么美妙。但是,由于各种原因(此处省略3000字),在系统运行过程中,那个周期性的tick还需要保持,因此,在切换到one shot mode的同时,也会调用tick_setup_sched_timer函数创建一个sched timer(一个普通的hrtimer而已),该timer的特点就是每次超期后还会调用hrtimer_forward,不断的将自己挂回hrtimer的红黑树,于是乎,tick_sched_do_timer接口按照tick的周期不断的被调用,从而模拟了周期性的tick。

4、在idle的时候如何停掉tick

我们知道,各个cpu上的swapper进程(0号进程,又叫idle进程)最后都是会执行cpu_idle_loop函数,该函数在真正执行cpu idle指令之前会调用tick_nohz_idle_enter,在该函数中,sched timer会被停掉,因此,周期性的HW timer不会再来,这时候将cpu从idle中唤醒的只能是和实际上系统中的hrtimer中的那个最近的超期时间有关。

5、如何恢复tick

概念同上,当从idle中醒来,tick_nohz_idle_exit函数被调用,重建sched timer,一切恢复了原状。

 

五、没有设置高精度timer的情况下,dynamic tick如何运作?

  这部分留给有兴趣的读者自己学习吧。


原创文章,转发请注明出处。蜗窝科技

http://www.wowotech.net/timer_subsystem/tick-device-layer.html

标签: Device tick tickless NO_HZ

评论:

xie1230
2016-06-03 09:58
@linuxer 请问一下时间子系统中的alarmtimer和driver下的rtc目录,两者采用的框架不同,这两者都是驱动rtc硬件的吗?两者有什么区别?分别在什么情况下使用呢?
linuxer
2016-06-06 09:10
@xie1230:比较alarmtimer和rtc其实不太适合,因为alarmtimer底层就是调用rtc的接口,也就是说alarmtimer是基于rtc的。如果要比较,我觉得hrtimer比较适合和alarmtimer比较。这两个模块都是向内核的其他模块提供timer的服务,当然,除了内核模块,应用程序也有类似的需求,因此内核又通过POSIX接口向用户空间提供了各种clock和timer服务。

从功能角度看,这两种timer完全类似,除了电源管理方面的特性。对于hrtimer而言,当系统进入电源管理状态的时候,hrtimer是不会触发的,而alarmtimer不会收到系统电源管理状态的影响。一个典型的关于alarmtimer的应用就是:关机闹钟。
sched_fork
2015-11-11 18:11
看懂代码不算什么,把学到的东西用简单的语言描述出来才是真正的高手。
我也偶尔有写一些博文的想法,但是总是各样的原因(工作忙,要学习英语等等)没有写下一些笔记。
向博主致敬
linuxer
2015-11-12 10:00
@sched_fork:非常同意您的看法,脑袋中的东西来的快去的也快(我自己写的文章半年之后再看都觉得非常的陌生,当然,仔细阅读一遍之后还是能很快回到大脑中),因此最好还是深思熟虑之后,整理形成文档。而且,由于对事物的理解是螺旋式上升的,因此,好的文档往往是不断的修改,打磨才能发出智慧的光芒。
huangzhongmin
2015-08-19 16:06
楼主,请教个问题,有空的话帮忙解答下,非常感谢:
Hrtimer在系统睡眠的时候能唤醒系统么,如果可以,那么用RTC模块的定时器的作用是什么,好像没必要(除了关机定时)?
huangzhongmin
2015-08-19 16:13
@huangzhongmin:我看Android实现闹钟是这样的:
1.系统唤醒情况下用hrtimer定时器
2.suspend的时候把最近的到期时间写到RTC HW上去,时间到了唤醒系统
如果hrtimer可以唤醒系统,好像第2步骤就没意义了

谢谢。
linuxer
2015-08-28 09:30
@huangzhongmin:抱歉,漏掉您的问题了,有的时候评论滚动太快的时候就会错过一些问题。

Hrtimer在系统睡眠的时候能唤醒系统么?
---------------------
一般而言是不可以的,主要看hrtimer基于的那个clockevent device的power domain,大部分的系统设计都会在系统睡眠的时候都是会关闭(或者让其进入低功耗状态)大部分的硬件block(包括构建hrtimer对应的HW timer),而保留很小一部分的HW block(主要是RTC以及一些做为wakeup source的IO)处于工作状态。

RTC模块的定时器的作用是什么?
--------------------
我想你问的是alarm timer,alarm timer是基于RTC的,所有基于RTC的定时器在系统关机(或者叫做睡眠)仍然是可以正常触发,唤醒系统
allan
2018-01-28 11:35
@linuxer:linuxer,您好:
   刚看了你这里的答复,有个疑问,如果hrtimer无法唤醒系统,那么系统进入睡眠很长时间的话,这些hrtimer都已经超时了,不就不能准确定时了吗?

谢谢
linuxer
2018-01-29 19:12
@allan:如果你的定时器需要在系统suspend唤醒系统,那么hrtime也许并不适合,你可以考虑使用alarmtimer。
allan
2018-01-29 19:56
@linuxer:多谢回复:
其实我不理解为什么hrtimer不能唤醒系统。。系统suspend不会把最近的hrtimer设置到底HW timer模块吗(clock event device),为什么不能唤醒系统...
linuxer
2018-01-30 09:06
@allan:其实这和整个系统的电源管理相关,一般而言,当系统进入suspend的时候,绝大多数系统中的HW block都进入off状态,不能工作了,只有一小块“电源管理模块”能够存活,这个小模块仅仅能响应很少的HW 信号,唤醒系统。一般而言,clock event device所在的domain都不属于这个“电源管理模块”,因此clock event device一般都不能唤醒系统。
Jacky
2015-05-25 15:13
在CFS scheduler 中periodic 的tick 也是需要的么?
linuxer
2015-05-26 09:02
@Jacky:CFS scheduler当然需要周期性tick。无论哪种调度器,只要考虑时间因素(该进程的timeslice),并且以tick为单位统计进程的时间信息,那么它就需要周期性的tick。
passerby
2015-08-27 21:27
@linuxer:那CFS还是和时间片轮转法一样在每个tick检查进程切换(检查进程时间片是否超时)?还是直接通过虚拟运行时间对于的实际运行时间直接设定hrtimer,在理论的虚拟时间运行完后再从rq中寻找下个运行进程?
linuxer
2015-08-28 09:31
@passerby:这个问题我需要看调度器代码之后再回答你。
schedule
2015-09-05 15:58
@passerby:CFS 没有时间片的概念,scheduler不会事先分配时间片给task,时间系统对CFS的功能就是计时用。至于何时切换task,是看“相互追赶的速度”,为了不让速度慢的task被rq的虚拟时间被碾压死,task必须被执行
buyit
2015-05-16 09:04
请教几个问题:
在目前的嵌入式linux里面,特别是手机,基本都用到了tickless,并且支持hrtimer。请问这个必要性在哪里?
假设一个平台只支持periodic的timer,不支持oneshot的timer,那么是否意味着它不能使用tickless,也不能使用hrtimer,请问对这样的平台来说,有什么劣势,或者说有什么具体的驱动和应用程序会不能运行?
对于hrtimer,假设底层硬件支持了,并且软件里面也用上了,但是由于硬件的原因导致它不准,至少到不了ns级别的准确度,请问会发生什么不良后果?有什么具体的驱动和应用程序是依赖于ns级别的hrtimer的吗?
linuxer
2015-05-18 09:22
@buyit:在目前的嵌入式linux里面,特别是手机,基本都用到了tickless,并且支持hrtimer。请问这个必要性在哪里?
------------------------------------
tickless可以降低功耗(不需要处理不必要的tick中断),对嵌入式平台应该还是可以带来不错的performance
hrtimer主要和real time应用相关

假设一个平台只支持periodic的timer,不支持oneshot的timer,那么是否意味着它不能使用tickless,也不能使用hrtimer
---------------------
是的

请问对这样的平台来说,有什么劣势,或者说有什么具体的驱动和应用程序会不能运行?
----------------------
不会影响程序和驱动的运行,当然指功能层面,性能就不保证了。


对于hrtimer,假设底层硬件支持了,并且软件里面也用上了,但是由于硬件的原因导致它不准,至少到不了ns级别的准确度,请问会发生什么不良后果?有什么具体的驱动和应用程序是依赖于ns级别的hrtimer的吗?
-----------------------------
如果驱动软件需要控制几个ns的时序,那么多半需要HW来控制。我接触过一个RF信号处理的系统,对时间的精度要求很高,因此HW提供了一个特别的器件,这个器件是可编程的,一旦触发执行,所有对时间要求高的那个执行序列由那个硬件控制器按照之前驱动软件已经编好的程序来控制硬件动作。
buyit
2015-05-18 09:51
@linuxer:所以即使不能支持hrtimer,wifi,bt,hdmi,display,audio,微信,浏览器,这些常用的驱动程序和应用程序应该都可以运行良好?有没有特定的场景,由于hrtimer不支持导致它们运行的性能会下降?
linux的hrtimer是不是为了服务器级别的驱动和应用程序创建的?
linuxer
2015-05-18 11:26
@buyit:从timer的角度看应用程序和驱动,其实只是有两种,一种是有real time需求的,一种是没有。没有hrtimer的支持,那么timer的精度受限于tick。
假设hz=100,也就是说tick的精度是10ms,无论是驱动(调用timer接口)还是应用程序(posix clock and timer接口),设定10ms以下的精度,例如2ms,那么实际上这个timer由于精度不够,不可能在2ms秒后触发,而是在10ms后触发。如果支持hrtimer,那么2ms后即可以触发,并启动处理过程,当然,对于用户空间的程序还存在调度问题,这是另外一个话题了。

我觉得hrtimer是不是为了服务器级别的驱动和应用程序无关,只是和real time application相关,而这样的应用是不分服务器或者嵌入式平台的
buyit
2015-04-29 14:10
非常清晰的解答,让我对idle的理解又深了一层,请问cpu local timer在哪种idle情况下会停,在哪种idle模式下仍然运行,这个描述是不是在ARM ARM里面?之前没有仔细读过timer相关的章节,回头要好好研究一下,否则自己的SOC做出来都不知道怎么用。。。  如果有其它参考文档请告知。
再次感谢你的回答。
linuxer
2015-04-30 00:24
@buyit:cpu idle framework是一个挺复杂的framework,有兴趣可以参考wowo同学的4篇文档,讲的比较清楚。具体如何设计一个SOC的C state(idle state)是和具体的CPU实现相关,ARM并没有规定。
buyit
2015-04-29 11:31
请教一个问题:
     假设在旧的linux上面,HZ=100,也就是10ms为周期产生timer irq,那么系统中所有的软件timer的精度只能够到10ms的级别,系统产生timer irq的频率就是一秒有100次。
     换成新的架构,有no hz,tickless的模式,假设系统支持了高精度timer,但是为了调度器考虑,仍然产生了一个hz=100的hrtimer。 在系统正常运行过程中,假设一段时间内一直有工作的进程在运行,轮不到idle进程运行,那么这段时间内,系统中每秒钟产生100次hrtimer,为调度器使用,另外还会有一些精度更高的比如ns级别的hrtimer也会产生irq,所以对比旧的架构来看,新的架构下面如果系统负荷大的时候,timer中断反而会更多。
     假设系统空闲,变成了idle模式,那么旧的架构下面,如果cpuidle的级别不够深,会每秒被timer irq唤醒100次,几乎就是不能idle。而新的tickless架构下面,在idle之前把sched timer停掉了,因此idle过程中除非有其它hrtimer到期,否则不会被调度器使用的timer唤醒。
请问理解是否正确?谢谢。
linuxer
2015-04-29 12:26
@buyit:所以对比旧的架构来看,新的架构下面如果系统负荷大的时候,timer中断反而会更多。
-------------------------------------
的确,新的内核架构下,timer的中断会更多,但对于高性能的CPU而言,增加的中断次数可以忽略不计的。在旧的架构下,由于不支持高精度timer,因此,原本散布在各个ns时间点上的timer事件都并入到一个10ms的timer 中断event上来,因此中断次数当然比较少。

请问理解是否正确?
--------------
理解基本正确,除了“cpuidle的级别不够深”这句话。在多核架构下,timer硬件往往build in在cpu core上,因此,当cpu进入的idle级别比较深的时候,有可能local timer也进入inactive状态,这导致该硬件timer无法触发timer到期的中断事件。而实际上,cpu idle状态的时候需要硬件timer处于working状态。
这里使用新旧架构有些模糊,更准确的描述是:在有tick的内核中,每个cpu core上的swapper进程在被调度到的时候都会控制本cpu core进入idle状态,无论cpuidle的级别深或者不深,cpu都会每秒被timer irq唤醒100次。当然,如果cpu core定义了多种idle状态并且在较深的状态的时候导致local timer进入inactive状态,这时候,需要其他的手段来解决(tick broadcast framework)timer唤醒问题
quote
2015-05-03 13:29
@linuxer:这里的答案和本章内容之间充满着矛盾?
  在内核切换到tickless之后,仍然会创建一个sched timer。如果系统接下来进入了idle模式,这个sched timer在文章介绍是会被停止的,既然停止了这个周期性的timer,那么假设系统在1分钟之内都没有其它timer到期,系统1分钟都不退出idle?
idle线程被执行到的那个瞬间,代表所有其它线程都主动放弃了CPU,都在等待某种信号?是否有可能其它线程只是运行时间过长,被调度器剥夺了CPU资源,从而轮到idle线程暂时运行一下?在我看来,系统中所有的线程,不管它的优先级有多低,也不管高优先级的线程有多霸道一直占着CPU不放,调度器始终会保障低优先级的线程有机会运行一小会的,是吗?如果这种情况存在,那么idle把sched timer彻底停止显然是不合适的,必须有一个全局timer来broadcasting?
   总之文中的那句话“sched timer会被停掉,因此,周期性的HW timer不会再来,这时候将cpu从idle中唤醒的只能是和实际上系统中的hrtimer中的那个最近的超期时间有关” 以及回答里的这句话“无论cpuidle的级别深或者不深,cpu都会每秒被timer irq唤醒100次” 是有矛盾的。
linuxer
2015-05-03 21:56
@quote:在内核切换到tickless之后,仍然会创建一个sched timer。如果系统接下来进入了idle模式,这个sched timer在文章介绍是会被停止的,既然停止了这个周期性的timer,那么假设系统在1分钟之内都没有其它timer到期,系统1分钟都不退出idle?
-----------------------------------------------------
如果也没有其他中断触发的情况下(例如用户按下按键、以太网收到数据),那么是的,系统1分钟都不退出idle

idle线程被执行到的那个瞬间,代表所有其它线程都主动放弃了CPU,都在等待某种信号?
------------------------------------------------------------
是的。当然我理解你这里说的“信号”包括:等待signal、阻塞在I/O上、等待timer到期等等

是否有可能其它线程只是运行时间过长,被调度器剥夺了CPU资源,从而轮到idle线程暂时运行一下?
-----------------------------------------------
不会,idle进程不参与时间片的运算,只要有进程是runnable的(更准确的说法是对于n个cpu core的系统,只要有n个进程是runnable的),idle是不可能运行到的。

在我看来,系统中所有的线程,不管它的优先级有多低,也不管高优先级的线程有多霸道一直占着CPU不放,调度器始终会保障低优先级的线程有机会运行一小会的,是吗?
---------------------------------------------------------
不是,对于实时进程,只要它是可执行状态,那么normal进程是不会有机会执行到的。调度算法不是一两句可以将清楚的,我就不赘述了。

总之文中的那句话“sched timer会被停掉,因此,周期性的HW timer不会再来,这时候将cpu从idle中唤醒的只能是和实际上系统中的hrtimer中的那个最近的超期时间有关” 以及回答里的这句话“无论cpuidle的级别深或者不深,cpu都会每秒被timer irq唤醒100次” 是有矛盾的。
------------------------------------------------------------
我的原文是这样的:在有tick的内核中,每个cpu core上的swapper进程在被调度到的时候都会控制本cpu core进入idle状态,无论cpuidle的级别深或者不深,cpu都会每秒被timer irq唤醒100次。
我这里强调的是“在有tick的内核中”,也就是说没有配置NO HZ的情况。
对于dynamic tick,当没有执行idle进程的时候,其tick的情况和传统的周期性tick内核行为是一致的,而调度到idle进程执行的时候,会停掉sched timer,从而禁止了周期性tick的到来
netoohui
2015-04-09 17:40
同意楼上
schedule
2015-03-27 09:20
赞赞赞!赞完再看!

发表评论:

Copyright @ 2013-2015 蜗窝科技 All rights reserved. Powered by emlog