linux时间子系统 - clocksource/timekeeper

article/2025/9/12 11:59:45

linux时间子系统中有一个很重要的记录时间的模块就是timekeeper,而timekeeper需要底层clock硬件设备的支持,每一个设备用结构体clocksource来表示,注册进系统的每一个clocksource会凭借优先级最终被选择成为timekeeper的时钟源。

1. clocksource的注册


1.1 clocksource结构体

struct clocksource {cycle_t (*read)(struct clocksource *cs);cycle_t mask;u32 mult;u32 shift;u64 max_idle_ns;u32 maxadj;
#ifdef CONFIG_ARCH_CLOCKSOURCE_DATAstruct arch_clocksource_data archdata;
#endifu64 max_cycles;const char *name;struct list_head list;int rating;----------------------------------------clock设备的优先级int (*enable)(struct clocksource *cs);-------------clock设备使能void (*disable)(struct clocksource *cs);-----------clock设备关闭unsigned long flags;-------------------------------clock源的标志void (*suspend)(struct clocksource *cs);-----------PM调用函数suspendvoid (*resume)(struct clocksource *cs);------------PM调用函数resume/* private: */
#ifdef CONFIG_CLOCKSOURCE_WATCHDOG/* Watchdog related data, used by the framework */struct list_head wd_list;cycle_t cs_last;cycle_t wd_last;
#endifstruct module *owner;
};

1.2 clocksource_list

每一个注册进系统的clock设备都会加入一个全局链表clocksource_list

(kernel/time/clocksource.c)

static LIST_HEAD(clocksource_list);

但是timekeeper只会选取其中最合适的一个作为主clock,用一下变量来表示

static struct clocksource *curr_clocksource;

1.3 注册函数

clocksource的注册函数有如下几个:

(include/linux/clocksource.h)

static inline int __clocksource_register(struct clocksource *cs)
{return __clocksource_register_scale(cs, 1, 0);
}static inline int clocksource_register_hz(struct clocksource *cs, u32 hz)
{return __clocksource_register_scale(cs, 1, hz);
}static inline int clocksource_register_khz(struct clocksource *cs, u32 khz)
{

1.4 clocksource注册过程

clocksource设备的注册可以当作一个驱动,所以一般clock设备的文件都在dricers/clocksource/目录下,下面以arm global timer为例来介绍注册过程。

clocksource设备的初始化接口由宏定义:

CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",global_timer_of_register);

global的初始化函数为global_timer_of_register,下图是注册的函数调用关系图:

这里写图片描述

1.4.1 把clock设备加入clocksource_list

函数clocksource_enqueue实现这个过程

static void clocksource_enqueue(struct clocksource *cs)
{struct list_head *entry = &clocksource_list;struct clocksource *tmp;list_for_each_entry(tmp, &clocksource_list, list)/* Keep track of the place, where to insert */if (tmp->rating >= cs->rating)entry = &tmp->list;--------------得到最合适插入的地方list_add(&cs->list, entry);--------------加入clocksource_list
}

1.4.2 选取最合适的curr_clocksource

函数__clocksource_select实现这个过程:

static void __clocksource_select(bool skipcur)
{bool oneshot = tick_oneshot_mode_active();struct clocksource *best, *cs;/* Find the best suitable clocksource */best = clocksource_find_best(oneshot, skipcur);if (!best)
        return;--------------------------------------------没有找到合适的就直接返回/* Check for the override clocksource. */list_for_each_entry(cs, &clocksource_list, list) {if (skipcur && cs == curr_clocksource)continue;if (strcmp(cs->name, override_name) != 0)continue;/** Check to make sure we don't switch to a non-highres* capable clocksource if the tick code is in oneshot* mode (highres or nohz)*/if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && oneshot) {/* Override clocksource cannot be used. */pr_warn("Override clocksource %s is not HRT compatible - cannot switch while in HRT/NOHZ mode\n",cs->name);override_name[0] = 0;} else/* Override clocksource can be used. */best = cs;-------------------------------------根据上面各个条件的过滤,最后得到最好的clocksourcebreak;}if (curr_clocksource != best && !timekeeping_notify(best)) {pr_info("Switched to clocksource %s\n", best->name);curr_clocksource = best;--------------------------把clocksource给curr_clocksource }
}

2. timekeeper


struct timekeeper {struct tk_read_base tkr_mono;struct tk_read_base tkr_raw;u64         xtime_sec;unsigned long       ktime_sec;struct timespec64   wall_to_monotonic;ktime_t         offs_real;ktime_t         offs_boot;ktime_t         offs_tai;s32         tai_offset;unsigned int        clock_was_set_seq;u8          cs_was_changed_seq;ktime_t         next_leap_ktime;struct timespec64   raw_time;/* The following members are for timekeeping internal use */cycle_t         cycle_interval;u64         xtime_interval;s64         xtime_remainder;u32         raw_interval;/* The ntp_tick_length() value currently being used.* This cached copy ensures we consistently apply the tick* length for an entire tick, as ntp_tick_length may change* mid-tick, and we don't want to apply that new value to* the tick in progress.*/u64         ntp_tick;/* Difference between accumulated time and NTP time in ntp* shifted nano seconds. */s64         ntp_error;u32         ntp_error_shift;u32         ntp_err_mult;
#ifdef CONFIG_DEBUG_TIMEKEEPINGlong            last_warning;/** These simple flag variables are managed* without locks, which is racy, but they are* ok since we don't really care about being* super precise about how many events were* seen, just that a problem was observed.*/int         underflow_seen;int         overflow_seen;
#endif
};

TODO

Change Log


datecontentlinux
2016.12.11clocksourcelinux 4.6.3

http://chatgpt.dhexx.cn/article/2AfF6rCP.shtml

相关文章

【Java】Timer和TimerTask详解

以下内容根据 The JavaTM Tutorial 和相关API doc翻译整理,以供日后参考: 1.概览 Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。 TimerTask一个抽象类,它的子类代表一个可以…

【Linux内核代码分析1】Linux时间子系统及HRTIMER实现

Linux时间子系统软件架构 (1)嵌入式设备需要较好的电源管理策略。传统的linux会有一个周期性的时钟,即便是系统无事可做的时候也要醒来,这样导致系统不断的从低功耗(idle)状态进入高功耗的状态。这样的设计…

Linux Time

1、Linux时钟框架 上图是linux时钟框架一个经典的描述。本质上linux各种时钟架构和服务是基于硬件提供的两种timer而构建的。 1、定时Timer 这类timer每个cpu都有一个独立的,称为local timer。这类timer的中断一般都是PPI(Private Peripheral Interrup…

Linux时间子系统基础(三):时间的维护者:timekeeper

本系列文章的前两节讨论了用于计时的时钟源:clocksource,以及内核内部时间的一些表示方法,但是对于真实的用户来说,我们感知的是真实世界的真实时间,也就是所谓的墙上时间,clocksource只能提供一个按给定频…

攻防世界--TimeKeeper

将price和id加上引号,触发debug 联想到扫描目录出现的/console Flask debug pin安全问题 这种方法有点难,换种方法 目录穿越 可以成功读取任意文件,获得flag。

html 时间控件滚动选择器,TimePicker

TimePicker滚动的列表选择器,可用于时间选择。多个TimePicker组合起来可实现复杂的应用,如效果图中,俩个TimePicker组合,一个表示"分"、一个表示"秒"。 效果图: 如何使用xml创建 android:id"…

Linux时间子系统之时间维护层(Time Keeper)

时间维护层会收到Tick层的周期调用,每次调用的周期是由内核参数决定的。在此期间,时间维护层可以读取时钟源设备的周期数,从而感知时间的流逝。 目前时间维护层主要负责维护以下几种类型的时间: 实时时间(CLOCK_REAL…

【Linux内核|时间子系统】Linux时间子系统(二)timekeeping简介

文章目录 1. timekeeping2. 计算墙上时间、启动时间差值3. timekeeper初始化3.1. 默认时钟源3.2. tk_setup_internals3.3. 设置时间 4. timekeeping_update4.1. tk_update_ktime_data:tkr_mono和tkr_raw设置4.2. update_fast_timekeeper4.3. shadow_timekeeper 1. t…

matlab 梯度下降 求偏导,通过计算图求梯度下降中各偏导的推导

通过计算图求梯度下降中各偏导的推导 Author: nex3z 2017-08-30 在 Neural Networks and Deep Learning 课程的 Logistic Regression Gradient Descent 一节以逻辑回归为例,介绍了使用计算图(Computation Graph)求梯度下降中各偏导的方法,但没有给出具体…

matlab|求导数/最值

本博文源于matlab求导数求极值求最值,涉及内容极限命令求导/diff求导/一元函数一阶导数,多阶导数,求参数导数/函数极值和最值/不给定区间求最值 用极限命令求导 例子:求函数3sinx4x^2在x0处的导数 >> syms t; limit((3*…

matlab 梯度下降 求偏导,吴恩达机器学习课程课时12梯度下降算法中参数θ0,θ1求偏导...

最近学习吴恩达的机器学习课程。 看到了线性回归的梯度下降算法。课程中将了一个非常简单的线性回归: 比如给出一些房子的size和对应的price,我们可以建立一个模型(在此模型就是线性回归), 希望之后在给出任意一个房子的size,可以…

matlab求COPULA偏导,matlab note

Update date:2018-01-05 Matlab Note 1 vine-copula 1.1 xlsread() 打开xlsx里面的数据 S3CE xlsread(电表建模数据.xlsx,S3CE,‘G2:G52’) 1.2常见希腊发音总结 image.png 3.prob() 连乘 由于matlab中的元素是以矩阵为单位,prod(x)就是把x向量中所有元…

matlab求解多元函数的偏导数diff

本博文源于matlab求解多元函数导数。涉及求一阶/求多阶/求向量偏导数/求隐函数导数 多元函数的偏导数 diff(f(x,y,z),变量名)例子 求x^2lny根号z的偏导数 >> syms x >> syms y >> syms z >> du_dx diff(x^2log(y)sqrt(z),x)du_dx 2*x>> du_dz…

matlab实现隐函数求偏导数(impldiff函数)

目录 总述函数说明应用举例例1例2 函数实现 总述 由前面给出的算法,可以编写出如下函数来求解隐函数的偏导数。 函数说明 function dy impldiff(f, x, y, n) %impldiff %隐函数求导 % 调用格式: % f1 impldiff(f, x, y, n) % 其中:f…

matlab偏导数方程,利用Matlab求解不同类型的偏微分方程

来源:新浪了凡春秋的博客 在科学技术各领域中,有很多问题都可以归结为偏微分方程问题。在物理专业的力学、热学、电学、光学、近代物理课程中都可遇见偏微分方程。偏微分方程,再加上边界条件、初始条件构成的数学模型,只有在很特殊情况下才可求得解析解。随着计算机技术的发…

【MATLAB】求偏导数

目录 1、示例1 2、示例2 3、MATLAB求偏导数的应用 1、示例1 syms x y; z=(1+x*y)^y; zx=diff (z,’x’)

MATLAB求解偏导数

MATLAB具有多元函数求解偏导数的功能。 例: 1.函数关于x的二阶偏导数 syms x y >> z x^4y^4-4*x^2*y^2; >> zxx diff(z,x,2)zxx 12*x^2 - 8*y^2 2.函数关于y的二阶偏导数 zyy diff(z,y,2)zyy 12*y^2 - 8*x^2 3.函数二阶混合偏导数 zxy diff(dif…

MATLAB常用求导和求偏导函数

matlab求导命令diff调用格式: diff(函数) , 求的一阶导数;diff(函数, n) ,求的n阶导数(n是具体整数);diff(函数,变量名),求对的偏导数;diff(函数, 变量名,n)…

性能测试流程(完整版)

一、 规范性能测试实施流程的意义 规范的性能测试实施流程能够加强测试工作流程控制,明确性能测试各阶段应完成的工作,指导测试人员正确、有序的开展性能测试工作,提高各角色在性能能测试中的工作效率。本次分享的性能测试实施流程是性能测试…

性能测试流程相关

1、脚本制作流程 脚本制作方法可参考此链接:性能测试脚本实战_HealerLX的博客-CSDN博客 (1)抓包工具抓包 (2)录入到性能测试工具中 (3)调试脚本直到成功 (4)加上运行逻辑…