内核抢占

内核抢占是一个软件特性,并不是一个硬件特性

我之所以在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中的又是啥呢?这就是抢占的软件机制之所在了;首先,这个问题只会出现在抢占内核中呢,在抢占内核中,有的地方要避免抢占,只要抢占关闭了,那么肯定就不会发生抢占了呀,为啥还要关闭中断呢

每次进入临界区都要关闭抢占,抢占是针对同一个和上的操作
 

 

posted @ 2018-10-20 14:04  honpey  阅读(549)  评论(0编辑  收藏  举报