色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux驅(qū)動開發(fā)-內(nèi)核定時器

DS小龍哥-嵌入式技術(shù) ? 2022-09-17 15:06 ? 次閱讀

【摘要】 內(nèi)核定時器是內(nèi)核用來控制在未來某個時間點(基于jiffies(節(jié)拍總數(shù)))調(diào)度執(zhí)行某個函數(shù)的一種機制,相關(guān)函數(shù)位于 和 kernel/timer.c 文件中。 當內(nèi)核定時器定時時間到達時,會進入用戶指定的函數(shù),相當于軟中斷。內(nèi)核定時器注冊開啟后,運行一次就不會再運行(相當于自動注銷),我們可以重新設(shè)置定時器的超時時間,讓定時器重復(fù)運行。

1. 內(nèi)核定時器介紹

內(nèi)核定時器是內(nèi)核用來控制在未來某個時間點(基于jiffies(節(jié)拍總數(shù)))調(diào)度執(zhí)行某個函數(shù)的一種機制,相關(guān)函數(shù)位于 和 kernel/timer.c 文件中。

當內(nèi)核定時器定時時間到達時,會進入用戶指定的函數(shù),相當于軟中斷。內(nèi)核定時器注冊開啟后,運行一次就不會再運行(相當于自動注銷),我們可以重新設(shè)置定時器的超時時間,讓定時器重復(fù)運行。

每當時鐘中斷發(fā)生時,全局變量jiffies(一個32位的unsigned long 變量)就加1,因此jiffies記錄了linux系統(tǒng)啟動后時鐘中斷發(fā)生的次數(shù),驅(qū)動程序常利用jiffies來計算不同事件間的時間間隔。內(nèi)核每秒鐘將jiffies變量增加HZ次。因此,對于HZ值為100的系統(tǒng),jiffy+1等于隔了10ms,而對于HZ為1000的系統(tǒng),jiffy+1僅為1ms。

內(nèi)核定時器結(jié)構(gòu)體:
下面列出了需要關(guān)心的成員

struct timer_list {
	unsigned long expires;         //設(shè)置超時時間,用jiffies作為基準值
	void (*function)(unsigned long); //類似中斷服務(wù)函數(shù),設(shè)置定時器到時后處理的函數(shù) 
	unsigned long data;           //中斷服務(wù)函數(shù)的參數(shù)
}

expires設(shè)置:以當前時間為基準加上延時時間,時間基準用jiffies變量表示,延時時間可以使用以下兩個宏轉(zhuǎn)換成jiffies單位。

2. 內(nèi)核定時器相關(guān)API函數(shù)

2.1 修改定時器超時時間

函數(shù)原型 *int mod_timer(struct timer_list timer, unsigned long expires)
函數(shù)功能 修改定時器超時時間
函數(shù)參數(shù) timer:對應(yīng)的定時器結(jié)構(gòu)體 expires:超時時間
函數(shù)返回值 成功返回 :修改成功的時間值
函數(shù)定義文件 \linux-3.5\kernel\timer.c

2.2 初始化定時器

函數(shù)原型 #define init_timer(timer)\
函數(shù)功能 初始化定時器結(jié)構(gòu)
函數(shù)參數(shù) timer:對應(yīng)的定時器結(jié)構(gòu)體
函數(shù)定義文件 \linux-3.5\include\linux\timer.h

2.3 關(guān)閉定時器

函數(shù)原型 int del_timer(struct timer_list *timer)
函數(shù)功能 關(guān)閉定時器,停用一個定時器。
函數(shù)參數(shù) timer:對應(yīng)的定 時器結(jié)構(gòu)體
函數(shù)返回值 返回0:成功
函數(shù)定義文件 \linux-3.5\include\linux\timer.h

2.4 關(guān)閉定時器

函數(shù)原型 int del_timer_sync(struct timer_list *timer)
函數(shù)功能 關(guān)閉定時器,停用一個定時器,多處理器使用。如果編內(nèi)核時不支持 SMP(多處理器), del_timer_sync()和 del_timer()等價
函數(shù)參數(shù) timer:對應(yīng)的定時器結(jié)構(gòu)體
函數(shù)返回值 返回0:成功
函數(shù)定義文件 \linux-3.5\include\linux\timer.h

