Linux内核编程——内核定时器

在Linux UWB Stack的内核模块实现中,较多的使用了内核定时器,本文基于fake MCPS实现中的应用为背景,介绍了内核定时器的使用。

1. 内核定时器

  Linux内核用来控制在未来某个时间点【基于jiffies(节拍总数)】调度执行某个函数的一种机制,相关函数位于 <linux/timer.h> 和 <kernel/timer.c> 文件中。
  当内核定时器定时时间到达时,会进入用户指定的函数,相当于软中断。内核定时器注册开启后,运行一次就不会再运行(相当于自动注销),我们可以重新设置定时器的超时时间,让定时器重复运行。
  每当时钟tick中断发生时,全局变量jiffies(一个32位的unsigned long 变量)就加1,因此jiffies记录了linux系统启动后时钟中断发生的次数,驱动程序常利用jiffies来计算不同事件间的时间间隔。内核每秒钟将jiffies变量增加HZ次。因此,对于HZ值为100的系统,jiffy+1等于隔了10ms,而对于HZ为1000的系统,jiffy+1仅为1ms。

内核定时器使用

首先需要创建一个struct timer_list实例,并通过timer_setup设置定时器的超时处理函数,并启动。

static struct timer_list g_timer;void timer_setup(struct timer_list *timer, void (*callback)(struct timer_list *), unsigned int flags);

timer_setup函数的实现相对比较简单:

void timer_setup(struct timer_list *timer, void (*callback)(struct timer_list *), unsigned int flags)
{memset(timer, 0, sizeof(*timer));INIT_LIST_HEAD(&timer->entry);timer->function = callback;timer->flags = flags;
}

2)定时器设置好之后,配置超时时间启动定时器

// 设置定时器的超时时间,在全局jiffies变量基础上增加,jiffies与系统设置的HZ相关
void mod_timer(struct timer_list *timer, unsigned long expires);

这样,定时器在设置的超时时间到之后,运行用户设定的函数(callback),若要保证周期性的运行,则可以在周期函数中,重复设置定时器的超时时间。

void del_timer(struct timer_list * timer);

del_timer 函数用于删除一个已经激活的定时器。其中,timer 是一个指向定时器结构体的指针。如果定时器已经被取消或者还未被激活,则不会有任何操作。在删除定时器之后,定时器的定时操作也会被取消。

关于内核定时器时间转换

//将输入的微秒时间转换为jiffies单位
unsigned long usecs_to_jiffies(const unsigned int m);
//将输入的毫秒时间转换为jiffies单位
unsigned long msecs_to_jiffies(const unsigned int m);

相反的,也可以将jiffies单位的时间转换为struct timespec的时间单位。

void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)struct timespec {time_t tv_sec;  // 秒数long tv_nsec;   // 纳秒数
};

2. 内核定时器应用——fake MCPS实现

在uwb stack的mcps802154_fake.c的fake MCPS实现代码如下:

static struct timer_list g_timer;
// 1s = 1000 ms
static const int g_time_interval = 1000;// 周期任务,在每次任务中,重新设定定时器的超时时间
static void periodic_task(struct timer_list *unused)
{// .../*Restarting the timer...*/mod_timer(&g_timer, jiffies + msecs_to_jiffies(g_time_interval));if (rx_enabled) {rx_enabled = false;mcps802154_rx_frame(driver_llhw);}if (tx_queued) {tx_queued = false;mcps802154_tx_done(driver_llhw);}
}static int __init fake_init(void)
{int r;pr_info("fake_mcps: init\n");// 分配底层硬件驱动driver_llhw = mcps802154_alloc_llhw(0, &fake_ops);if (driver_llhw == NULL) {return -ENOMEM;}// ...// mcps802154注册底层硬件驱动r = mcps802154_register_llhw(driver_llhw);if (r) {mcps802154_free_llhw(driver_llhw);driver_llhw = NULL;return r;}// 设置定时器,启动周期定时器timer_setup(&g_timer, periodic_task, 0);mod_timer(&g_timer, jiffies + msecs_to_jiffies(g_time_interval));return 0;
}static void __exit fake_exit(void)
{pr_info("fake_mcps: Exit\n");// 注销及释放底层硬件驱动mcps802154_unregister_llhw(driver_llhw);mcps802154_free_llhw(driver_llhw);driver_llhw = NULL;/*Deleting the timer aka the periodic task.*/stop_timer = true;del_timer(&g_timer);
}module_init(fake_init);
module_exit(fake_exit);

