欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學堂Linux培訓詳解Linux時鐘中斷

2019-09-23 10:39:13 5469瀏覽

本篇文章扣丁學堂Linux培訓小編給小伙伴們分享一下Linux時鐘中斷詳解,對Linux開發(fā)技術感興趣的小伙伴就隨小編來了解一下吧,希望對小伙伴們有幫助。


扣丁學堂Linux培訓詳解Linux時鐘中斷


在Linux的0號中斷是一個定時器中斷。在固定的時間間隔都發(fā)生一次中斷,也是說每秒發(fā)生該中斷的頻率都是固定的。該頻率是常量HZ,該值一般是在100~1000之間。該中斷的作用是為了定時更新系統(tǒng)日期和時間,使系統(tǒng)時間不斷地得到跳轉(zhuǎn)。另外該中斷的中斷處理函數(shù)除了更新系統(tǒng)時間外,還需要更新本地CPU統(tǒng)計數(shù)。指的是調(diào)用scheduler_tick遞減進程的時間片,若進程的時間片遞減到0,進程則被調(diào)度出去而放棄CPU使用權。


時鐘中斷的產(chǎn)生:


Linux的OS時鐘的物理產(chǎn)生原因是可編程定時/計數(shù)器產(chǎn)生的輸出脈沖,這個脈沖送入CPU,就可以引發(fā)一個中斷請求信號,我們就把它叫做時鐘中斷。


“時鐘中斷”是特別重要的一個中斷,因為整個操作系統(tǒng)的活動都受到它的激勵。系統(tǒng)利用時鐘中斷維持系統(tǒng)時間、促使環(huán)境的切換,以保證所有進程共享CPU;利用時鐘中斷進行記帳、監(jiān)督系統(tǒng)工作以及確定未來的調(diào)度優(yōu)先級等工作。可以說,“時鐘中斷”是整個操作系統(tǒng)的脈搏。


時鐘中斷的物理產(chǎn)生如圖所示:


扣丁學堂Linux視頻教程


操作系統(tǒng)對可編程定時/計數(shù)器進行有關初始化,然后定時/計數(shù)器就對輸入脈沖進行計數(shù)(分頻),產(chǎn)生的三個輸出脈沖Out0、Out1、Out2各有用途,很多接口書都介紹了這個問題,我們只看Out0上的輸出脈沖,這個脈沖信號接到中斷控制器8259A_1的0號管腳,觸發(fā)一個周期性的中斷,我們就把這個中斷叫做時鐘中斷,時鐘中斷的周期,也就是脈沖信號的周期,我們叫做“滴答”或“時標”(tick)。從本質(zhì)上說,時鐘中斷只是一個周期性的信號,完全是硬件行為,該信號觸發(fā)CPU去執(zhí)行一個中斷服務程序,但是為了方便,我們就把這個服務程序叫做時鐘中斷。



Linux實現(xiàn)時鐘中斷的全過程


1、可編程定時/計數(shù)器的初始化


IBM PC中使用的是8253或8254芯片。有關該芯片的詳細知識我們不再詳述,只大體介紹以下它的組成和作用,如下表所示:


扣丁學堂Linux在線視頻教程


計數(shù)器0的輸出就是圖中的Out0,它的頻率由操作系統(tǒng)的設計者確定,Linux對8253的初始化程序段如下(在/arch/i386/kernel/i8259.c的init_IRQ()函數(shù)中):


set_intr_gate(ox20, interrupt[0]); 
 
/*在IDT的第0x20個表項中插入一個中斷門。這個門中的段選擇符設置成內(nèi)核代碼段的選擇符,偏移域設置成0號中斷處理程序的入口地址。*/ 
 
outb_p(0x34,0x43);  /* 寫計數(shù)器0的控制字:工作方式2*/ 
 
outb_p(LATCH & 0xff , 0x40); /* 寫計數(shù)初值LSB 計數(shù)初值低位字節(jié)*/ 
 
outb(LATCH >> 8 , 0x40); /* 寫計數(shù)初值MSB 計數(shù)初值高位字節(jié)*/ 
 
LATCH(英文意思為:鎖存器,即其中鎖存了計數(shù)器0的初值)為計數(shù)器0的計數(shù)初值,在/include/linux/timex.h中定義如下: 
 
#define CLOCK_TICK_RATE 1193180 /* 圖5.3中的輸入脈沖 */ 
 
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* 計數(shù)器0的計數(shù)初值 */ 


CLOCK_TICK_RATE是整個8253的輸入脈沖,如圖所示為1.193180MHz,是近似為1MHz的方波信號,8253內(nèi)部的三個計數(shù)器都對這個時鐘進行計數(shù),進而產(chǎn)生不同的輸出信號,用于不同的用途。


HZ表示計數(shù)器0的頻率,也就是時鐘中斷或系統(tǒng)時鐘的頻率,在/include/asm/param.h中定義如下:


#define HZ 100



2、與時鐘中斷相關的函數(shù)


下面我們看時鐘中斷觸發(fā)的服務程序,該程序代碼比較復雜,分布在不同的源文件中,主要包括如下函數(shù):


時鐘中斷程序:timer_interrupt( );

中斷服務通用例程do_timer_interrupt();

時鐘函數(shù):do_timer( );

中斷安裝程序:setup_irq( );

中斷返回函數(shù):ret_from_intr( );


(1) timer_interrupt( )


這個函數(shù)大約每10ms被調(diào)用一次,實際上, timer_interrupt( )函數(shù)是一個封裝例程,它真正做的事情并不多,但是,作為一個中斷程序,它必須在關中斷的情況下執(zhí)行。如果只考慮單處理機的情況,該函數(shù)主要語句就是調(diào)用do_timer_interrupt()函數(shù)。


(2) do_timer_interrupt()


do_timer_interrupt()函數(shù)有兩個主要任務,一個是調(diào)用do_timer( ),另一個是維持實時時鐘(RTC,每隔一定時間段要回寫),其實現(xiàn)代碼在/arch/i386/kernel/time.c中, 為了突出主題,筆者對以下函數(shù)作了改寫,以便于讀者理解:


static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
{ 
 do_timer(regs); /* 調(diào)用時鐘函數(shù),將時鐘函數(shù)等同于時鐘中斷未嘗不可*/ 
 if(xtime.tv_sec > last_rtc_update + 660) 
 update_RTC(); 
 /*每隔11分鐘就更新RTC中的時間信息,以使OS時鐘和RTC時鐘保持同步,11分鐘即660秒,xtime.tv_sec的單位是秒,last_rtc_update記錄的是上次RTC更新時的值 */             
} 


其中,xtime是前面所提到的timeval類型,這是一個全局變量。


(3) 時鐘函數(shù)do_timer() (在/kernel/sched.c中)


void do_timer(struct pt_regs * regs) 
{ 
 (*(unsigned long *)&jiffies)++; /*更新系統(tǒng)時間,這種寫法保證對jiffies 
 
操作的原子性*/ 
 update_process_times(); 
 ++lost_ticks; 
 if( ! user_mode ( regs ) ) 
  ++lost_ticks_system; 
  mark_bh(TIMER_BH);    
 if (tq_timer)      
  mark_bh(TQUEUE_BH); 
} 


其中,update_process_times()函數(shù)與進程調(diào)度有關,從函數(shù)的名子可以看出,它處理的是與當前進程與時間有關的變量,例如,要更新當前進程的時間片計數(shù)器counter,如果counter<=0,則要調(diào)用調(diào)度程序,要處理進程的所有定時器:實時、虛擬、概況,另外還要做一些統(tǒng)計工作。


與時間有關的事情很多,不能全都讓這個函數(shù)去完成,這是因為這個函數(shù)是在關中斷的情況下執(zhí)行,必須處理完最重要的時間信息后退出,以處理其他事情。那么,與時間相關的其他信息誰去處理,何時處理?這就是由第三章討論的后半部分去去處理。 上面timer_interrupt()(包括它所調(diào)用的函數(shù))所做的事情就是上半部分。


在該函數(shù)中還有兩個變量lost_ticks和lost_ticks_system,這是用來記錄timer_bh()執(zhí)行前時鐘中斷發(fā)生的次數(shù)。因為時鐘中斷發(fā)生的頻率很高(每10ms一次),所以在timer_bh()執(zhí)行之前,可能已經(jīng)有時鐘中斷發(fā)生了,而timer_bh()要提供定時、記費等重要操作,所以為了保證時間計量的準確性,使用了這兩個變量。lost_ticks用來記錄timer_bh()執(zhí)行前時鐘中斷發(fā)生的次數(shù),如果時鐘中斷發(fā)生時當前進程運行于內(nèi)核態(tài),則lost_ticks_system用來記錄timer_bh()執(zhí)行前在內(nèi)核態(tài)發(fā)生時鐘中斷的次數(shù),這樣可以對當前進程精確記費。


扣丁學堂Linux基礎教程



(4)中斷安裝程序


從上面的介紹可以看出,時鐘中斷與進程調(diào)度密不可分,因此,一旦開始有時鐘中斷就可能要進行調(diào)度,在系統(tǒng)進行初始化時,所做的大量工作之一就是對時鐘進行初始化,其函數(shù)time_init ()的代碼在/arch/i386/kernel/time.c中,對其簡寫如下:


 void __init time_init(void) 
 { 
xtime.tv_sec=get_cmos_time(); 
xtime.tv_usec=0; 
setup_irq(0,&irq0); 
} 


其中的get_cmos_time()函數(shù)就是把當時的實際時間從CMOS時鐘芯片讀入變量xtime中,時間精度為秒。而setup_irq(0,&irq0)就是時鐘中斷安裝函數(shù),那么irq0指的是什么呢,它是一個結構類型irqaction,其定義及初值如下:


static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};

setup_irq(0, &irq0)的代碼在/arch/i386/kernel/irq.c中,其主要功能就是將中斷程序連入相應的中斷請求隊列,以等待中斷到來時相應的中斷程序被執(zhí)行。


struct irqaction { 
  irq_handler_t handler;  //中斷處理函數(shù),注冊時提供  
  unsigned long flags;   //中斷標志,注冊時提供  
  cpumask_t mask;    //中斷掩碼  
  const char *name;   //中斷名稱 
  void *dev_id;      //設備id,本文后面部分介紹中斷共享時會詳細說明這個參數(shù)的作用 
  struct irqaction *next;  //如果有中斷共享,則繼續(xù)執(zhí)行,  
  int irq;        //中斷號,注冊時提供 
  struct proc_dir_entry *dir; //指向IRQn相關的/proc/irq/n目錄的描述符 
}; 


這個結構體包含了處理一種中斷所需要的各種信息,它代表了內(nèi)核接受到特定IRQ之后應該采取的操作。


1、handler:該指針所指向的函數(shù)就是在中斷服務程序,當中斷發(fā)生時內(nèi)核便會調(diào)用這個指針指向的函數(shù)。


2、flags:該標志位可以是0,也可以是:

SA_INTERRUPT:表示此中斷處理程序是一個快速中斷處理程序,在2.6中默認情況下沒有這個標志;設置該標志位,中斷處理程序禁止任何中斷運行,沒有該標志,僅屏蔽正在運行的IRQ線;

SA_SAMPLE_RANDOM:表示這個中斷對內(nèi)核池有貢獻,在中斷時產(chǎn)生一些隨機數(shù);

SA_SHIRQ:此標志位表示允許多個中斷服務程序共享一個中斷號,如不設則一個程序?qū)粋€中斷線;


3、mask:在x86上不會用到。


4、name:產(chǎn)生中斷的硬件的名字。


5、dev_id:該標志位主要在共享中斷號時使用,即你設置flags=SA_SHIRQ時,有多個中斷服務程序共享一個中斷號時,內(nèi)核就需要知道在用完中斷程序后該刪除那個中斷服務程序。不共享時此成員為null。


6、next:如果flags=SA_SHIRQ,那么這就是指向?qū)α兄邢乱粋€struct irqaction結構體的指針,否則為空。


7、irq:不用說這就是中斷號了。


到現(xiàn)在為止,我們僅僅是把時鐘中斷程序掛入中斷請求隊列,什么時候執(zhí)行,怎樣執(zhí)行,這是一個復雜的過程,為了讓讀者對時鐘中斷有一個完整的認識,我們忽略中間過程,而給出一個整體描述。我們將有關函數(shù)改寫如下,體現(xiàn)時鐘中斷的大意:


do_timer_interrupt( )   /*這是一個偽函數(shù) */ 
{            
 SAVE_ALL     /*保存處理機現(xiàn)場 */ 
 intr_count += 1;    /* 這段操作不允許被中斷 */ 
 timer_interrupt()    /* 調(diào)用時鐘中斷程序 */ 
 intr_count -= 1;    
 jmp ret_from_intr    /* 中斷返回函數(shù) */ 
} 