2.5 轉(zhuǎn)換時間(微妙單位)

函數(shù)原型 unsigned long usecs_to_jiffies(const unsigned int m)
函數(shù)功能 轉(zhuǎn)換時間(微妙單位),用于填充定時器結(jié)構(gòu)體,設(shè)置超時時間
函數(shù)參數(shù) m:要轉(zhuǎn)換的時間值(微妙為單位)
函數(shù)返回值 成功返回轉(zhuǎn)換成功的時間。用于填充定時器結(jié)構(gòu)體,設(shè)置超時時間
函數(shù)定義文件 \linux-3.5\kernel\timer.c

2.6 轉(zhuǎn)換時間(毫秒為單位)

函數(shù)原型 unsigned long msecs_to_jiffies(const unsigned int m)
函數(shù)功能 轉(zhuǎn)換時間(毫秒為單位),用于填充定時器結(jié)構(gòu)體,設(shè)置超時時間
函數(shù)參數(shù) m:要轉(zhuǎn)換的時間值(毫秒為單位)
函數(shù)返回值 成功返回轉(zhuǎn)換成功的時間。用于填充定時器結(jié)構(gòu)體,設(shè)置超時時間
函數(shù)定義文件 \linux-3.5\kernel\timer.c

將jiffies單位轉(zhuǎn)為struct timespec結(jié)構(gòu)體表示:

Void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value);

示例:
jiffies_to_timespec(jiffies,&value);
printk("value.ts_sec=%d\n",value.tv_sec);
printk("value.tv_nsec=%d\n",value.tv_nsec);

2.7 初始化定時器的結(jié)構(gòu)體成員

TIMER_INITIALIZER( _function, _expires, _data) 宏用于賦值定時器結(jié)構(gòu)體的function、 expires、 data 和 base 成員, 這個宏的定義如下所示:(被DEFINE_TIMER宏調(diào)用)

#define TIMER_INITIALIZER(_function, _expires, _data) {		\
		.entry = { .prev = TIMER_ENTRY_STATIC },	\
		.function = (_function),			\
		.expires = (_expires),				\
		.data = (_data),				\
		.base = &boot_tvec_bases,			\
		.slack = -1,					\
		__TIMER_LOCKDEP_MAP_INITIALIZER(		\
			__FILE__ ":" __stringify(__LINE__))	\
	}

2.8 初始化定時器并且賦值

DEFINE_TIMER( _na me , _functi o n, _e x pires, _data) 宏是定義并初始化定時器成員的“快捷方式”, 這個宏定義如下所示:

/*初始化定時器,并進行賦值*/
#define DEFINE_TIMER(_name, _function, _expires, _data)		\
	struct timer_list _name =				\
		TIMER_INITIALIZER(_function, _expires, _data)

2.9 定時器初始化賦值

setup_timer()也可用于初始化定時器并賦值其成員, 其源代碼如下:

