Linux內核源碼分析之調度、內核線程模型 And Centos7.2's Kernel Resource Analysis


本文分為概述、歷史、el7.2代碼架構圖解三部分。
解決的問題:
  a.Kernel調度發展過程;
  b.以架構圖的方式,詳解el7.2具體調度實現、內核線程模型、調度時間片計算,以及探究整個Kernel實際運行過程。
 
1.概述
    現代操作系統,通過虛擬化CPU及內存,來達到最大化硬件能力的目的
        a.內存虛擬化:
            每個task都有自己獨立的虛擬內存地址空間,然后映射到physical memory;實際內存總量是一定的,為了使多個程序同時、正常的運行起來,每個task虛擬內存都從0x0000開始,當程序被載入內存中時,才在物理內存管理表中,建立虛擬內存和物理內存的關系,task運行時實際是CPU在物理內存上進行指令運算、存取。
            好比桌子上有一堆huge水果,但是你只有一個small籃子,為了讓每個huge水果被食用時,都是通過籃子裝載的,只有在食用時,才從桌子上把huge水果放到籃子的固定位置,提供給你食用。
        b.CPU虛擬化:
            每個task並不是一直獨占CPU,而是將CPU按照時鍾頻率進行划分,通常HZ為1000,每個獲取執行權限的task執行一個時序,而從在秒級層面看來,本時間段中,有多個task獲得執行,達到模擬並行的效果。
            這個過程和現實中人做事情一樣,每一個固定時間段,精力集中在一件事上,但是一整天,咱並行做了很多任務。
    CPU調度的難點在於必須使高、低優先級的task都得到執行,並且交互式task必須在50-150ms中得到執行。
 
2.歷史
   a.0.01版
        最初的調度系統中,只有一個處理隊列,並且循環不斷的從其中取出要執行的task。
        在那個年代,最多能執行的task總數為NR_TASKS=32;並且從那時起就引入了執行task狀態RUNNING、INTERRUPTIBLE、UNINTERRUPTIBLE的概念;同時,提出了按照優先級和時間片來決定next exec task,這一schedule核心的思想,貫穿了整個Kernel的發展。
    
    b.O(n) Scheduler in Version 2.4
        簡單粗暴的將系統的一段時間划分給系統上所有task,以保證在這段時間(lifetime生命周期)內所有進程得到執行;
        在這段時間末尾,有些task的timeslice未用完,則將其值的一半加到下一個時間段中
        其顯著缺點是耗費太多時間在選擇要執行的task上,並且對real-time task支持不好
 
    c.O(1) in early versionf of 2.6 kernel
        由於其顯著的選擇goodness task速度及對real-time的支持,很快便取代了O(n) Scheduler
        i.從全局進行priority規划,0-139共140個等級,數字越小,優先級越高;同時,對real-time和normal task的等級區間進行了規划,即0-99作為real-time task專用區間,100-139作為normal task區間;
        ii.CPU搶占思想的提出,當有task進入TASK_RUNNING時,並根據其與當前task優先級大小(current——調度系統中指向當前執行進程的宏,非常重要),決定是否調用schedule()——調用此方法,會重新選擇執行task,以達到高優先級搶占低優先級task CPU的目的;
        iii.根據task的交互程度動態調整task優先級;
        iv.為real-time設計了靜態優先級。
        
        設計:
        i.為避免每次選擇執行task時,遍歷所有task,這里使用兩個數組來裝載task——active and expired array(list),從active array中取出task進行執行,task耗盡分配的時間后,放入expired array。
        ii.將active及expired array按照140個優先級進行划分,這樣每個active或expired數組都是二維數組——含有140個元素,每個元素都是一個list;並且持有一個bitmap,用來標識140個list中,哪個list有task
        經此設計,每次schedule()先查bitmap,從低位開始,從有task的list中取出task來執行,而優先級一致的task按序執行即可,從而實現了O(1)的調度速度。
        iii.使用task's sleep time來標記交互式task,active array根據sleep time進行排序,這塊非常復雜,且容易異常情況態度,會導致各種各樣問題。
 
    d.內核調度分支——The Staircase Scheduler
        核心思想是在c的基礎上,高優先級task執行一次后,其優先級減1,並放入對應array中,等待下次執行。
 
    e.Default Scheduler CFS——Completely Fair Scheduler For Normal Task
        提出了根據不同類型task使用不同的調度策略的思想,real-time task使用“kernel-3.10.0-327.el7/linux-3.10.0-327.el7.centos.x86_64/kernel/sched/rt.c”進行調度,而normal task則使用fair.c進行調度;fair.c即是CFS的實現,針對的是normal task的調度,其思想是"根據one normal task's weight占total normal task weight總和百分比來決定CPU使用率,達到了理想的高度精確的多任務調度:
        i.重新設計的優先級,引入nice的概念,范圍為[-20,19],值越小,獲得CPU使用率越大;
        ii.理想的按nice數值控制的CPU使用率,即nice每上升1,則少獲取10%CPU;為達到精確控制,設計了prio_to_weight數組(見下圖),只有兩個nice為0的進程為,每個進程CPU使用率占比都為1024/(1024+1024);只有一個nice為0與1的進程是,nice為0進程CPU使用率為1024/(1024+820)=0.55,nice為1進程CPU使用率為0.45,兩者的CPU使用率相差10%,
        iii.使用Red-Black Tree來存取task,每次調度時間復雜度為O(lgN)
        iv.內核層面的優先級仍然為0-140,0-99為real-time task,100-139為normal task,向上兼容real-time task的調度,通過將nice值加上120(120=real-time task優先級個數100+nice值個數40的一半)得到priority,而priority減去120得到nice
        v.同時引入按組調度的概念,整體CPU使用率按組進行划分(如只有GroupA與B時,GroupA與B各占50%使用率)
 
3.el7.2代碼圖解(入口為紅色五角星)
 
 
 
 
4.參考資料:
  http://www.linuxjournal.com/magazine/real-time-linux-kernel-scheduler?page=0,0
  start_kernel():https://danielmaker.github.io/blog/linux/start_kernel.html
    http://blog.csdn.net/hlchou/article/details/7425416
  http://blog.csdn.net/gatieme/article/details/52067748系列
  [個人博客Linux kernel部分調度]
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM