色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > linux內(nèi)核時(shí)間管理

linux內(nèi)核時(shí)間管理 時(shí)間:2017-11-23      來(lái)源:未知

前言:

Linux中如何對(duì)時(shí)間進(jìn)行管理?時(shí)鐘節(jié)拍的概念及延時(shí)函數(shù)的用法很多同學(xué)都用不好,下面我給大家總結(jié)一下。

 

一,linux時(shí)鐘運(yùn)作機(jī)制

1,linux時(shí)鐘運(yùn)作機(jī)制

• 大部分PC機(jī)中有兩個(gè)時(shí)鐘源,分別是實(shí)時(shí)時(shí)鐘(RTC)和 操作系統(tǒng)(OS)時(shí)鐘

• 實(shí)時(shí)時(shí)鐘也叫CMOS時(shí)鐘,它靠電池供電,即使系統(tǒng)斷電,也可以維持日期和時(shí)間。

• RTC和OS時(shí)鐘之間的關(guān)系通常也被稱(chēng)作操作系統(tǒng)的時(shí)鐘運(yùn)作機(jī)制

• 不同的操作系統(tǒng),其時(shí)鐘運(yùn)作機(jī)制也不同

linux中的時(shí)鐘機(jī)制大致如下圖所示

linux中時(shí)鐘機(jī)制

由上圖可知:

RTC是硬件時(shí)鐘,它為整個(gè)計(jì)算機(jī)提供一個(gè)計(jì)時(shí)標(biāo)準(zhǔn),是原始底層的時(shí)鐘數(shù)據(jù),由紐扣電池供電,系統(tǒng)斷電后仍然在工作

OS時(shí)鐘產(chǎn)生于PC主板上的定時(shí)/計(jì)數(shù)芯片,由操作系統(tǒng)控制這個(gè)芯片的工作,OS時(shí)鐘的基本單位就是該芯片的計(jì)數(shù)周期,開(kāi)機(jī)時(shí)操作系統(tǒng)取得RTC中的時(shí)間數(shù)據(jù)來(lái)初始化OS時(shí)鐘,所以它只是在開(kāi)機(jī)有效,由操作系統(tǒng)控制,已被稱(chēng)為軟時(shí)鐘或系統(tǒng)時(shí)鐘。操作系統(tǒng)通過(guò)OS時(shí)鐘提供給應(yīng)用程序和時(shí)間有關(guān)的服務(wù)。

擴(kuò)展:OS時(shí)鐘其本質(zhì)是一個(gè)計(jì)數(shù)器,計(jì)數(shù)器從計(jì)數(shù)初值開(kāi)始,每收到一次脈沖信號(hào),計(jì)數(shù)器減1,當(dāng)減至0時(shí),就會(huì)輸出高電平或低電平,然后獲取重載值重新從初值開(kāi)始計(jì)數(shù),不斷循環(huán),這樣就得到一個(gè)輸出脈沖,這個(gè)脈沖作用中斷控制器上,產(chǎn)生中斷信號(hào),觸發(fā)時(shí)鐘中斷。

 

2,OS時(shí)鐘中斷

 

• OS時(shí)鐘是由可編程定時(shí)/計(jì)數(shù)器產(chǎn)生的輸出脈沖觸發(fā)中斷而產(chǎn)生的,而輸出脈沖的周期叫做一個(gè)“時(shí)鐘節(jié)拍”(Tick,又稱(chēng)滴答),(中斷觸發(fā)時(shí)會(huì)進(jìn)入中斷處理函數(shù),使jiffies+1)

• 操作系統(tǒng)的“時(shí)間基準(zhǔn)” 由設(shè)計(jì)者決定,Linux的時(shí)間基準(zhǔn)是1970年1月1日凌晨0點(diǎn)

• OS時(shí)鐘記錄的時(shí)間就是系統(tǒng)時(shí)間。系統(tǒng)時(shí)間以“時(shí)鐘節(jié)拍”為單位

•時(shí)鐘中斷觸發(fā)的頻率,由內(nèi)核HZ來(lái)確定,系統(tǒng)啟動(dòng)時(shí)會(huì)按照定義的HZ值對(duì)硬件進(jìn)行設(shè)置

比如對(duì)HZ的定義如下:

#define  Hz 100      

內(nèi)核時(shí)間頻率:表示每秒鐘觸發(fā)100次時(shí)鐘中斷,即每10ms觸發(fā)一次,

   每次中斷jiffies+1,,則每秒jiffies增加了100,

 

• Linux中用全局變量 jiffies表示系統(tǒng)自啟動(dòng)以來(lái)的時(shí)鐘節(jié)拍數(shù)目(時(shí)鐘中斷觸發(fā)的次數(shù))

   因此系統(tǒng)運(yùn)行的時(shí)間以s為單位計(jì)數(shù),  就等于 jiffies/HZ

   內(nèi)核啟動(dòng)時(shí)將該變量初始化為0,此后,每次時(shí)鐘中斷處理程序都會(huì)增加該變量的值,每秒鐘觸發(fā)中斷的次數(shù)為Hz, 

 

3、實(shí)際時(shí)間

 

實(shí)際時(shí)間就是現(xiàn)實(shí)中鐘表上顯示的時(shí)間,其實(shí)內(nèi)核中并不常用這個(gè)時(shí)間,主要是用戶(hù)空間的程序有時(shí)需要獲取當(dāng)前時(shí)間,所以?xún)?nèi)核中也管理著這個(gè)時(shí)間。

實(shí)際時(shí)間的獲取是在開(kāi)機(jī)后,內(nèi)核初始化時(shí)從RTC讀取的。

內(nèi)核讀取這個(gè)時(shí)間后就將其放入內(nèi)核中的 xtime 變量中,并且在系統(tǒng)的運(yùn)行中不斷更新這個(gè)值。

 

當(dāng)前實(shí)際時(shí)間(墻上時(shí)間):  xtime.tv_sec以秒為單位,存放著自1970年7月1日(UTC)以來(lái)經(jīng)過(guò)的時(shí)間,1970年1月1日被稱(chēng)為紀(jì)元。多數(shù)Unix系統(tǒng)的墻上時(shí)間都是基于該紀(jì)元而言的。xtime.tv_nsec記錄自上一秒開(kāi)始經(jīng)過(guò)的納秒數(shù)。

在<Time.h(incluce/linux)>中 

extern struct timespec xtime; 

#ifndef _STRUCT_TIMESPEC 

#define _STRUCT_TIMESPEC 

struct timespec {      /*高精度*/

     time_t  tv_sec;     /* seconds */ 

    long    tv_nsec;    /* nanoseconds 納秒*/ 

}; 

     #endif

 從用戶(hù)空間取得墻上時(shí)間的主要接口是gettimeofday(),在內(nèi)核中對(duì)應(yīng)的系統(tǒng)調(diào)用為sys_gettimeofday():

雖然內(nèi)核也實(shí)現(xiàn)了time()系統(tǒng)調(diào)用,但是gettimeofday()幾乎完全取代了它。C庫(kù)函數(shù)也提供了墻上時(shí)間相關(guān)的庫(kù)調(diào)用,比如ftime(),ctime()。

  除了更新xtime時(shí)間外,內(nèi)核不會(huì)想用戶(hù)空間程序那樣頻繁的使用xtime。但是,在文件系統(tǒng)的實(shí)現(xiàn)代碼中存放訪(fǎng)問(wèn)時(shí)間戳(創(chuàng)建,存取,修改等)需要使用xtime。

 

4,時(shí)鐘中斷處理程序----操作系統(tǒng)的脈搏

 

每一次時(shí)鐘中斷的產(chǎn)生都觸發(fā)下列幾個(gè)主要的操作:

– 給jiffies變量加 1

– 更新時(shí)間和日期,既更新xtime墻上時(shí)間

– 確定當(dāng)前進(jìn)程在CPU 上已運(yùn)行了多長(zhǎng)時(shí)間,如果已經(jīng)超過(guò)了分配給它的時(shí)間,則搶占它

– 更新資源使用統(tǒng)計(jì)數(shù)

– 檢查定時(shí)器時(shí)間間隔是否已到,如果是,則執(zhí)行它注冊(cè)的函數(shù)(運(yùn)行于底半部軟中斷中)

 

 以上工作每秒要發(fā)生 Hz次,也就是說(shuō)PC上的時(shí)鐘中斷處理程序執(zhí)行的頻率為Hz

 

5、時(shí)間系統(tǒng)總結(jié)

1、節(jié)拍----->jiffies

     又稱(chēng)時(shí)鐘滴答,是一個(gè)全局變量,它的值在系統(tǒng)引導(dǎo)的時(shí)候初始化為0,在時(shí)鐘中斷初始化完成后,每次時(shí)鐘中斷發(fā)生,在時(shí)鐘中斷處理例程中都會(huì)將jiffies的值 +1。

     jiffies_64:為了解決jiffies溢出問(wèn)題,更重要的是通過(guò)jiffies_64可以知道自開(kāi)機(jī)以來(lái)的時(shí)間間隔。

2、節(jié)拍率---->HZ

     HZ表示時(shí)鐘中斷發(fā)生的頻率。可以在.config的配置文件中改寫(xiě)。1/HZ是每個(gè)jiffies+1的時(shí)間間隔。

3、通過(guò)jiffies可以進(jìn)行時(shí)間的比較和時(shí)間轉(zhuǎn)換

4、時(shí)間比較

     32位                                                    64位

     time_after(a,b)                                    time_after64(a,b)

     time_before(a,b)                                 time_before64(a,b)

     time_after_eq(a,b)                              time_after_eq64(a,b)

     time_before_eq(a,b)                           time_before_eq64

     time_in_range(a,b,c)                           time_in_range(a,b,c)

5、時(shí)間轉(zhuǎn)換

     a、jiffies和msecs以及usecs的轉(zhuǎn)換:

     unsigned int jiffies_to_msecs(const unsigned long);

     unsigned int jiffies_to_usecs(const unsigned long);

     unsigned long msecs_to_jiffies(const unsigned int m);

     unsigned long usecs_to_jiffies(const unsigned int u);

 

    b、jiffies和timespec以及timeval的轉(zhuǎn)換

     在用戶(hù)空間,應(yīng)用程序更多的使用秒以及毫秒等時(shí)間形式,而在內(nèi)核中多使用jiffes。

     內(nèi)核定義了struct timeval 和 struct timespec 兩種數(shù)據(jù)結(jié)構(gòu)

     struct timespec {

               __kernel_time_t tv_sec;

               long              tv_nsec;

      }

     struct timeval {

               __kernel_time_t          tv_sec;

              __kernel_suseconds_t  tv_usec;

    }

    相互轉(zhuǎn)換函數(shù):

     unsigned long timespec_to_jiffies(const struct timespec *value);

     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);

 

6、要注意的是jiffies的精度問(wèn)題。如果HZ = 1000,則jiffies增加1代表1ms。

     如果要用到更高精度的始終,要用其他的硬件機(jī)制。

 

 

二、內(nèi)核短延時(shí)

 

Linux內(nèi)核中提供了下列3個(gè)函數(shù)以分別進(jìn)行納秒、微秒和毫秒延遲:

 

void ndelay(unsigned long nsecs);

void udelay(unsigned long usecs);

void mdelay(unsigned long msecs);

 

上述延遲的實(shí)現(xiàn)原理本質(zhì)上是忙等待,它根據(jù)CPU頻率進(jìn)行一定次數(shù)的循環(huán)。如果沒(méi)有特殊的理由(比如在中斷上下文中獲取自旋鎖的情況),不推薦使用這些函數(shù)延遲較長(zhǎng)的時(shí)間,浪費(fèi)CPU。

注:ndelay 和 mdelay都是基于udelay,將udelay的次數(shù)除1000就是ndelay,因此ndelay的次數(shù)為1000的整數(shù)倍才準(zhǔn)確。

 

 

有時(shí)候,人們?cè)谲浖羞M(jìn)行下面的延遲:

void delay(unsigned int time)

{

while(time--);

}

ndelay()、udelay()和mdelay()函數(shù)的實(shí)現(xiàn)方式原理與此類(lèi)似。

內(nèi)核在啟動(dòng)時(shí),會(huì)運(yùn)行一個(gè)延遲循環(huán)校準(zhǔn)(Delay Loop Calibration),計(jì)算出lpj(Loops Per Jiffy)即處理器在一個(gè)jiffy時(shí)間內(nèi)運(yùn)行一個(gè)內(nèi)部的延遲循環(huán)的次數(shù),內(nèi)核啟動(dòng)時(shí)會(huì)打印如下類(lèi)似信息:

Calibrating delay loop... 530.84 BogoMIPS (lpj=1327104)

如果我們直接在bootloader傳遞給內(nèi)核的bootargs中設(shè)置lpj=1327104,則可以省掉這個(gè)校準(zhǔn)的過(guò)程節(jié)省約百毫秒級(jí)的開(kāi)機(jī)時(shí)間。

 

睡著延時(shí)

毫秒時(shí)延(以及更大的秒時(shí)延)已經(jīng)比較大了,在內(nèi)核中,好不要直接使用mdelay()函數(shù),這將耗費(fèi)CPU資源,對(duì)于毫秒級(jí)以上的時(shí)延,內(nèi)核提供了下述函數(shù):

 

void msleep(unsigned int millisecs);

unsigned long   msleep_interruptible(unsigned int millisecs);

void ssleep(unsigned int seconds);

 