//初始化定時器并進行賦值
#define setup_timer(timer, fn, data)					\
	do {								\
		static struct lock_class_key __key;			\
		setup_timer_key((timer), #timer, &__key, (fn), (data));\
	} while (0)

static inline void setup_timer_key(struct timer_list * timer,
				const char *name,
				struct lock_class_key *key,
				void (*function)(unsigned long),
				unsigned long data)
{
	timer->function = function;
	timer->data = data;
	init_timer_key(timer, name, key);
}

3. 使用定時器的步驟

(1) 定義定時器結(jié)構(gòu)體timer_list。

/*定義一個內(nèi)核定時器配置結(jié)構(gòu)體*/
static struct timer_list mytimer ; 

(2) 設(shè)置超時時間,定義定時器處理函數(shù)和傳參。

mytimer.expires=jiffies+ msecs_to_jiffies(1000); /*設(shè)置定時器的超時時間,1000毫秒*/
//或者
//mytimer.expires=jiffies+HZ; /*設(shè)置定時器的超時時間,1000毫秒*/

mytimer.function = time_fun;	              /*定時器超時的回調(diào)函數(shù),類似中斷服務(wù)函數(shù)*/
mytimer.data = 12;                       /*傳給定時器服務(wù)函數(shù)的參數(shù)*/

(3) 開啟定時器。

init_timer(&mytimer);          /*初始化定時器*/
add_timer(&mytimer);	        /*啟動定時器*/

完整示例代碼:

#include 
#include 
#include 

static struct timer_list timer;

static void timer_function(unsigned long data)
{
	printk("data=%ld\n",data);
	mod_timer(&timer,msecs_to_jiffies(3000)+jiffies);
}

static int __init tiny4412_linux_timer_init(void)
{
	timer.expires=HZ*3+jiffies; /*單位是節(jié)拍*/
	timer.function=timer_function;
	timer.data=666;
	
	/*1. 初始化定時器*/
	init_timer(&timer);
	/*2. 添加定時器到內(nèi)核*/
	add_timer(&timer);
    printk("驅(qū)動測試: 驅(qū)動安裝成功\n");
    return 0;
}

static void __exit tiny4412_linux_timer_cleanup(void)
{
	/*3. 刪除定時器*/
	del_timer_sync(&timer);
    printk("驅(qū)動測試: 驅(qū)動卸載成功\n");
}

module_init(tiny4412_linux_timer_init);    /*驅(qū)動入口--安裝驅(qū)動的時候執(zhí)行*/
module_exit(tiny4412_linux_timer_cleanup); /*驅(qū)動出口--卸載驅(qū)動的時候執(zhí)行*/

MODULE_LICENSE("GPL");  /*設(shè)置模塊的許可證--GPL*/

4. 內(nèi)核提供的延時函數(shù)

Linux 內(nèi)核中提供了進行納秒、微秒和毫秒延遲。
void ndelay(unsigned long nsecs) ;
void udelay(unsigned long usecs) ;
void mdelay(unsigned long msecs) ;
上述延遲的實現(xiàn)原理本質(zhì)上是忙等待,根據(jù) CPU 頻率進行一定次數(shù)的循環(huán)。在內(nèi)核中,最好不要直接使用mdelay()函數(shù), 這將無謂地耗費CPU資源。
void msleep(unsigned int millisecs) ;
unsigned long msleep_interruptible(unsigned int millisecs) ;
void ssleep(unsigned int seconds) ;
上述函數(shù)將使得調(diào)用它的進程睡眠參數(shù)指定的時間, msleep()、 ssleep()不能被打斷,而 msleep_interruptible()則可以被打斷。

5. 精度較高的時間獲取方式

高精度定時器通常用ktime作為計時單位。
獲取內(nèi)核高精度時間單位: ktime_t ktime_get(void)

下面是一些時間輔助函數(shù)用于計算和轉(zhuǎn)換:

ktime_t ktime_set(const long secs, const unsigned long nsecs);   
ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs);   
ktime_t ktime_add(const ktime_t add1, const ktime_t add2);   
ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);   
ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec);   
ktime_t timespec_to_ktime(const struct timespec ts);   
ktime_t timeval_to_ktime(const struct timeval tv);   
struct timespec ktime_to_timespec(const ktime_t kt);   //轉(zhuǎn)換的時間通過timespec結(jié)構(gòu)體保存
struct timeval ktime_to_timeval(const ktime_t kt);     //轉(zhuǎn)換的時間通過timeval結(jié)構(gòu)體保存
s64 ktime_to_ns(const ktime_t kt);     //轉(zhuǎn)換為ns單位
int ktime_equal(const ktime_t cmp1, const ktime_t cmp2);   
s64 ktime_to_us(const ktime_t kt);    //轉(zhuǎn)換為us單位
s64 ktime_to_ms(const ktime_t kt);    //轉(zhuǎn)換為ms單位
ktime_t ns_to_ktime(u64 ns);

示例: 計算經(jīng)過的一段時間

