Timers and time management in the Linux kernel. Part 6

这篇文章 Timers and time management in the Linux kernel. Part 6. 是出自 linux-insides一书中 Timers and time management 章节 内核版本比对5.7-rc1 进行了相关调整, 增加相关备注 Linux内核中的定时器和时间管理.Part 6. x86_64 相关的时钟源 这是chapter的第六部分,它描述了Linux内核中与计时器和时间管理相关的内容。 在之前的part中,我们看到了clockevents框架,现在我们将继续深入探讨与时间管理相关的问题 Linux内核中的内容。 本部分将描述与时钟源相关的x86架构的实现(有关[clocksource]概念的更多信息,您可以在second part 中找到相关信息. 首先,我们必须知道在x86体系结构中可以使用哪些时钟源。 从 sysfs 或者从下面的文件 /sys/devices/system/clocksource/clocksource0/available_clocksource. /sys/devices/system/clocksource/clocksourceN来获取相关信息: available_clocksource - 提供系统可用是时钟源 current_clocksource - 提供系统当前使用时钟源 实际看一下: $ cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm 我们可以看到有三个注册的时钟源在这个系统里: tsc - Time Stamp Counter; hpet - High Precision Event Timer; acpi_pm - ACPI Power Management Timer. 现在让我们看看第二个文件,它提供了最佳时钟源(在系统中具有最佳评级的时钟源) $ cat /sys/devices/system/clocksource/clocksource0/current_clocksource tsc tsc是Time Stamp Counter的简写. second part有过描述, 他描述了Linux Kernel的clocksource框架, 系统最好的时钟源应当是最有最好或最高功率,频率的, 或者说是具有最高frequency. ...

2020-04-27 · 6 min · 1139 words

linux-sides-Timers and time management in the Linux kernel. Part 5.

这篇文章 Timers and time management in the Linux kernel. Part 5. 是出自 linux-insides一书中 Timers and time management 章节 Introduction to timers 内核版本比对5.5-rc6 进行了相关调整, 增加相关备注 clockevents框架简介 这是本章节的第五部分,它描述了Linux内核中与计时器和时间管理相关的内容。正如您可能从本部分的标题中注意到的那样,将讨论clockevents框架。我们已经在本章的第二部分中看到了一个框架。这是clocksource框架。这两个框架都是Linux内核中的计时抽象。 首先,让我们回忆一下clocksource框架以及它的用途。 clocksource框架的主要目标是提供timeline。如documentation中所述: 例如,在Linux终端上输入命令date将最终读取时钟源以确定确切的时间。 Linux内核支持许多不同的时钟源。 您可以在drivers/clocksource中找到其中的一些。 例如,老一些的比如Intel 8253-可编程间隔计时器,频率为1193182, 还有一个-ACPI PM计时器,频率为3579545Hz。 除了drivers/clocksource目录之外,每种体系结构都可以提供自己的体系结构专用时钟源。 例如x86架构提供了高精度事件计时器,或者例如是powerpc通过timebase寄存器提供对处理器计时器的访问。 每个时钟源都提供单调原子计数器。 Linux内核支持大量不同的时钟源,每个时钟源都有自己的参数,例如frequency。 clocksource框架的主要目标是提供API,以选择系统中最佳的可用时钟源,即频率最高的时钟源。 clocksource框架的另一个目标是由时钟源提供的以人类时间单位的表示的原子计数器。 在这个时候,纳秒是Linux内核中给定时钟源的时间值单位的首选。 clocksource框架被定义在include/linux/clocksource.h头文件中的clocksource结构中,其中包含时钟源的name,系统中某些时钟源的额定值(频率较高的时钟源在系统中具有最大的额定值),系统中所有已注册时钟源的list,enable和disable字段来启用和禁用时钟源,指向read函数(必须返回时钟源的原子计数器)的指针等等。 另外,clocksource结构提供了两个字段:mult和shift,这是由某个时钟源提供给人类计时单位的原子计数器转换所必需的,即nanoseconds.通过以下公式进行转换: ns ~= (clocksource * mult) >> shift 我们已经知道,除了clocksource结构之外,clocksource框架还提供了一个API,用于注册具有不同频率比例因子的时钟源: static inline int clocksource_register_hz(struct clocksource *cs, u32 hz) static inline int clocksource_register_khz(struct clocksource *cs, u32 khz) 时钟源注销: int clocksource_unregister(struct clocksource *cs) … 除了clocksource框架之外,Linux内核还提供了clockevents框架。 如文档中所述: 时钟事件与时钟源在概念上相反 主要目标是管理时钟事件设备,或者换句话说,即管理允许注册事件的设备,换句话说,就是要进行以下操作的设备:中断将在将在将来的指定时间发生。 现在,我们对Linux内核中的clockevents框架有了一些了解,现在是时候来看一下API. clockevents框架相关API 描述时钟事件设备的主要结构是clock_event_device结构。 此结构在include/linux/clockchips.h头文件中定义,并且包含大量字段。 除了clocksource结构之外,它还具有name字段,其中包含时钟事件设备的可读名称,例如local APIC计时器: static struct clock_event_device lapic_clockevent = { .name = "lapic", ... ... ... } 某个时钟事件设备的event_handler,set_next_event,next_event函数的地址是中断处理程序,下一个事件的设置程序和本地分别存储下一个事件。 clock_event_device结构的另一个字段是-features字段。 它的价值可能来自以下通用功能: ...

2020-01-19 · 4 min · 715 words

HugeTLB Pages

这篇文章 Huge TLB Pages是出Linux Kernel文档 概述 该文档目的是简要概述在Linux内核HugePage。 现代CPU体系架构支持基于多个页面。 例如,x86 CPU通常支持4K和2M(如果体系结构支持,则为1G)页面大小,ia64架构支持多种页面大小4K,8K,64K,256K,1M,4M,16M,256M和ppc64支持4K和16M。 TLB是虚拟到物理的缓存转化。 通常,这是处理器上非常稀缺的资源。 操作系统试图充分利用有限数量的TLB资源。 现在,随着物理内存越来越大,这种优化变得越来越(几个GB)容易获得。 用户可以通过使用mmap系统调用来使用Linux内核中的Huge Page或标准SYSV共享内存系统调用(shmget,shmat)。 首先,Linux内核需要使用CONFIG_HUGETLBFS构建和CONFIG_HUGETLB_PAGE配置选项。 /proc/meminfo 文件提供内核Huge Page池中的持久性Huge Page的总数。它还显示默认Huge Page大小和空闲的数量,保留数量的信息 以及默认大小的Huge Page池中的多余Huge Page。 需要Huge Page大小才能生成正确的对齐方式, 映射Huge Page区域的系统调用的参数大小。 /proc/meminfo 文件中包含Huge Page信息如下: HugePages_Total: uuu HugePages_Free: vvv HugePages_Rsvd: www HugePages_Surp: xxx Hugepagesize: yyy kB Hugetlb: zzz kB HugePages_Total 总页面数量 HugePages_Free 未使用页面数量 HugePages_Rsvd 预留未使用数量 HugePages_Surp 预留未使用数量, 指大于/proc/sys/vm/nr_hugepages部分, 最大保留值由/proc/sys/vm/nr_overcommit_hugepages控制. Hugepagesize 每个页的大小单位Kb Hugetlb 占用内存大小(kB)相当于 HugePages_Total * Hugepagesize 详细信息可以查看 /sys/kernel/mm/hugepages /proc/filesystems 可以看到内核中的的hugetlbfs文件系统类型 ...

2020-01-07 · 2 min · 353 words

Netflix Blog- Mantis 开源

这篇文章Open Sourcing Mantis: A Platform For Building Cost-Effective, Realtime, Operations-Focused Applications 是出自 Netflix Technology Blog。 作为流式微服务生态系统,Mantis平台为工程师提供将观察和操作复杂分布式系统的成本降至最低的功能。 Mantis已开源 特点: 解决问题变得容易 开发人员可以根据需要从任何检测的应用程序中获取事件流。 解决问题成本降低 能够在事件上实现基于流的可观察性,同时使工程师能够使用工具来降低原本会对业务造成不利影响的成本。 指导原则 访问原始事件 实时访问这些事件 对获取数据进行新维度分析 保证最小花费,不抢占正常业务使用资源 Mantis 一些应用 Netflix流健康实时监控 上下文报警 Raven,MQL Mantis查询语言 Cassandra 健康检查 日志监控 Chaos监控 PII快速识别敏感数据。

2019-11-03 · 1 min · 38 words

linux-sides-Timers and time management in the Linux kernel. Part 4.

这篇文章 Timers and time management in the Linux kernel. Part 4. 是出自 linux-insides一书中 Timers and time management 章节 Introduction to timers 内核版本比对5.4-rc2 进行了相关调整, 增加相关备注 Linux内核中的定时器和时间管理.Part 4. 定时器 这是本章的第四部分,通过前一部分描述了Linux内核中与计时器和时间管理相关的内容,我们知道Linux内核中的tick broadcase框架和NO_HZ模式。我们将在这一部分继续研究与Linux内核中与时间管理相关的内容,并熟悉Linux内核中的另一个概念-timers。在研究Linux内核中的计时器之前,我们必须学习一些有关此概念的理论。请注意,我们将在本部分中考虑软件计时器。 Linux内核提供了软件计时器的概念,以允许将来可以调用内核功能。计时器在Linux内核中被广泛使用。例如,查看源代码文件 net/netfilter/ipset/ip_set_list_set.c。此源代码文件提供了用于管理IP地址组的框架的实现。 在 list_set 结构中包含了 time_list 变量 gc : struct list_set { ... struct timer_list gc; ... }; 并非gc字段具有timer_list类型。 在include/linux/timer.h 头文件中定义的结构,该结构的要点是存储 Linux内核中的动态计时器。 实际上,Linux内核提供了两种类型的计时器,称为动态计时器和间隔计时器。 内核使用第一种计时器,用户模式使用第二种计时器。timer_list结构包含实际的dynamic定时器。 在我们的示例中,list_set包含gc计时器代表垃圾收集的计时器。 该计时器将在list_set_gc_init函数中初始化: static void list_set_gc_init(struct ip_set *set, void (*gc)(struct timer_list *t)) { struct list_set *map = set->data; timer_setup(&map->gc, gc, 0); mod_timer(&map->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ); } 按照现有版本进行调整 由gc指针指向的函数,将在超时时间等于map->gc.expires后被调用。 ...

2019-10-25 · 6 min · 1230 words

wiki-Capability Maturity Model Integration

这是 CMMI的wiki 能力成熟度模型集成(CMMI)是一个过程级改进培训和评估程序。 它是由ISACA的子公司CMMI Institute管理的,由卡内基梅隆大学(CMU)开发。 许多美国国防部(DoD)和美国政府合同都要求这样做,尤其是在软件开发方面。 CMU声称CMMI可用于指导整个项目,部门或整个组织的流程改进。 CMMI为流程定义了以下成熟度级别:初始,已管理,已定义,已量化管理和优化中。 2.0版于2018年发布(1.3版于2010年发布,是此Wiki文章中其余信息的参考模型)。 CMMI由CMU在美国专利商标局注册。 概述 成熟度水平的特征 picture from wiki 最初,CMMI涉及三个感兴趣的领域: 产品和服务开发-CMMI for Development(CMMI-DEV); 服务的建立,管理,—CMMI for Services (CMMI-SVC); 产品和服务获取— CMMI for Acquisition(CMMI-ACQ)。 在2.0版中,这三个区域(以前每个区域都有一个单独的模型)被合并为一个模型。 CMMI由行业,政府和CMU的软件工程学院(SEI)组成的小组开发。 CMMI模型为开发或改进满足组织业务目标的流程提供了指导。 CMMI模型也可以用作评估组织流程成熟度的框架。 到2013年1月,整个CMMI产品套件已从SEI转移到卡耐基梅隆大学新成立的组织CMMI研究所。 历史 CMMI由CMMI项目开发,旨在通过将许多不同的模型集成到一个框架中来提高成熟度模型的可用性。该项目由行业,政府和卡内基梅隆软件工程学院(SEI)的成员组成。主要赞助商包括国防部长办公室(OSD)和国防工业协会。 CMMI是功能成熟度模型(CMM)或软件CMM的后继产品。 CMM是从1987年到1997年开发的。2002年发布了1.1版,随后在2006年8月发布了1.2版,并在2010年11月发布了1.3版。CMMIV1.3的一些重大更改是对敏捷软件开发的支持, 对高成熟度实践的改进和实施流程的改进。 根据软件工程学院(SEI,2008)的说法,CMMI帮助 " 整合传统上独立的组织功能,设置流程改进目标和优先级,为质量流程提供指导,并为评估当前流程提供参考点。" 2016年3月,CMMI研究所被ISACA收购。 CMMI主题 表示 在1.3版中,CMMI有两种表示形式:连续表示和分段表示。 连续表示的目的是使用户可以专注于对组织的近期业务目标重要的特定过程,或组织为之分配高度风险的特定过程。 分阶段的表示旨在提供标准的改进顺序,并且可以用作比较不同项目和组织的成熟度的基础。 分阶段的表示还提供了从SW-CMM到CMMI的轻松迁移。 在2.0版中,以上表示分离已被取消,现在只有一个内聚模型。 模型框架(v1.3) 取决于所使用的关注领域(收购,服务,开发),其包含的过程领域将有所不同。 流程区域是组织的流程将覆盖的区域。下表列出了版本1.3中所有感兴趣的CMMI领域共有的17个CMMI核心过程领域。 缩写 名称 领域 成熟度 OT Organizational Training Process Management 3 OPP Organizational Process Performance Process Management 4 OPM Organizational Performance Management Process Management 5 OPF Organizational Process Focus Process Management 3 OPD Organizational Process Definition Process Management 3 RSKM Risk Management Project Management 3 REQM Requirements Management Project Management 2 QPM Quantitative Project Management Project Management 4 PP Project Planning Project Management 2 PMC Project Monitoring and Control Project Management 2 IPM Integrated Project Management Project Management 3 SAM Supplier Agreement Management Support 2 PPQA Process and Product Quality Assurance Support 2 MA Measurement and Analysis Support 2 DAR Decision Analysis and Resolution Support 3 CM Configuration Management Support 2 CAR Causal Analysis and Resolution Support 5 服务的成熟度级别 针对服务模型CMMI,列出了以下过程域及其成熟度级别: ...

2019-10-15 · 2 min · 297 words

linux-sides-Timers and time management in the Linux kernel. Part 3.

这篇文章 Timers and time management in the Linux kernel. Part 3. 是出自 linux-insides一书中 Timers and time management 章节 The tick broadcast framework and dyntick 内核版本比对5.3-rc8 进行了相关调整, 增加相关备注 Linux内核中的定时器和时间管理.Part 3. tick broadcast框架和dyntick 这是本章 的第三部分,他描述了定时器和时间管理的相关内容,前一部分我们讲到了 clocksource框架. 我们已经开始考虑这个框架,因为它与Linux内核提供的特殊计数器密切相关。在本章的第一部分 已经看到了其中的一个 - jiffies. 正如我在本章的第一部分已经写过的那样,我们将在Linux内核初始化期间逐步考虑与时间管理相关的内容。之前章节调用: register_refined_jiffies(CLOCK_TICK_RATE); 这个函数定义在 kernel/time/jiffies.c 文件中, 并初始化变量 refined_jiffies 时钟源. 被setup_arch 调用, setup_arch定义在arch/x86/kernel/setup.c中,并执行特定于体系结构的(以x86_64 为例)初始化。 查看setup_arch的实现,您将注意到register_refined_jiffies的调用是setup_arch函数完成其工作之前的最后一步。 在setup_arch执行结束后,已经配置了许多不同的x86_64特定的东西。 例如,一些早期interrupt处理程序已经能够处理中断, 为initrd保留的内存空间,DMI扫描,Linux内核日志缓冲区已经设置,这意味着printk函数能够工作,e820的解析,Linux内核已经知道可用内存和许多其他架构特定的东西(如果你感兴趣,您可以在本书的第二章章节中阅读有关setup_arch函数和Linux内核初始化过程的更多信息。 现在,setup_arch完成了它的工作,我们可以回到通用Linux内核代码。回想一下setup_arch函数是从start_kernel函数调用的,该函数在init/ main.c源代码文件中定义。所以,我们将回到这个功能。您可以看到在start_kernel函数内部的setup_arch函数之后有很多不同的函数被调用,但由于我们的章节专门讨论定时器和时间管理相关的部分,我们将跳过所有与此无关的代码话题。与Linux内核中的时间管理相关的第一个函数是: tick_init(); 在start_kernel中。 tick_init函数在kernel/time/tick-common.c源代码文件中定义,做两件事: 初始化tick broadcast框架相关的数据结构; 初始化full tickless模式相关的数据结构。 我们在本书中没有看到与tick broadcast框架相关的任何内容,并且对Linux内核中的tickless模式一无所知。因此,这一部分的要点是研究这些概念并了解它们是什么。 The idle process 首先看下tick_init函数的实现. 正如之前说得这个函数定义在 kernel/time/tick-common.c 源码文件中,由以下两个函数组成: void __init tick_init(void) { tick_broadcast_init(); tick_nohz_init(); } 正如您从段落标题中可以理解的那样,我们现在只对tick_broadcast_init函数感兴趣。 此函数在kernel/time/tick-broadcast.c源代码文件中定义并执行初始化 tick broadcast框架相关的数据结构。 在我们查看tick_broadcast_init函数的实现之前,我们将尝试了解这个函数的作用,我们需要了解tick broadcast框架。 ...

2019-09-13 · 4 min · 689 words

Linuxjournal-The Linux Scheduler

这篇文章 The Linux Scheduler作者Moshe Bar发表在linuxjournal, 是一篇2000年的文章.从Linux版本时间线可以看到,那时Linux内核版本2.2, 过了一年后2001正式发布2.4版本 图片来源wiki/Linux内核 正文 了解内核如何为单处理器和多处理器计算机调度任务。 上个月,我们开始了一个关于Linux内核内部的新系列。 在第一部分中,我们研究了Linux如何管理流程以及为什么Linux在许多方面比许多商业UNIX系统更好地创建和维护流程。 这一次,我们详细讨论了调度问题。 令我惊讶的是,在这里,Linux走向非传统的方式,无视核心理论中的传统智慧。 结果非常好。 我们来看看如何。 调度类 在Linux 2.2.x中有三类进程,从调度程序的数据定义可以看出(来自linux/include/linux/sched.h): 调度策略 #define SCHED_OTHER 0 #define SCHED_FIFO 1 #define SCHED_RR 2 SCHED_OTHER任务是正常的用户任务(默认)。 在SCHED_FIFO中运行的任务永远不会被抢占。它们将仅在等待同步内核事件或者如果已从用户空间请求显式睡眠或重新调度,释放CPU资源。 在SCHED_RR中运行的任务是实时(RT)的 ,但如果运行队列中有另一个实时任务,它们将离开CPU。因此CPU资源将在所有SCHED_RR任务之间分配。如果至少有一个实时任务正在运行,则不允许在任何CPU中运行其他SCHED_OTHER任务。每个实时任务都有一个rt_priority,因此允许SCHED_RR类随意在所有SCHED_RR任务之间分配CPU资源。 SCHED_RR类的rt_priority与SCHED_OTHER(默认)类的普通优先级字段完全相同。 只有root用户才能通过sched_setscheduler系统调用更改当前任务的类。 内核的任务之一是确保即使在异常进程的情况下系统仍然处于其控制之下。一个这样异常的程序可能会过快地fork太多进程。因此,内核变得如此忙碌以至于无法满足其他职责。我发现Linux对用户态程序生成子进程的速度没有限制。 HP-UX,Solaris和AIX每个处理器的时间限制(tick)为一个fork(在Linux下称为jiffie)。清单1中的补丁(请参阅参考资料)将允许每个jiffie最多一个fork(一个jiffie通常是1/100秒,除了Alpha架构,它是1/1024)。 文中提到的清单1 (稍微调整了下格式) 2.3.26/kernel/fork.c Thu Oct 28 22:30:51 1999 +++ /tmp/fork.c Tue Nov 9 01:34:36 1999 @@ -591,6 +591,14 @@ int retval = -ENOMEM; struct task_struct *p; DECLARE_MUTEX_LOCKED(sem); + static long last_fork; + while (time_after(last_fork+1, jiffies)) + { + __set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + last_fork = jiffies; if (clone_flags & CLONE_PID) { /* This is only allowed from the boot up thread */ 个人理解,如果last_fork+1>jiffies说明当前进程在1个jiffie内创建,设置进程休眠,类似delay功能(这个地方也不是很确认:(, 后续需要再验证一下) ...

2019-09-04 · 5 min · 907 words

linux kernel documentation-CFS Scheduler

这篇文章 CFS Scheduler是Linux Kernel文档 1.概述 CFS - “Completely Fair Scheduler”,是新的交互式流程调度算法,由Ingo Molnar实现,并在Linux 2.6.23中合并。它是替换以前的Vanilla Kernel的SCHED_OTHER调度策略对应的调度算法。 SCHED_OTHER是老版本中的调度策略后续成为SCHED_NORMAL Vanilla Kernel是指http://www.kernel.org/的上Linux的发布版本 What is Vanilla kernel Debian wiki vanilla CFS 80%的设计可以用一句话来概括:CFS基本上是模型真实硬件上的“理想,精确的多任务CPU”。 理想的多任务CPU是一种(不存在的 :-) )具有100%物理性能的CPU 功率和每个任务可以以精确的相等速度并行运行每个任务 1 / nr_running速度。例如:如果有2个任务在运行,那么它就会运行每个物理功率为50%, 即实际上并联。 在真正的硬件上,我们一次只能运行一个任务,所以我们必须这样做 介绍虚拟运行时(vruntime))的概念。任务的虚拟运行时 指定下一个时间片何时开始执行理想 上面描述的多任务CPU。在实践中,任务的虚拟运行时是它的实际运行时间标准化为正在运行的任务总数。 2.部分实现细节 在CFS中,通过每个任务task的虚拟运行时(vruntime)通过 p->se.vruntime(纳秒为单位)值体现。这样,就可以任务可以等到准确时间戳并测量应该得到的预期CPU时间。 [小细节:在理想硬件上,任何时候所有任务都会相同 p-> se.vruntime — 任务将同时执行, 没有任务将从CPU时间等到一样的份额。] CFS的任务选择逻辑基于此p->se.vruntime值,因此非常简单:它总是尝试以最小的p->se.vruntime运行任务值(即至少执行到目前为止的任务)。 CFS总是试图拆分 可运行任务之间的CPU时间接近理想的多任务硬件 可能。 CFS的其余大部分设计都脱离了这个非常简单的概念, 有一些附加的装饰,如nice值,多处理和各种算法变体去识别睡眠者。 3. 红黑树 CFS的设计非常激进:它没有使用旧的数据结构 runqueues,但它使用按时间排序的rbtree来构建未来执行任务的时间轴 ,因此不涉及数组切换(以前的Vanilla Kernel调度器O(1)和RSDL/SD涉及到)。 Linux 2.4调度使用时间片epoch,类似多路复用模式,使用runqueue调度方法与进程个数有关 array switch:O(1)为每个CPU维护了两个数组active与expire数组,随着时钟中断发生,1.调度器判断当前进程类型交互进程或者实时进程,重置其时间片重新插入active数组,不是交互实时进程、时间片使用完毕的放入expired数组, 当所有active为空,active与expired交换 RSDL/SD是对O(1)改进 Linux 调度器发展简述 CFS还维护rq->cfs.min_vruntime值,这是一个单调递增值,用于跟踪runqueue中所有任务中的最小vruntime。使用min_vruntime跟踪系统完成的工作总量; 该值用于尽可能多地将新激活的实体放置在树的左侧。 每一个cpu维护一个min_vruntime,每一个子进程创建时被初始化为这个值,如果schedule_feature 设置了SCHED_DEBIT,vruntime还会再增大一些 从几个问题开始理解CFS调度器 runqueue中运行任务的总数通过rq->cfs.load值计算,该值是在runqueue上排队的任务的权重之和。 ...

2019-08-29 · 2 min · 225 words

linux-sides-Timers and time management-Introduction to the clocksource framework

这篇文章 Timers and time management in the Linux kernel. Part 2. 是出自 linux-insides一书中 Timers and time management 章节 Introduction to the clocksource framework Linux内核中的定时器和时间管理.Part 2. clocksource框架简介 上一节Part 1是Timer的第一部分,描述了Linux内核中与计时器和时间管理相关的东西。我们在前一部分中了解了两个概念: jiffies clocksource 第一个全局变量定义在include/linux/jiffies.h头文件中,代表在每个定时器中断期间增加的计数器。因此,如果我们可以访问这个全局变量并且我们知道定时器中断率,我们可以将jiffies转换为人类时间单位。我们已经知道在Linux内核中由编译时常量(称为“HZ”)表示的定时器中断速率。HZ的值等于CONFIG_HZ内核配置选项的值,如果我们通过文件arch/x86/configs/x86_64_defconfig查找到内核相关配置: CONFIG_HZ_1000 = Y 设置内核配置选项后. x86_64 体系架构下 CONFIG_HZ值默认是 1000 , 如果我们将jiffies除以HZ: jiffies / HZ 我们将获得自Linux内核开始工作之后经过的秒数,换句话说,我们将获得系统uptime. 由于HZ代表一秒钟内的定时器中断量,我们可以在未来的某个时间设置一个值。例如: /* one minute from now */ unsigned long later = jiffies + 60*HZ; /* five minutes from now */ unsigned long later = jiffies + 5*60*HZ; 这是Linux内核中非常常见的做法。例如,如果您将查看 arch/x86/kernel/smpboot.c 源代码文件,你会发现do_boot_cpu函数。此功能启动除引导处理器之外的所有处理器。您可以找到等待十秒钟的应用程序处理器响应的代码段: if (!boot_error) { timeout = jiffies + 10*HZ; while (time_before(jiffies, timeout)) { ... ... ... schedule(); } ... ... ... } 备注: 原书udelay(100)后修改为schedule() 详见x86/smpboot: Remove udelay(100) when polling cpu_initialized_map ...

2019-08-20 · 5 min · 1003 words