通过fake_init完成必要的mcps802154相关的注册,同时设置内核定时器,周期性的启动模拟的收发操作。
模块退出时,通过fake_exit函数进行注销,删除已经激活的定时器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【安鸾靶场】实战渗透

文章目录 前言一、租房网 (150分)二、企业网站 (300分)三、SQL注入进阶 (550分) 前言 最近看到安鸾的靶场有些比较有意思就打了一下午&#xff0c;有一定难度。 一、租房网 (150分) http://106.15.50.112:8031/ 刚打开burp就报了thinkphp的代码执行 直接getshell flag&a…

华为云云耀云服务器L实例评测|基于canal缓存自动更新流程 SpringBoot项目应用案例和源码

前言 最近华为云云耀云服务器L实例上新&#xff0c;也搞了一台来玩&#xff0c;期间遇到各种问题&#xff0c;在解决问题的过程中学到不少和运维相关的知识。 在之前的博客中&#xff0c;介绍过canal的安装和配置&#xff0c;参考博客 拉取创建canal镜像配置相关参数 & …

【Java】HashMap 背诵版

HashMap 背诵版 1. HashMap、Hashtable 和 ConcurrentHashMap 的区别&#xff1f;1.1 线程安全&#xff1a;1.2 继承关系&#xff1a;1.3 允不允许null值&#xff1a; 2. HashMap 的数据结构2.1 什么是hash表&#xff1f;2.2 HashMap 的数据结构 3. 什么是hash冲突&#xff0c;…

1.1.OpenCV技能树--第一单元--OpenCV简介

目录 1.文章内容来源 2.OpenCV简介 3.课后习题代码复现 4.易错点总结与反思 1.文章内容来源 1.题目来源:https://edu.csdn.net/skill/practice/opencv-77f629e4593845b0bf97e74ca8ec95ae/8292?languageopencv&materialId20807 2.资料来源:https://edu.csdn.net/skill…

Go 复合数据类型之结构体与自定义类型

Go 复合数据类型之结构体与自定义类型 文章目录 Go 复合数据类型之结构体与自定义类型一、类型别名和自定义类型1.1 类型定义&#xff08;Type Definition&#xff09;简单示例 1.2 类型别名简单示例 1.3 类型定义和类型别名的区别 二、结构体2.1 结构体介绍2.2 结构体的定义2.…

day-65 代码随想录算法训练营(19)图论 part 04

463.岛屿的周长 分析&#xff1a; 1.陆地的旁边是海面&#xff0c;存在周长2.陆地在边界上&#xff0c;存在周长 思路一&#xff1a;深度优先遍历 1.通过记录访问情况来访问数据 class Solution { public:int direct[4][2]{{0,1},{0,-1},{1,0},{-1,0}};int res0;void dfs(…

集群服务器

文章目录 项目名:实现集群服务器技术栈通过这项目你学到(或者复习到)实现功能编码环境json环境muduo库boost库MySql数据库登录mysql&#xff1a;查看mysql服务开启了没有&#xff1f;mysql的服务器及开发包库chat&#xff0c;表 allgroup friend groupuser offlinemessage user…

从零开始学习线性回归:理论、实践与PyTorch实现