static int hello_init(void)
{
	ktime_t my_time,my_time2;
	unsigned int i,j;
	unsigned int time_cnt=0;
	my_time=ktime_get();    		//獲取當前時間
	i=ktime_to_us(my_time); 		//轉(zhuǎn)us
	
	udelay(600);  				//延時一段時間
	
	my_time2=ktime_get();  	  	//獲取當前時間
	j=ktime_to_us(my_time2);  		//轉(zhuǎn)us
	
	printk("time_cnt=%ld\n",j-i); 	//得出之間差值,正確值為: 600
	return 0;
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1372

    瀏覽量

    40278
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3246

    瀏覽量

    114720
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4327

    瀏覽量

    62573
收藏 人收藏

    評論

    相關(guān)推薦

    定時器自動控制開關(guān)怎么設(shè)置

    的工作原理 定時器自動控制開關(guān)的工作原理基于時間控制。它通過內(nèi)部的計時來跟蹤時間,當達到預(yù)設(shè)的時間點時,定時器會發(fā)送信號給控制電路,從而驅(qū)動開關(guān)動作。這個過程可以分為以下幾個步驟:
    的頭像 發(fā)表于 09-19 16:19 ?1395次閱讀

    linux驅(qū)動程序如何加載進內(nèi)核

    Linux系統(tǒng)中,驅(qū)動程序是內(nèi)核與硬件設(shè)備之間的橋梁。它們允許內(nèi)核與硬件設(shè)備進行通信,從而實現(xiàn)對硬件設(shè)備的控制和管理。 驅(qū)動程序的編寫
    的頭像 發(fā)表于 08-30 15:02 ?444次閱讀

    Linux 驅(qū)動開發(fā)與應(yīng)用開發(fā),你知道多少?

    一、Linux驅(qū)動開發(fā)與應(yīng)用開發(fā)的區(qū)別開發(fā)層次不同:Linux
    的頭像 發(fā)表于 08-30 12:16 ?748次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>與應(yīng)用<b class='flag-5'>開發(fā)</b>,你知道多少?

    定時器的工作方式介紹

    定時器是計算機和嵌入式系統(tǒng)中常見的一種硬件模塊,用于實現(xiàn)定時和計數(shù)功能。定時器的工作方式通常由一組寄存來控制,這些寄存定義了
    的頭像 發(fā)表于 07-12 10:29 ?903次閱讀

    定時器相關(guān)的寄存有哪些類型

    在微控制編程中,定時器是一種非常常見的功能模塊,用于實現(xiàn)各種定時和計數(shù)功能。定時器的工作原理是通過內(nèi)部的計數(shù)來跟蹤時間的流逝,當計數(shù)
    的頭像 發(fā)表于 07-12 10:25 ?904次閱讀

    鴻蒙開發(fā)系統(tǒng)基礎(chǔ)能力:Timer定時器

    設(shè)置一個定時器,該定時器定時器到期后執(zhí)行一個函數(shù)。
    的頭像 發(fā)表于 06-28 11:33 ?986次閱讀
    鴻蒙<b class='flag-5'>開發(fā)</b>系統(tǒng)基礎(chǔ)能力:Timer<b class='flag-5'>定時器</b>

    如何實現(xiàn)一個軟件定時器

    Linux,uC/OS,F(xiàn)reeRTOS等操作系統(tǒng)中,都帶有軟件定時器,原理大同小異。典型的實現(xiàn)方法是:通過一個硬件定時器產(chǎn)生固定的時鐘節(jié)拍,每次硬件定時器中斷到,就對一個全局的時間
    的頭像 發(fā)表于 04-29 11:00 ?632次閱讀

    s7200定時器的五種故障介紹

    定時器或CPU故障:如果定時器本身或PLC的CPU出現(xiàn)故障,也可能導(dǎo)致定時器無法復(fù)位。此時,需要檢查定時器和CPU的工作狀態(tài),確保其正常運行。
    的頭像 發(fā)表于 04-03 17:08 ?2421次閱讀

    ?PLC定時器介紹

    定時器是PLC中重要的編程元件,是累計時間增量的內(nèi)部器件。大部分自動控制領(lǐng)域都需要定時器進行延時控制,靈活地使用定時器可以編制出復(fù)雜的控制程序。
    發(fā)表于 03-22 12:36 ?2330次閱讀
    ?PLC<b class='flag-5'>定時器</b>介紹

    使用555定時器的可調(diào)雙定時器電路

    定時器 IC 555 是最通用和最常用的 IC 之一,因為它的應(yīng)用范圍更廣,如 PWM放大器、延遲定時器、開關(guān)電路、占空比選擇、時鐘脈沖發(fā)生等。這也可用于各種應(yīng)用,如精確
    的頭像 發(fā)表于 02-25 15:16 ?2186次閱讀
    使用555<b class='flag-5'>定時器</b>的可調(diào)雙<b class='flag-5'>定時器</b>電路

    定時器原理能控制馬達嗎為什么

    定時器原理可以用于控制馬達。馬達是一種將電能轉(zhuǎn)換為機械能的設(shè)備,通常由電動機和傳動裝置組成。定時器是一種電子設(shè)備,用來生成和計時精確而穩(wěn)定的時間信號。通過將定時器與馬達控制電路相連,可以實現(xiàn)對馬達
    的頭像 發(fā)表于 01-23 15:21 ?662次閱讀

    555定時器的基本功能 555定時器的工作原理及其應(yīng)用

    555定時器是一種非常常見和常用的集成電路,它具有廣泛的應(yīng)用領(lǐng)域,例如計時、頻率分頻、脈沖寬度調(diào)制等。本文將詳細介紹555定時器的基本功能、工作原理以及應(yīng)用。 一、555定時器的基本功能 555
    的頭像 發(fā)表于 01-18 11:12 ?1.5w次閱讀

    AWTK 開源串口屏開發(fā)(6) - 定時器的用法

    定時器是個常用的功能,AWTK串口屏提供了豐富的定時器函數(shù),用于定時器的啟動、停止、暫停、恢復(fù)、修改和重置等功能,本文以計時的例子來介紹定時器
    的頭像 發(fā)表于 01-13 08:24 ?568次閱讀
    AWTK 開源串口屏<b class='flag-5'>開發(fā)</b>(6) - <b class='flag-5'>定時器</b>的用法

    AT32 定時器配置中pr和div的作用

    AT32定時器是51系列單片機中的一種定時器,可以實現(xiàn)多種定時功能。在AT32定時器中,pr和div是兩個相關(guān)的參數(shù),用于配置定時器的工作參
    的頭像 發(fā)表于 01-08 10:12 ?1297次閱讀

    單片機定時器的用法

    本章以CW32通用定時器為例介紹單片機定時器的用法。
    的頭像 發(fā)表于 01-04 10:37 ?1390次閱讀
    單片機<b class='flag-5'>定時器</b>的用法
    主站蜘蛛池模板: 粉色视频午夜网站入口| 手机免费毛片| 99视频在线观看免费| 美女露出逼| 92电影网午夜福利| 免费观看久久| mxgs-877痉挛媚药按摩| 欧洲精品一区二区不卡观看| bbwvideos欧美老妇| 青青国产在线观看视频| 村上里沙快播| 无限资源在线观看8| 国产三级在线观看视频| 亚洲spank男男实践网站| 黑人干肥婆| 与邻居换娶妻子2在线观看| 麻豆AV久久无码精品九九| 97免费人妻在线观看| 欧美一区二区在线观看| 大地影院免费观看视频| 午夜毛片在线观看| 果冻传媒色AV国产播放| 亚洲综合免费视频| 麻豆精品人妻一区二区三区蜜桃| 97视频精品| 色老板美国在线观看| 国产午夜精品久久久久婷婷| 亚洲精品在线不卡| 快穿之H啪肉| videosgrati欧美另类| 少妇无码吹潮久久精品AV| 国产亚洲tv在线观看| 一级毛片在线免费视频| 男女AA片免费| 国产不卡一卡2卡三卡4卡网站| 亚洲AV久久无码精品九号软件| 久久国产精品无码视欧美| 97在线精品视频| 色女仆影院| 黄得让人湿的片段| 99精品国产电影|