linux kernel时钟获取

这篇具有很好参考价值的文章主要介绍了linux kernel时钟获取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 概览

  你的百米记录是多少?你的千米赛跑记录是多少?你的爱车到达百公里每小时的时间是多少?在前一天晚上你就设置好了电饭煲,让其在第二天早上你醒来前就煮好粥。你的上下班点又是多少?你们又是如何和你的异性定好约会时间的?可见在人类社会中时间的概念是相当的重要。在linux的内核中也是如此,有时需要等待硬件一段时间以让其初始化完成。有时你需要在确定的几秒后来访问硬件,此时你的程序需要对比当前的时间点和开始等待的时间点间隔是否达到了要求值。

2. 每秒系统滴答次数–HZ

  HZ代表kernel的系统时钟每秒的产生的中断次数,例如HZ为250时,那么每秒系统时钟产生中断的间隔则是1/250s即4ms。其定义如下

//file:kernel/include/asm-generic/param.h
# define HZ		CONFIG_HZ	/* Internal kernel timer frequency */

  可见HZ由CONFIG_HZ定义,但是CONFIG_HZ则是编译时自动生成的,可以从.config中找到具体的值

//file:kernel/.config
CONFIG_HZ=250

  在代码中也可以直接打印出HZ的值,其代码如下

time_test_drv_init
    TIME_TEST_INFO("[HZ]%d[jiffies]%lu", HZ, jiffies);

  执行结果如下

[492257.266132] timeTest:time_test_drv_init,47:[HZ]250[jiffies]4417956623

3. 系统滴答记录–jiffies

  jiffies字面意思为时间量,其在内核中用于记录系统启动后系统滴答发生的次数,其定义如下

//file:kernel/arch/arm64/kernel/vmlinux.lds.S
jiffies = jiffies_64;
//kernel/include/linux/jiffies.h
extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;

4. jiffies时间对比API

4.1 time_before&&time_before_eq

  time_before用于对比两个时刻的jiffies值,其定义如下

//file:kernel/include/linux/jiffies.h
#define time_before(a,b)	time_after(b,a)

  作用也很简单,如果a时间点在b之前那么就返回true,否则返回false。在c中true也就是非零值,false则为零。对于 time_before_eq和time_before就是多了一层为真的条件,在a和b相等时也返回真值。示例代码如下

time_test_drv_init
    unsigned long delayTime = jiffies + HZ;//delay 1s
    time_before(jiffies, delayTime);

4.2 time_after&&time_after_eq

  time_after用于判断两个时刻jiffies值,其定义如下

//kernel/include/linux/jiffies.h
#define time_after(a,b)		\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)((b) - (a)) < 0))

  如果a的值在b之后,就返回true,否则返回false。time_after_eq也是多了一层为真的条件,在a和b相等时也会返回true。
  下面的代码判断展示以上的接口使用

time_test_drv_init
	TIME_TEST_INFO("time_after:[delayTime]%lu, [jiffies]%lu, [timer_after]%d, [time_before]%d",
					delayTime,
					jiffies,
					time_after(jiffies, delayTime),
					time_before(jiffies, delayTime));

  执行结果如下

[492257.266142] timeTest:time_test_drv_init,56:time_after:[delayTime]4417956873, [jiffies]4417956623, [timer_after]0, [time_before]1

5.内核时间的获取

  在我们的日常生活中所说的时间一般指的就是墙时间,但对于设备驱动来说墙时间显得不必要并且表示也更复杂,设备驱动中更在意的启动时间以及过去了多久。

5.1 ktime_get

   ktime_get 实际上获取的就是CLOCK_MONOTONIC时间,其在内核中的描述如下

Useful for reliable timestamps and measuring short time intervals accurately. 
Starts at system boot time but stops during suspend.

  通过ktime_get获取的时间是不统计设备休眠时间的,其返回值类型为ktime_t,单位为纳秒,并且这个时间统计的起始点则是设备启动后。其ktime_get和ktime_t的定义如下

//kernel/include/linux/ktime.h
/* Nanosecond scalar representation for kernel time values */
typedef s64	ktime_t;
//kernel/kernel/time/timekeeping.c
ktime_t ktime_get(void)
{
    ...
    return ktime_add_ns(base, nsecs);
}

  下面是接口使用的代码片段

