Linux內(nèi)核搶占與中斷返回-_第1頁
Linux內(nèi)核搶占與中斷返回-_第2頁
Linux內(nèi)核搶占與中斷返回-_第3頁
Linux內(nèi)核搶占與中斷返回-_第4頁
Linux內(nèi)核搶占與中斷返回-_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Linux內(nèi)核搶占與中斷返回1、上下文一般來說,CPU在任何時刻都處于以下三種情況之一:(1運(yùn)行于用戶空間,執(zhí)行用戶進(jìn)程;(2運(yùn)行于內(nèi)核空間,處于進(jìn)程上下文;(3運(yùn)行于內(nèi)核空間,處于中斷上下文。應(yīng)用程序通過系統(tǒng)調(diào)用陷入內(nèi)核,此時處于進(jìn)程上下文。現(xiàn)代幾乎所有的CPU體系結(jié)構(gòu)都支持中斷。當(dāng)外部設(shè)備產(chǎn)生中斷,向CPU發(fā)送一個異步信號,CPU調(diào)用相應(yīng)的中斷處理程序來處理該中斷,此時CPU處于中斷上下文。在進(jìn)程上下文中,可以通過current關(guān)聯(lián)相應(yīng)的任務(wù)。進(jìn)程以進(jìn)程上下文的形式運(yùn)行在內(nèi)核空間,可以發(fā)生睡眠,所以在進(jìn)程上下文中,可以使作信號量(semaphore。實(shí)際上,內(nèi)核經(jīng)常在進(jìn)程上下文中使用信號量

2、來完成任務(wù)之間的同步,當(dāng)然也可以使用鎖。中斷上下文不屬于任何進(jìn)程,它與current沒有任何關(guān)系(盡管此時current指向被中斷的進(jìn)程。由于沒有進(jìn)程背景,在中斷上下文中不能發(fā)生睡眠,否則又如何對它進(jìn)行調(diào)度。所以在中斷上下文中只能使用鎖進(jìn)行同步,正是因?yàn)檫@個原因,中斷上下文也叫做原子上下文(atomic context。在中斷處理程序中,通常會禁止同一中斷,甚至?xí)拐麄€本地中斷,所以中斷處理程序應(yīng)該盡可能迅速,所以又把中斷處理分成上部和下部。2、上下文切換上下文切換,也就是從一個可執(zhí)行進(jìn)程切換到另一個可執(zhí)行進(jìn)程。上下文切換由函數(shù)context_switch(函數(shù)完成,該函數(shù)位于kernel/

3、sched.c中,它由進(jìn)程調(diào)度函數(shù)schedule(調(diào)用。 static inlinetask_t * context_switch(runqueue_t *rq, task_t *prev, task_t *nextstruct mm_struct *mm = next->mm;struct mm_struct *oldmm = prev->active_mm;if (unlikely(!mm next->active_mm = oldmm;atomic_inc(&oldmm->mm_count;enter_lazy_tlb(oldmm, next; else

4、switch_mm(oldmm, mm, next;if (unlikely(!prev->mm prev->active_mm = NULL;WARN_ON(rq->prev_mm;rq->prev_mm = oldmm;/* Here we just switch the register state and the stack. */switch_to(prev, next, prev;return prev; 其中,switch_mm(將虛擬內(nèi)存映射到新的進(jìn)程;switch_to完成最終的進(jìn)程切換,它保存原進(jìn)程的所有寄存器信息,恢復(fù)新進(jìn)程的所有寄存器信息,并執(zhí)行

5、新的進(jìn)程。無論何時,內(nèi)核想要進(jìn)行任務(wù)切換,都通過調(diào)用schedule(完成任務(wù)切換。3、用戶搶占當(dāng)內(nèi)核即將返回用戶空間時,內(nèi)核會檢查need_resched是否設(shè)置,如果設(shè)置,則調(diào)用schedule(,此時,發(fā)生用戶搶占。一般來說,用戶搶占發(fā)生幾下情況:(1從系統(tǒng)調(diào)用返回用戶空間;(2從中斷(異常處理程序返回用戶空間。4、內(nèi)核搶占內(nèi)核從2.6開始就支持內(nèi)核搶占,對于非內(nèi)核搶占系統(tǒng),內(nèi)核代碼可以一直執(zhí)行,直到完成,也就是說當(dāng)進(jìn)程處于內(nèi)核態(tài)時,是不能被搶占的(當(dāng)然,運(yùn)行于內(nèi)核態(tài)的進(jìn)程可以主動放棄CPU,比如,在系統(tǒng)調(diào)用服務(wù)例程中,由于內(nèi)核代碼由于等待資源而放棄CPU,這種情況叫做計劃性進(jìn)程切換(p

6、lanned process switch。但是,對于由異步事件(比如中斷引起的進(jìn)程切換,搶占式內(nèi)核與非搶占式是有區(qū)別的,對于前者叫做強(qiáng)制性進(jìn)程切換(forced process switch。為了支持內(nèi)核搶占,內(nèi)核引入了preempt_count字段,該計數(shù)初始值為0,每當(dāng)使用鎖時加1,釋放鎖時減1。當(dāng)preempt_count 為0時,表示內(nèi)核可以被安全的搶占,大于0時,則禁止內(nèi)核搶占。該字段對應(yīng)三個不同的計數(shù)器(見軟中斷一節(jié),也就是說在以下三種任何一種情況,該字段的值都會大于0。(1 內(nèi)核執(zhí)行中斷處理程序時,通過irq_enter增加中斷計數(shù)器的值;#define irq_enter(

7、(preempt_count( += HARDIRQ_OFFSET(2可延遲函數(shù)被禁止(執(zhí)行軟中斷和tasklet時經(jīng)常如此,由local_bh_disable完成;(3通過把搶占計數(shù)器設(shè)置為正而顯式禁止內(nèi)核搶占,由preempt_disable完成。當(dāng)從中斷返回內(nèi)核空間時,內(nèi)核會檢preempt_count和need_resched的值(返回用戶空間時只需要檢查need_resched,如查preempt_count為0且need_resched設(shè)置,則調(diào)用schedule(,完成任務(wù)搶占。一般來說,內(nèi)核搶占發(fā)生以下情況:(1從中斷(異常返回時,preempt_count為0且need_re

8、sched置位;(2在異常處理程序中(特別是系統(tǒng)調(diào)用調(diào)用preempt_enable(來允許內(nèi)核搶占發(fā)生; /incude/linux/preempt.h#define preempt_enable( do /搶占計數(shù)器值減1preempt_enable_no_resched(; /檢查是否需要進(jìn)行內(nèi)核搶占調(diào)度,見(3preempt_check_resched(; while (0 (3 啟用可延遲函數(shù)時,即調(diào)用local_bh_enable(時發(fā)生; /kernel/softirq.cvoid local_bh_enable(voidWARN_ON(irqs_disabled(;/* Kee

9、p preemption disabled until we are done with* softirq processing:*/軟中斷計數(shù)器值減1preempt_count( -= SOFTIRQ_OFFSET - 1;if (unlikely(!in_interrupt( && local_softirq_pending(do_softirq(; /軟中斷處理/搶占計數(shù)據(jù)器值減1dec_preempt_count(;/檢查是否需要進(jìn)行內(nèi)核搶占調(diào)度preempt_check_resched(;/include/linux/preempt.h#define preempt_

10、check_resched( do /檢查need_reschedif (unlikely(test_thread_flag(TIF_NEED_RESCHED /搶占調(diào)度preempt_schedule(; while (0/kernel/sched.casmlinkage void _sched preempt_schedule(voidstruct thread_info *ti = current_thread_info(;/* If there is a non-zero preempt_count or interrupts are dis abled,* we do not wan

11、t to preempt the current task. Just return. */檢查是否允許搶占,本地中斷關(guān)閉,或者搶占計數(shù)器值不為0時不允許搶占if (unlikely(ti->preempt_count | irqs_disabled(return;need_resched:ti->preempt_count = PREEMPT_ACTIVE;/發(fā)生調(diào)度schedule(;ti->preempt_count = 0;/* we could miss a preemption opportunity between schedule an d now */bar

12、rier(;if (unlikely(test_thread_flag(TIF_NEED_RESCHEDgoto need_resched; (4內(nèi)核任務(wù)顯示調(diào)用schedule(,例如內(nèi)核任務(wù)阻塞時,就會顯示調(diào)用schedule(,該情況屬于內(nèi)核自動放棄CPU。5、從中斷返回當(dāng)內(nèi)核從中斷返回時,應(yīng)當(dāng)考慮以下幾種情況:(1內(nèi)核控制路徑并發(fā)執(zhí)行的數(shù)量:如果為1,則CPU返回用戶態(tài)。(2掛起進(jìn)程的切換請求:如果有掛起請求,則進(jìn)行進(jìn)程調(diào)度;否則,返回被中斷的進(jìn)程。(3待處理信號:如果有信號發(fā)送給當(dāng)前進(jìn)程,則必須進(jìn)行信號處理。(4單步調(diào)試模式:如果調(diào)試器正在跟蹤當(dāng)前進(jìn)程,在返回用戶態(tài)時必須恢復(fù)單步模式

13、。(5Virtual-8086模式:如果中斷時CPU處于虛擬8086模式,則進(jìn)行特殊的處理。5.1從中斷返回中斷返回點(diǎn)為ret_from-intr: #從中斷返回ret_from_intr:GET_THREAD_INFO(%ebpmovl EFLAGS(%esp, %eax # mix EFLAGS and CSmovb CS(%esp, %altestl $(VM_MASK | 3, %eax #是否運(yùn)行在VM86模式或者用戶態(tài)/*中斷或異常發(fā)生時,處于內(nèi)核空間,則返回內(nèi)核空間;否則返回用戶空間*/ jz resume_kernel # returning to kernel or vm86

14、-space 從中斷返回時,有兩種情況,一是返回內(nèi)核態(tài),二是返回用戶態(tài)。5.1.1、返回內(nèi)核態(tài) #ifdef CONFIG_PREEMPT/*返回內(nèi)核空間,先檢查preempt_count,再檢查need_resched*/ENTRY(resume_kernel/*是否可以搶占,即preempt_count是否為0*/cmpl $0,TI_preempt_count(%ebp # non-zero preempt_count ?jnz restore_all #不能搶占,則恢復(fù)被中斷時處理器狀態(tài)need_resched:movl TI_flags(%ebp, %ecx # need_resch

15、ed set ?testb $_TIF_NEED_RESCHED, %cl #是否需要重新調(diào)度jz restore_all #不需要重新調(diào)度testl $IF_MASK,EFLAGS(%esp # 發(fā)生異常則不調(diào)度jz restore_all#將最大值賦值給preempt_count,表示不允許再次被搶占movl $PREEMPT_ACTIVE,TI_preempt_count(%ebpsticall schedule #調(diào)度函數(shù)climovl $0,TI_preempt_count(%ebp #preempt_count還原為0#跳轉(zhuǎn)到need_resched,判斷是否又需要發(fā)生被調(diào)度jmp

16、 need_resched#endif 5.1.2、返回用戶態(tài) /*返回用戶空間,只需要檢查need_resched*/ENTRY(resume_userspace #返回用戶空間,中斷或異常發(fā)生時,任務(wù)處于用戶空間cli # make sure we don't miss an interrupt# setting need_resched or sigpending# between sampling and the iretmovl TI_flags(%ebp, %ecxandl $_TIF_WORK_MASK, %ecx # is there any work to be do

17、ne on# int/exception return?jne work_pending #還有其它工作要做jmp restore_all #所有工作都做完,則恢復(fù)處理器狀態(tài)#恢復(fù)處理器狀態(tài)restore_all:RESTORE_ALL# perform work that needs to be done immediately before resum ptionALIGN#完成其它工作work_pending:testb $_TIF_NEED_RESCHED, %cl #檢查是否需要重新調(diào)度jz work_notifysig #不需要重新調(diào)度#需要重新調(diào)度work_resched:cal

18、l schedule #調(diào)度進(jìn)程cli # make sure we don't miss an interrupt# setting need_resched or sigpending# between sampling and the iretmovl TI_flags(%ebp, %ecx/*檢查是否還有其它的事要做*/andl $_TIF_WORK_MASK, %ecx # is there any work to be done other# than syscall tracing?jz restore_all #沒有其它的事,則恢復(fù)處理器狀態(tài)testb $_TIF_NE

19、ED_RESCHED, %cljnz work_resched #如果need_resched再次置位,則繼續(xù)調(diào)度#VM和信號檢測work_notifysig: # deal with pending signals and# notify-resume requeststestl $VM_MASK, EFLAGS(%esp #檢查是否是VM模式movl %esp, %eaxjne work_notifysig_v86 # returning to kernel-space or# vm86-spacexorl %edx, %edx#進(jìn)行信號處理call do_notify_resumejmp

20、 restore_allALIGNwork_notifysig_v86:pushl %ecx # save ti_flags for do_notify_resume call save_v86_state # %eax contains pt_regs pointerpopl %ecxmovl %eax, %espxorl %edx, %edxcall do_notify_resume #信號處理jmp restore_all 5.2、從異常返回異常返回點(diǎn)為ret_from_exception:#從異常返回ALIGNret_from_exception:preempt_stop /*相當(dāng)于cli,從中斷返回時,在handle_IRQ_event已經(jīng)關(guān)中斷,不需要這步*/6、從系統(tǒng)調(diào)用返回 #系統(tǒng)調(diào)用入口ENTRY(system_callpushl %eax # save orig_eaxSAVE_ALLGET_THREAD_INFO(%ebp# system call tracing in operationtestb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT,TI_flags(%ebp jnz syscall_trace_entrycmpl $(nr_syscalls, %eaxjae sysc

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論