linux內核定時器

文章目錄

  • 一、jiffies定時器
    • 1.1 工作原理
    • 1.2 timer_list結構體
    • 1.3 相關接口
      • 1.3.1 初始化和啟動定時器
      • 1.3.2 修改定時器
      • 1.3.3 刪除定時器
      • 1.3.4 jiffies相關接口
  • 二、高精度定時器
    • 2.1 hrtimer結構體
    • 2.2 相關接口
      • 2.2.1 初始化和啟動定時器
      • 2.2.2 取消定時器
      • 2.2.3 通過定時器實現周期性任務

一、jiffies定時器

傳統定時器(基于jiffies)是Linux內核中最早和最基本的定時機制。jiffies是一個全局變量,它記錄了自系統啟動以來的“滴答數”(ticks)。每次時鐘中斷發生時,jiffies會增加。這個機制基于系統時鐘中斷的頻率,因此其精度受到時鐘頻率的限制。

1.1 工作原理

  1. 時鐘中斷:
    時鐘中斷是一個固定頻率的周期性中斷事件,每次時鐘中斷發生時,內核會增加jiffies的值;
    時鐘頻率通常由宏HZ定義,比如HZ=1000表示每秒發生1000次時鐘中斷(每毫秒一次);
  2. jiffies變量:
    jiffies是一個全局變量,用于記錄自系統啟動以來的時鐘中斷次數;
    在每次時鐘中斷處理過程中,內核會增加jiffies的值;

1.2 timer_list結構體

傳統定時器使用struct timer_list結構體來定義和管理定時器任務。

struct timer_list {struct hlist_node entry;unsigned long expires; // 定時器到期的jiffies值void (*function)(unsigned long); // 定時器回調函數unsigned long data; // 回調函數參數
};

1.3 相關接口

定時器相關接口定義在kernel\time\timer.c文件中。主要流程涉及以下接口。

1.3.1 初始化和啟動定時器

使用add_timer接口啟動定時器,參數是timer_list

void add_timer(struct timer_list *timer)

代碼示例:

#include <linux/timer.h>
#include <linux/jiffies.h>static struct timer_list my_timer;void my_timer_callback(unsigned long data)
{printk(KERN_INFO "Timer callback function called with data: %lu\n", data);
}void setup_timer(void)
{// 初始化定時器init_timer(&my_timer);my_timer.function = my_timer_callback;my_timer.data = 0; // 回調函數參數my_timer.expires = jiffies + HZ; // 1秒后到期// 添加定時器到內核add_timer(&my_timer);
}

類似的接口還有add_timer_on,該接口功能是在指定的cpu上啟動一個定時器:

void add_timer_on(struct timer_list *timer, int cpu)

1.3.2 修改定時器

使用mod_timer接口修改定時器的超時時間:

void my_timer_callback(unsigned long data)
{printk(KERN_INFO "Timer callback function called with data: %lu\n", data);// 如果需要周期性定時器, 使用mod_timer修改定時器超時時間mod_timer(&my_timer, jiffies + msecs_to_jiffies(500));
}

在上述定時器回調接口my_timer_callback中,調用mod_timer修改定時器的超時時間為500ms,這樣能給實現每隔500ms循環調用定時器超時回調接口。
mod_timer接口的功能相當于del_timer(timer); timer->expires = expires; add_timer(timer);,即刪除定時器、設置定時器超時時間、啟動定時器。

1.3.3 刪除定時器

使用del_timer接口刪除定時器:

del_timer(&my_timer);

1.3.4 jiffies相關接口

上述定時器單位是以jiffies為單位的,添加定時器和修改定時器的超時時間,都是以jiffies為單位的。下面介紹幾個常用的jiffies與其它時間單位轉化的接口:

static __always_inline unsigned long msecs_to_jiffies(const unsigned int m);
unsigned int jiffies_to_msecs(const unsigned long j);
static __always_inline unsigned long usecs_to_jiffies(const unsigned int u);
unsigned int jiffies_to_usecs(const unsigned long j);static inline unsigned long timespec_to_jiffies(const struct timespec *value);
static inline void jiffies_to_timespec(const unsigned long jiffies,struct timespec *value);unsigned long timeval_to_jiffies(const struct timeval *value);
void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value);