文章目录 &#x1f966;介绍&#x1f966;基本知识&#x1f966;代码实现&#x1f966;完整代码&#x1f966;总结 &#x1f966;介绍 线性回归是统计学和机器学习中最简单而强大的算法之一&#xff0c;用于建模和预测连续性数值输出与输入特征之间的关系。本博客将深入探讨线性…

面试题: Spring中Bean的实例化和Bean的初始化有什么区别?

Spring中Bean的实例化和Bean的初始化有什么区别? 背景答案扩展知识什么是实例化什么是初始化 个人评价我的回答 背景 想换工作, 看了图灵周瑜老师的视频想记录一下, 算是学习结果的一个输出. 答案 Spring 在创建一个Bean对象时, 会先创建出一个Java对象, 会通过反射来执行…

Mac上protobuf环境构建-java

参考文献 getting-started 官网pb java介绍 maven protobuf插件 简单入门1 简单入门2 1. protoc编译器下载安装 https://github.com/protocolbuffers/protobuf/releases?page10 放入.zshrc中配置环境变量  ~/IdeaProjects/test2/ protoc --version libprotoc 3.12.1  …

Javascript文件上传

什么是文件上传 文件上传包含两部分&#xff0c; 一部分是选择文件&#xff0c;包含所有相关的界面交互。一部分是网络传输&#xff0c;通过一个网络请求&#xff0c;将文件的数据携带过去&#xff0c;传递到服务器中&#xff0c;剩下的&#xff0c;在服务器中如何存储&#xf…

基于SpringBoot的电影评论网站

目录 前言 一、技术栈 二、系统功能介绍 电影信息管理 电影评论回复 电影信息 用户注册 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了电影评…

Redisson—分布式集合详述

7.1. 映射&#xff08;Map&#xff09; 基于Redis的Redisson的分布式映射结构的RMap Java对象实现了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。与HashMap不同的是&#xff0c;RMap保持了元素的插入顺序。该对象的最大容量受Redis限制&#xff0c;最大元素数…

Pyhon-每日一练(1)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Vue中如何进行分布式路由配置与管理

Vue中的分布式路由配置与管理 随着现代Web应用程序的复杂性不断增加&#xff0c;分布式路由配置和管理成为了一个重要的主题。Vue.js作为一种流行的前端框架&#xff0c;提供了多种方法来管理Vue应用程序的路由。本文将深入探讨在Vue中如何进行分布式路由配置与管理&#xff0…

OpenWRT、Yocto 、Buildroot和Ubuntu有什么区别

OpenWRT&#xff1a; 用途&#xff1a;OpenWRT 是一个专注于路由器和嵌入式网络设备的Linux发行版。它提供了一个优化的Linux环境&#xff0c;旨在将网络设备变成功能丰富、高度可定制的路由器。 包管理器&#xff1a;OpenWRT 使用 opkg 包管理器&#xff0c;它是一个轻量级的…

Spring Boot中的@Controller使用教程

一 Controller使用方法&#xff0c;如下所示&#xff1a; Controller是SpringBoot里最基本的组件&#xff0c;他的作用是把用户提交来的请求通过对URL的匹配&#xff0c;分配个不同的接收器&#xff0c;再进行处理&#xff0c;然后向用户返回结果。下面通过本文给大家介绍Spr…

linux内核分析:虚拟化

https://www.cnblogs.com/wujuntian/p/16294898.html 三种虚拟化方式 1. 对于虚拟机内核来讲,只要将标志位设为虚拟机状态,我们就可以直接在 CPU 上执行大部分的指令,不需要虚拟化软件在中间转述,除非遇到特别敏感的指令,才需要将标志位设为物理机内核态运行,这样大大…

minio分布式文件存储

基本介绍 什么是 MinIO MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。基于 Apache License v2.0 开源协议&#xff0c;虽然轻量&#xff0c;却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应…

Java方法:重复使用的操作可以写成方法哦

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、方法的概念1、什么是方法&#xff1f;2、方法的定义3、方法调用的过程 二、方法重载1、重载的概念2、方法签名 在日常生活中…