1. 程式人生 > >內核搶占

內核搶占

() details 特性 boot cor utm irq 現在 copy

內核搶占是一個軟件特性,並不是一個硬件特性

我之所以在perf record -e kprobes:schedule -g -a 沒發現時鐘中斷,是因為我的內核根本就沒有開啟內核的搶占,不對啊,用戶態也應該發生調度啊!

-- 所以啊並不是說我不能找到這個值而是說

--為啥沒有抓到時鐘中斷引起的調度呢?時鐘中斷是如何作用調度的?時鐘中斷只會判斷是否need resched,並不會在中斷函數中發生調度!中斷函數返回用戶態的時候可能會發生調度比如抓到了大量的函數prepare_exit_to_usermode,所以中斷處理函數是幹嘛的呀

 2f6a31 do_timer (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2fe48c tick_sched_do_timer (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2fe519 tick_sched_timer (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2ef212 __hrtimer_run_queues (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2ef9d8 hrtimer_interrupt (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  252f88 local_apic_timer_interrupt (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  a26f9d smp_apic_timer_interrupt (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  a25262 apic_timer_interrupt (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  8bbbc7 cpuidle_enter (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2c3d52 call_cpuidle (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                  2c4010 cpu_startup_entry (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)

能抓到do_timer函數,說明時鐘中斷沒有被屏蔽,但是

(3) 通過把搶占計數器設置為正而顯式禁止內核搶占,由preempt_disable完成。 當從中斷返回內核空間時,內核會檢preempt_count和need_resched的值(返回用戶空間時只需要檢查need_resched),如查preempt_count為0且need_resched設置,則調用schedule(),完成任務搶占。一般來說,內核搶占發生以下情況: (1) 從中斷(異常)返回時,preempt_count為0且need_resched置位(見從中斷返回); (2) 在異常處理程序中(特別是系統調用)調用preempt_enable()來允許內核搶占發生; --------------------- 作者:Tommy_wxie 來源:CSDN 原文:https://blog.csdn.net/tommy_wxie/article/details/7425728?utm_source=copy 版權聲明:本文為博主原創文章,轉載請附上博文鏈接!link

#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
    DISABLE_INTERRUPTS(CLBR_ANY)
need_resched:
    cmpl    $0, PER_CPU_VAR(__preempt_count)
    jnz restore_all
    testl   $X86_EFLAGS_IF, PT_EFLAGS(%esp) # interrupts off (exception path) ?
    jz  restore_all
    call    preempt_schedule_irq
    jmp need_resched

也就是說在內核搶占關閉的情況下,__preempt_count

在搶占開啟的情況下,是會有搶占發生的,真是揪心:

64 #ifdef CONFIG_PREEMPT
65 # define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
66 #else //----------->在CONFIG_PREEMPT關閉的情況下,resume_kernel竟然直接就替換成了restore_all,這個restore_all不就是上文中在config_preempt開啟的情況下要走到的那個路徑嘛。。。所以這就沒跑了,當內核中關閉了搶占之後,時鐘中斷根本就不會發生調度。
67 # define preempt_stop(clobbers)
68 # define resume_kernel restore_all
69 #endif
70

那麽幾乎所有的博客中都會提到的thread_info中的又是啥呢?這就是搶占的軟件機制之所在了;首先,這個問題只會出現在搶占內核中呢,在搶占內核中,有的地方要避免搶占,只要搶占關閉了,那麽肯定就不會發生搶占了呀,為啥還要關閉中斷呢

每次進入臨界區都要關閉搶占,搶占是針對同一個和上的操作

內核搶占