其中,jmp ret_from_intr 是一段匯編代碼,也是一個較為復雜的過程,它最終要調(diào)用jmp ret_from_sys_call,即系統(tǒng)調(diào)用返回函數(shù),而這個函數(shù)與進程的調(diào)度又密切相關,,因此,我們重點分析 jmp ret_from_sys_call。


3、系統(tǒng)調(diào)用返回函數(shù):


系統(tǒng)調(diào)用返回函數(shù)的源代碼在/arch/i386/kernel/entry.S中


ENTRY(ret_from_sys_call) 
   cli     # need_resched and signals atomic test 
   cmpl $0,need_resched(%ebx) 
   jne reschedule 
   cmpl $0,sigpending(%ebx) 
   jne signal_return 
 restore_all: 
   RESTORE_ALL 
   ALIGN 
 signal_return: 
   sti    # we can get here from an interrupt handler 
   testl $(VM_MASK),EFLAGS(%esp) 
   movl %esp,%eax 
   jne v86_signal_return 
   xorl %edx,%edx 
   call SYMBOL_NAME(do_signal) 
   jmp restore_all 
   ALIGN 
  v86_signal_return: 
   call SYMBOL_NAME(save_v86_state) 
   movl %eax,%esp 
   xorl %edx,%edx 
   call SYMBOL_NAME(do_signal) 
   jmp restore_all 
 …. 
 reschedule: 
   call SYMBOL_NAME(schedule) # test 
  jmp ret_from_sys_call 


這一段匯編代碼就是前面我們所說的“從系統(tǒng)調(diào)用返回函數(shù)”ret_from_sys_call,它是從中斷、異常及系統(tǒng)調(diào)用返回時的通用接口。這段代碼主體就是ret_from_sys_call函數(shù),其執(zhí)行過程中要調(diào)用其它一些函數(shù)(實際上是一段代碼,不是真正的函數(shù)),在此我們列出相關的幾個函數(shù):


(1)ret_from_sys_call:主體

(2)reschedule:檢測是否需要重新調(diào)度

(3)signal_return:處理當前進程接收到的信號

(4)v86_signal_return:處理虛擬86模式下當前進程接收到的信號

(5)RESTORE_ALL:我們把這個函數(shù)叫做徹底返回函數(shù),因為執(zhí)行該函數(shù)之后,就返回到當前進程的地址空間中去了。


可以看到ret_from_sys_call的主要作用有:


檢測調(diào)度標志need_resched,決定是否要執(zhí)行調(diào)度程序;處理當前進程的信號;恢復當前進程的環(huán)境使之繼續(xù)執(zhí)行。


最后我們再次從總體上瀏覽一下時鐘中斷:


每個時鐘滴答,時鐘中斷得到執(zhí)行。時鐘中斷執(zhí)行的頻率很高:100次/秒,時鐘中斷的主要工作是處理和時間有關的所有信息、決定是否執(zhí)行調(diào)度程序以及處理下半部分。和時間有關的所有信息包括系統(tǒng)時間、進程的時間片、延時、使用CPU的時間、各種定時器,進程更新后的時間片為進程調(diào)度提供依據(jù),然后在時鐘中斷返回時決定是否要執(zhí)行調(diào)度程序。下半部分處理程序是Linux提供的一種機制,它使一部分工作推遲執(zhí)行。時鐘中斷要絕對保證維持系統(tǒng)時間的準確性,而下半部分這種機制的提供不但保證了這種準確性,還大幅提高了系統(tǒng)性能。


想要了解更多關于Linux方面內(nèi)容的小伙伴,請關注扣丁學堂Linux培訓官網(wǎng)、微信等平臺,扣丁學堂IT職業(yè)在線學習教育平臺為您提供權威的Linux視頻,扣丁學堂老師精心推出的Linux視頻教程定能讓你快速掌握Linux從入門到精通開發(fā)實戰(zhàn)技能。扣丁學堂Linux技術交流群:422345477。


扣丁學堂微信公眾號                          Python全棧開發(fā)爬蟲人工智能機器學習數(shù)據(jù)分析免費公開課直播間


      【關注微信公眾號獲取更多學習資料】         【掃碼進入Python全棧開發(fā)免費公開課】




查看更多關于“Linux培訓資訊”的相關文章>>

標簽: Linux培訓 Linux視頻教程 紅帽Linux視頻 Linux學習視頻 Linux入門視頻 紅帽RHCE/RHCSA考試

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部