Timers and time management in the Linux kernel. Part 7.

这篇文章 Timers and time management in the Linux kernel. Part 7. 是出自 linux-insides一书中 Timers and time management 章节 内核版本比对5.7 进行了相关调整, 增加相关备注 Linux内核中与时间相关的系统调用 这是第七章也是最后一章chapter, 它描述了Linux内核中计数器和时间管理相关的内容. 在前面的章节 part, 我们在 x86_64: High Precision Event Timer 和Time Stamp Counter. 内部时间管理是Linux内核中一个有趣的部分, 但是,当然,不仅内核需要time概念. 我们的程序还需要知道时间。这一部分中,我们将考虑实际一些与时间管理相关的 system calls. 这些系统调用: clock_gettime; gettimeofday; nanosleep. 我们将从一个简单的用户空间C 程序开始, 并从standard library 函数执行某些系统调用。由于每个 architecture 提供了自己的某些系统调用实现,因此我们将仅考虑x86_64系统调用的特定实现,因为本书与此体系结构相关。 Additionally, we will not consider the concept of system calls in this part, but only implementations of these three system calls in the Linux kernel. If you are interested in what is a system call, there is a special chapter about this. ...

2020-06-07 · 8 min · 1541 words

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

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

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

linux-sides-Timers and time management-Introduction

这篇文章 Timers and time management in the Linux kernel. Part 1. 是出自 linux-insides一书中 Timers and time management 章节 Introduction 内核版本比对5.3-rc 进行了相关调整, 增加相关备注 Linux内核中的定时器和时间管理. Part 1. 介绍 这是另一篇文章,它在linux-insides一书中开启了新的篇章。前面的部分描述了系统调用概念,现在是时候开始新篇章了。正如人们可能从标题中理解的那样,本章将专门讨论Linux内核中的“定时器”和“时间管理”。当前章节的主题选择并非偶然。定时器(通常是时间管理)非常重要,并且在Linux内核中广泛使用。 Linux内核使用计时器执行各种任务,例如TCP实现中的不同超时,内核知道当前时间,调度异步函数,下一个事件中断调度和还有更多。 因此,我们将开始学习本部分中不同时间管理相关内容的实现。我们将看到不同类型的计时器以及不同的Linux内核子系统如何使用它们。与往常一样,我们将从Linux内核的最早部分开始,并完成Linux内核的初始化过程。我们已经在特殊的章节-Kernel initialization process中完成了它,它描述了Linux内核的初始化过程,但是你可能还记得我们错过了那里有些东西。其中一个是定时器的初始化。 我们开始吧。 初始化非标准PC硬件时钟 Linux内核解压缩后(更多关于此内容,您可以在内核解压缩部分中阅读)非特定代码开始在init/main.c源代码文件中工作。初始化lock validator后,初始化cgroups并设置canary值,我们可以看到setup_arch函数的调用。 你可能还记得,这个函数(定义在arch/x86/kernel/setup.c)准备/初始化特定于体系结构的东西(例如它为bss部分保留一个位置,为initrd保留一个位置,解析内核命令行以及许多其他事情)。除此之外,我们还可以找到一些时间管理相关的功能。 首先是: x86_init.timers.wallclock_init(); 我们在描述Linux内核初始化的章节中已经看到了x86_init结构。此结构包含指向不同平台的默认设置功能的指针,如 Intel MID,Intel CE4100 等x86_init结构定义在arch/x86/kernel/x86_init.c,正如您所看到的,它默认确定标准PC硬件。 我们可以看到,x86_init结构具有x86_init_ops类型,它为平台特定的设置提供了一组函数,如保留标准资源,平台特定的内存设置,中断处理程序的初始化等。这种结构如下所示: struct x86_init_ops { struct x86_init_resources resources; struct x86_init_mpparse mpparse; struct x86_init_irqs irqs; struct x86_init_oem oem; struct x86_init_paging paging; struct x86_init_timers timers; struct x86_init_iommu iommu; struct x86_init_pci pci; struct x86_hyper_init hyper; struct x86_init_acpi acpi; }; 备注: 新增以下两个成员 ...

2019-08-07 · 3 min · 631 words