二、高精度定時器

傳統定時器的精度和實時性受限于系統的時鐘中斷頻率和調度機制;
相對于傳統定時器(jiffies),高精度定時器可以提供納秒級的定時精度,適用于實時應用、精確計時等需求;

2.1 hrtimer結構體

struct hrtimer {struct timerqueue_node node; // 定時器隊列節點ktime_t _softexpires;        // 定時器到期時間enum hrtimer_restart (*function)(struct hrtimer *); // 回調函數enum hrtimer_mode state;     // 定時器狀態clockid_t clock_id;          // 使用的時鐘類型
};

2.2 相關接口

2.2.1 初始化和啟動定時器

linux中,可以使用hrtimer_init接口初始化一個高精度定時器;
使用hrtimer_start接口啟動定時器;
示例代碼:

#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/init.h>static struct hrtimer my_hrtimer;enum hrtimer_restart my_timer_callback(struct hrtimer *timer)
{printk(KERN_INFO "High-Resolution Timer Callback\n");// 如果需要周期性定時器,重新啟動定時器hrtimer_forward_now(timer, ns_to_ktime(1000000000)); // 1秒return HRTIMER_RESTART;
}void setup_hrtimer(void)
{ktime_t ktime;// 初始化高精度定時器hrtimer_init(&my_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);my_hrtimer.function = &my_timer_callback;// 設置定時器到期時間ktime = ktime_set(0, 1000000000); // 1秒hrtimer_start(&my_hrtimer, ktime, HRTIMER_MODE_REL);
}

在示例代碼中,使用hrtimer_init初始化一個定時器,使用hrtimer_start接口設置定時器超時時間是 1s 并啟動定時器。

2.2.2 取消定時器

當模塊卸載或者不需要定時器時,使用hrtimer_cancel接口取消定時器:

ret = hrtimer_cancel(&my_hrtimer);

2.2.3 通過定時器實現周期性任務

在定時器回調函數接口中,使用hrtimer_start 重啟啟動定時器,或者使用hrtimer_forward_now 接口更新定時器的到期時間,都能夠實現周期性任務。

hrtimer_forward_now:將定時器的到期時間向前推進一個時間間隔;適合保持固定周期,即使回調函數的執行時間可能有波動。
hrtimer_start:重新啟動定時器,可以靈活地設置新的到期時間;適用于需要在每次回調函數中動態調整定時器時間的場景。

代碼示例:

enum hrtimer_restart my_timer_callback(struct hrtimer *timer)
{printk(KERN_INFO "High-Resolution Timer Callback\n");// 如果需要周期性定時器,重新啟動定時器// 方法一:hrtimer_forward_now(timer, ns_to_ktime(1000000000)); // 1秒// 方法二:hrtimer_start(&my_hrtimer, ktime, HRTIMER_MODE_REL);return HRTIMER_RESTART;
}

注意:

  • 雖然 hrtimer 提供納秒級的精度,但是實際精度受硬件和系統調度的影響,會導致定時器實際觸發的時間可能會有稍微的偏差;
  • 這就導致使用hrtimer_start接口實現周期性任務時,每次產生一些偏差,可能會產生累計誤差;
  • hrtimer_forward_now接口是在定時器當前這次理論到期時間基礎上,向前推進一個周期設置下次超時時間,所以不會有累積誤差。如果對周期性的時間準確性有要求,建議使用hrtimer_forward_now接口。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41359.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41359.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41359.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

shell-awk語法整理

shell-awk語法整理 前言基本語法內置變量1. $02. NF3. NR4. FS5. RS6. OFS7. ORS8. FILENAME9. FNR10. ARGV11. ENVIRON12. IGNORECASE13. RSTART 和 RLENGTH示例解釋 內置函數循環語句&#xff08;后面的;可不加&#xff09;條件語句高級特性示例 特殊模式BEGINEND組合示例BEG…