上述函數(shù)將使得調(diào)用它的進(jìn)程睡眠參數(shù)指定的時(shí)間為millisecs,msleep()、ssleep()不能被打斷,而msleep_interruptible()則可以被打斷。

受系統(tǒng)Hz以及進(jìn)程調(diào)度的影響,msleep()類(lèi)似函數(shù)的精度是有限的。

 

三、內(nèi)核長(zhǎng)延時(shí)

在內(nèi)核中,一個(gè)直觀的延時(shí)的方法是將所要延遲的時(shí)間設(shè)置的當(dāng)前的jiffies加上要延遲的時(shí)間,這樣就可以簡(jiǎn)單的通過(guò)比較當(dāng)前的jiffies和設(shè)置的時(shí)間來(lái)判斷延時(shí)的時(shí)間時(shí)候到來(lái)。針對(duì)此方法,內(nèi)核中提供了簡(jiǎn)單的宏用于判斷延時(shí)是否完成。

 

time_after(a,b);         /*如果時(shí)間a在b之后 (a>b),則返回真,否則返回0*/

time_before(a,b);      /*如果時(shí)間a在b之前 (a<b),則返回真,否則返回0*/

 

長(zhǎng)延時(shí)實(shí)現(xiàn)舉例:

/* 延遲 100 個(gè) jiffies */

unsigned long delay = jiffies + 100;

while(time_before(jiffies, delay));

 

/* 再延遲 2s */

unsigned long delay = jiffies + 2*Hz;

while(time_before(jiffies, delay));

 

與time_before()對(duì)應(yīng)的還有一個(gè)time_after(),它們?cè)趦?nèi)核中定義為(實(shí)際上只是將傳入的未來(lái)時(shí)間jiffies和被調(diào)用時(shí)的jiffies進(jìn)行一個(gè)簡(jiǎn)單的比較):

#define time_after(a,b) \

(typecheck(unsigned long, a) && \

typecheck(unsigned long, b) && \

((long)(b) - (long)(a) < 0))

 

#define time_before(a,b) time_after(b,a)

 

 

為了防止在time_before()和time_after()的比較過(guò)程中編譯器對(duì)jiffies的優(yōu)化,內(nèi)核將其定義為

volatile變量,這將保證每次都會(huì)重新讀取這個(gè)變量。因此volatile更多的作用還是避免這種讀合并。

 

 

四、讓進(jìn)程睡固定的時(shí)間

 

下面兩個(gè)函數(shù)可以將當(dāng)前進(jìn)程添加到等待隊(duì)列中,從而在等待隊(duì)列上睡眠,當(dāng)超時(shí)發(fā)生時(shí),進(jìn)程將被喚醒:

 

sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout);

interrupt_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout);

上一篇:Linux設(shè)備驅(qū)動(dòng)申請(qǐng)?jiān)O(shè)備號(hào)過(guò)程分析

下一篇:Linux設(shè)備驅(qū)動(dòng)模型之kobject linux2.6.0

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專(zhuān)線(xiàn):010-82525158 企業(yè)培訓(xùn)洽談專(zhuān)線(xiàn):010-82525379 院校合作洽談專(zhuān)線(xiàn):010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見(jiàn)科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5,京公海網(wǎng)安備11010802025203號(hào)

回到頂部

色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 麻豆成人在线看| 亚洲性av网站| 精品综合久久久久久97| 亚洲精品国产精品国自产在线| 欧美高清激情视频| 亚洲男子天堂网| 国产精品视频大全| 欧美日韩亚洲高清| 亚洲视频axxx| 中文字幕精品影院| 亚洲激情在线观看视频免费| 国产精品普通话| 亚洲已满18点击进入在线看片| 欧美在线观看视频| 欧美福利视频在线| 欧美一区视频在线| 国产日韩欧美中文在线播放| 91精品国产电影| 欧美黄色片在线观看| 欧美一二三视频| 亚洲一区二区三区视频| 亚洲性夜色噜噜噜7777| 欧美成人午夜免费视在线看片 | 国产精品精品视频一区二区三区| 欧美日韩中文字幕日韩欧美| 日韩国产激情在线| 在线日韩中文字幕| 精品成人av一区| 久久精品国产久精国产一老狼| 亚洲免费视频在线观看| 久久久91精品| 久久中文字幕国产| 性欧美亚洲xxxx乳在线观看| 国模gogo一区二区大胆私拍| 欧美日韩激情小视频| 欧美最猛性xxxx| 欧美壮男野外gaytube| 亚洲第一福利网站| 亚洲免费电影在线观看| 九九热99久久久国产盗摄| 国产精品白丝av嫩草影院|