time_test_drv_init
    ktime_t curTime = 0;
    curTime = ktime_get();
    TIME_TEST_INFO("ktime_get:%lld ns", curTime);

  下面是上面代码执行的结果

[492257.266149] timeTest:time_test_drv_init,63:ktime_get:492257307974640 ns

5.2 ktime_get_ts64

  ktime_get_ts64和ktime_get的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64,timespec64的定义如下

//kernel/include/linux/time64.h
struct timespec64 {
	time64_t	tv_sec;			/* seconds */
	long		tv_nsec;		/* nanoseconds */
};

  timespec64中包含了秒和纳秒,相对ktime_t纳秒这个时间表示更加适合人类查看,下面是接口使用的代码片段

static void show_time_ts64(const char* caller, const int line, const struct timespec64 *curTimeTs)
{
	pr_info("%s,%d:%lld s %ld ns\n", caller, __LINE__, curTimeTs->tv_sec, curTimeTs->tv_nsec);
}

time_test_drv_init
    struct timespec64 curTimeTs;
	ktime_get_boottime_ts64(&curTimeTs);
	show_time_ts64(__func__, __LINE__, &curTimeTs);

  下面是上面代码执行的结果

[492257.266159] timeTest:time_test_drv_init,36:492257 s 307981986 ns

5.3 ktime_get_boottime

  通过ktime_get_boottime获取的时间和ktime_get最大的不同是其包含了设备进入休眠的时间,其返回值类型为ktime_t,单位为纳秒,这个时间统计的起始点也是设备启动后。其定义如下

/**
 * ktime_get_boottime - Returns monotonic time since boot in ktime_t format
 *
 * This is similar to CLOCK_MONTONIC/ktime_get, but also includes the
 * time spent in suspend.
 */
static inline ktime_t ktime_get_boottime(void)
{
	return ktime_get_with_offset(TK_OFFS_BOOT);
}

  使用代码如下

time_test_drv_init
    ktime_t curTime = 0;
	curTime = ktime_get_boottime();
	TIME_TEST_INFO("ktime_get_boottime:%lld ns", curTime);

  执行结果如下

[492257.266168] timeTest:time_test_drv_init,73:ktime_get_boottime:581660801601637 ns

5.4 ktime_get_boottime_ts

  ktime_get_boottime_ts相对于ktime_get_boottime的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64,timespec64的解释见5.2。

5.5 ktime_get_real

  ktime_get_real获取的时间的起点不是设备的启动时间点了,而是相对UTC的。内核中的说明如下

Returns the time in relative to the UNIX epoch starting in 1970 using the 
Coordinated Universal Time (UTC), same as gettimeofday() user space. This 
is used for all timestamps that need to persist across a reboot, like inode times,
but should be avoided for internal uses, since it can jump backwards due to a leap
second update, NTP adjustment settimeofday() operation from user space.

  下面是该几口的使用示例

time_test_drv_init
    ktime_t curTime = 0;
    curTime = ktime_get_real();
	TIME_TEST_INFO("ktime_get_real:%lld ns", curTime);

  执行结果如下

[492257.266278] timeTest:time_test_drv_init,83:ktime_get_real:1646007269096922216 ns

  可见1970+(1646007269096922216ns) ~= 2022。

5.6 ktime_get_real_ts

  示例代码如下

time_test_drv_init
	struct timespec64 curTimeTs;
	ktime_get_real_ts64(&curTimeTs);

  执行结果如下

[492257.266285] timeTest:time_test_drv_init,36:1646007269 s 96929639 ns

6.完整源码如下

timeTest文章来源地址https://www.toymoban.com/news/detail-468936.html

https://gitee.com/solo-king/linux-kernel-base-usage/blob/master/flagstaff/timeTest.c