R語言實戰—圓形樹狀圖

話不多說&#xff0c;先看最終效果&#xff1a; 圓形樹狀圖是樹狀圖的一個變型&#xff0c;其實都是層次聚類。 接下來看代碼步驟&#xff1a; 首先要先安裝兩個包&#xff1a; install.packages("ggtree") install.packages("readxl") 咱就別問問什么…

29、php實現和為S的兩個數字(含源碼)

題目&#xff1a;php 實現 和為S的兩個數字 描述&#xff1a; 輸入一個遞增排序的數組和一個數字S&#xff0c;在數組中查找兩個數&#xff0c; 是的他們的和正好是S&#xff0c;如果有多對數字的和等于S&#xff0c;輸出兩個數的乘積最小的。 輸出描述&#xff1a; 對應每個測…

go zero入門

一、goctl安裝 goctl 是 go-zero 的內置腳手架&#xff0c;可以一鍵生成代碼、文檔、部署 k8s yaml、dockerfile 等。 # Go 1.16 及以后版本 go install github.com/zeromicro/go-zero/tools/goctllatest檢查是否安裝成功 $ goctl -v goctl version 1.6.6 darwin/amd64vscod…

vue2響應式原理+模擬實現v-model

效果 簡述原理 配置對象傳入vue實例 模板解析&#xff0c;遍歷出所有文本節點&#xff0c;利用正則替換插值表達式為真實數據 data數據代理給vue實例&#xff0c;以后通過this.xxx訪問 給每個dom節點增加觀察者實例&#xff0c;由觀察者群組管理&#xff0c;內部每一個鍵值…

sqlite 數據庫 介紹

文章目錄 前言一、什么是 SQLite &#xff1f;二、語法三、SQLite 場景四、磁盤文件 前言 下載 目前已經出到了&#xff0c; Version 3.46.0 SQLite&#xff0c;是一款輕型的數據庫&#xff0c;是遵守ACID的關系型數據庫管理系統&#xff0c;它包含在一個相對小的C庫中。它是…

VMware虛擬機配置橋接網絡

轉載&#xff1a;虛擬機橋接網絡配置 一、VMware三種網絡連接方式 VMware提供了三種網絡連接方式&#xff0c;VMnet0, VMnet1, Vmnet8&#xff0c;分別代表橋接&#xff0c;Host-only及NAT模式。在VMware的編輯-虛擬網絡編輯器可看到對應三種連接方式的設置&#xff08;如下圖…

美好生活的 100 條建議

簡介 一些簡潔明了的人生建議&#xff0c;易于理解&#xff0c;并且能夠為日常生活中的各個方面提供實用的指導。 財富 (Possessions) 1. If you want to find out about people’s opinions on a product, google \reddit. You’ll get real people arguing, as compared t…

SpringBoot2.2.6使用spring-boot-validation讀取不到自定義配置文件中的屬性

SpringBoot2.2.6沒有做message.properties文件中屬性的自動讀取配置。解決方法有兩種&#xff1a; 1. 升級springboot版本到2.6.x以上 2. 在現有springboot版本的基礎上添加以下自定義配置&#xff1a; Configuration public class RequestParamValidationConfig implements…

學習筆記——交通安全分析12

目錄 前言 當天學習筆記整理 4信控交叉口交通安全分析 結束語 前言 #隨著上一輪SPSS學習完成之后&#xff0c;本人又開始了新教材《交通安全分析》的學習 #整理過程不易&#xff0c;喜歡UP就點個免費的關注趴 #本期內容接上一期11筆記 當天學習筆記整理 4信控交叉口交…

ORA-03115 ORA-06594--空間不足 rman 磁帶壓縮備份 控制文件恢復后備份信息丟失

---用舊的控制文件恢復后 這個控制文件本身的備份信息不在此還原出的控制文件中。所以這個備份的控制文件就刪不掉&#xff0c;看不到。 但是只要設置正確的dbid&#xff0c;還是可以用恢復這個控制文件的 正常未恢復過controlfile的話&#xff0c;這個控制文件備份信息在現有…

Square Root SAM論文原理

文章目錄 Square Root SAM論文原理核心原理SLAM問題的3種表示貝葉斯網絡因子圖&#xff08;Factor graph&#xff09;馬爾科夫隨機場(Markov Random Field, MRF) SLAM最小二乘問題&線性化因式分解 factorization矩陣與圖(Matrices ? Graphs)因式分解&變量消元(Factori…

Kafka系列之Kafka知識超強總結

一、Kafka簡介 Kafka是什么 Kafka是一種高吞吐量的分布式發布訂閱消息系統&#xff08;消息引擎系統&#xff09;&#xff0c;它可以處理消費者在網站中的所有動作流數據。 這種動作&#xff08;網頁瀏覽&#xff0c; 搜索和其他用戶的行動&#xff09;是在現代網絡上的許多社…

14-22 劍和遠方2 - 深度神經網絡中的學習機制

概論 在第一部分中&#xff0c;我們深入探討了人工智能的興衰簡史以及推動人工智能發展的努力。我們研究了一個簡單的感知器&#xff0c;以了解其組件以及簡單的 ANN 如何處理數據和權重層。在簡單的 ANN 中&#xff0c;不會對數據執行特定操作。ANN 中的激活函數是一個線性函…

Surface splatting (2D Gaussian splatting)代碼分析

源碼地址 colab.research.google.com/drive/1qoclD7HJ3-o0O1R8cvV3PxLhoDCMsH8W 核心代碼 surface_splatting def surface_splatting(means3D, scales, quats, colors, opacities, intrins, viewmat, projmat):# Rasterization setupprojmat torch.zeros(4,4).cuda()projm…

flask使用定時任務flask_apscheduler(APScheduler)

Flask-APScheduler描述: Flask-APScheduler 是一個 Flask 擴展&#xff0c;增加了對 APScheduler 的支持。 APScheduler 有三個內置的調度系統可供您使用&#xff1a; Cron 式調度&#xff08;可選開始/結束時間&#xff09; 基于間隔的執行&#xff08;以偶數間隔運行作業…

c#中的超時終止

在C#中&#xff0c;可以使用CancellationToken和Task的超時機制來實現調用方法時的超時終止。 一 用Task.Delay(int)模擬耗時操作 static async Task Main(string[] args){using (var cts new CancellationTokenSource(1 * 1000)){await doSomething(cts.Token);}Console.Wr…

移動校園(7)ii:uniapp響應攔截器處理token,以及微信小程序報錯當前頁面正在處于跳轉狀態,請稍后再進行跳轉....

依據昨天的寫完&#xff0c;在token過期之后&#xff0c;再次調用接口&#xff0c;會觸發后端攔截&#xff0c;扔進全局錯誤處理中間件 前端說明提示都沒有&#xff0c;只有一個這個&#xff0c;現在優化一下&#xff0c;再寫一個類似全局后置守衛&#xff0c;當狀態碼是401的時…

RAID 冗余磁盤陣列

RAID也是Linux操作系統中管理磁盤的一種方式。 只有Linux操作系統才支持LVM的磁盤管理方式。 而RAID是一種通用的管理磁盤的技術&#xff0c;使用于多種操作系統。 優勢&#xff1a;提升數據的讀寫速度&#xff0c;提升數據的可靠性。具體實現哪什么功能&#xff0c;要看你所…

RGB樹-美團2023筆試(codefun2000)

題目鏈接 RGB樹-美團2023筆試(codefun2000) 題目內容 塔子哥是一位著名的冒險家&#xff0c;他經常在各種森林里探險。今天&#xff0c;他來到了道成林&#xff0c;這是一片美麗而神秘的森林。在探險途中&#xff0c;他遇到了一棵 n 個節點的樹&#xff0c;樹上每個節點都被涂…