到了这里,关于linux kernel时钟获取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录--canvas 复刻锤子时钟

    canvas :使用脚本 (通常为 JavaScript) 来绘制图形的 HTML 元素。 本人遍历了以下两份文档,学习完就相当于有了笔和纸,至于最后能画出什么,则需要在 canvas 应用方面进一步学习。 MDN 的 Canvas 教程 1 张鑫旭的 Canvas API 中文文档 2 下面介绍如何使用 canvas 制作一个时钟,首先分析

    2024年02月14日
    浏览(20)
  • 【Linux Kernel】Linux内核裁剪

    目录 1. 内核简介 1.1 内核版本及特点 1.2 获取内核源码 1.3 内核启动过程简述 1.3.1 内核引导阶段 1.3.2 内核初始化阶段 2. 内核源码结构及Makefile分析 2.1 Linux内核Makefile分析 2.1.1决定编译那些文件 2.1.2 怎样编译这些文件 2.1.3 怎样链接这些文件 3. Kconfig分析 3.1 Kconfig文件的基本要

    2024年02月04日
    浏览(47)
  • ESP8266获取网络时间 实时时钟

    程序现象   1.发送指令AT+RST重启模块使应用模式更改生效; 2.发送指令ATE0取消回显 3.使用串口发送指令AT+CWMODE=1设置模块Wi-Fi应用模式为Station模式; 4.发送指令AT+CWJAP =\\\"ssid\\\",\\\"pwd\\\"连接AP; 5.发送指令AT+CIPMUX=0设置模块为单路连接模式,模块默认为单路连接模式; 6.发送指令AT+C

    2024年02月05日
    浏览(62)
  • STM32的RTC时钟的获取

    配置基本的参数:时钟、下载配置、串口(用于显示,记得重写fputc函数和使用微库Use MicroLIB) 生成keil程序后,首先找到rtc.c中的RTC_Init进行修改(如果不更改的话,会出现复位后出时间重新计算了) 内容如下(来自链接:https://blog.csdn.net/as480133937/article/details/105741893) 然后声

    2024年02月12日
    浏览(35)
  • rk3399移植linux kernel

    参考文章: 1.RK3399移植u-boot 2.I.MX6Q-SDB开发板移植ubuntu 3.Rockchip RK3399 - 移植ubuntu 20.04.4根文件系统 4.Rockchip RK3399 - 移植uboot 2023.04 linux 6.3   在前一节中移植了rk3399的u-boot,这一节就继续移植linux kernel。不过rk3399在移植kenel前,需要先制作根文件系统,这样才能在生成内核镜像

    2024年02月14日
    浏览(53)
  • CVE-2023-32233 Linux kernel

    近日,研究人员发现了Linux内核的NetFilter框架中的新漏洞(CVE-2023-32233)。该漏洞可被本地用户用于将权限提升为root,并完全控制系统。问题的根源在于 tfilter nf_tables 是如何处理批处理请求的,经过身份验证的本地攻击者可通过发送特制的请求破坏 Netfilter nf_tables 的内部状态

    2024年02月12日
    浏览(33)
  • ubuntu linux kernel内核操作

    1.内核编译前的准备工作 2.下载内核 4. 编译新内核 5. 内核安装 6. 安装模块 7. 生成initrd.img文件 8. 切换到/boot/grub/目录下,自动查找新内核,并添加至grub引导 9. 重启Ubantu,在previous version中选择启动新编译的内核 VMware虚拟机Ubantu20.04,Linux5.8.1内核源代码包 1.内核编译前的准备

    2024年02月19日
    浏览(42)
  • 【Linux内核】从0开始入门Linux Kernel源码

    🌈 博客个人主页 :Chris在Coding 🎥 本文所属专栏 :[Linux内核] ❤️  前置学习专栏 :[Linux学习]从0到1 ⏰  我们仍在旅途                                                                                    ​ 目录         前言--Linux内核简述         内核的

    2024年02月20日
    浏览(42)
  • vivado中的FPGA时钟管理单元PLL学习记录

    FPGA中时钟管理模块(CMT)包括PLL和MMCM,用于将时钟倍频(比如输入时钟25M,我们要产生50M时钟)、分频(在不影响系统功能的前提下,较低的工作时钟,能够降低系统功耗)、改变相位偏移或占空比等。 当需要上板时,由于板上晶振时钟固定,所以其他频率的时钟产生就要用到

    2024年01月16日
    浏览(48)
  • linux kernel:devres模块架构分析

    https://www.kernel.org/doc/html/latest/driver-api/driver-model/devres.html https://www.cnblogs.com/sammei/p/3498052.html devres in linux driver 相关文件: include/linux/device.h drivers/base/devres.c 初始数据结构图: struct device里面的devres_head 链表头,用于管理devres 相关文件:drivers/pinctrl/core.c 该文件中只使用了如下

    2024年02月02日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包