1. 程式人生 > 遊戲攻略 >《艾爾登法環》白色腳印位置及打法 白色金色腳印怎麼打

《艾爾登法環》白色腳印位置及打法 白色金色腳印怎麼打

程序管理

程序概述

thread_info:儲存了特定體系結構的彙編程式碼段需要訪問的那部分程序的資料,放在核心棧頂,其中嵌入指向task_struct的指標

task_struct:通用的方式描述程序,核心使用slab管理task_stuct的分配和釋放,包含了mm_struct這個記憶體描述結構

thread_union:將核心棧(向下增長)和thread_info(所以在棧頂)放在這個聯合體

程序狀態:TASK_RUNNING,TASK_INTERRUPTABLE,TASK_UNINTERRUPTABLE,__TASK_TRACED,__TASK_STOPPED

程序建立:fork沒有複製所有資訊,而是在被使用時才複製(寫時拷貝),fork() -> clone() -> do_fork() -> copy_process(建立新的task_struct) -> dup_task_struct(分配一個核心棧,填充thread_info,task_struct)

執行緒:建立執行緒的時候,和建立程序類似,只不過在呼叫 clone 的時候,傳入了一些引數標誌,而且共享了地址空間、檔案系統資源、檔案描述符、訊號處理程式

kthread_create建立核心程序

1 : 構造了一個kthread_create_info 結構體,將其掛接到 kthread_create_list連結串列上

2 : 喚醒核心執行緒kthreadd去建立執行緒

程序排程

排程器

分配程序執行時間,並通過排程演算法,切換兩個程序的上下文

優先順序

靜態優先順序:範圍為100-139(MAX_RT_PRIO - MAX_PRIO-1),核心2.6中的靜態優先順序相當於核心2.4中的nice值

-20,19),但轉到MAX_RT_PRIO到MAX_PRIO-1取值範圍,其公式為:static priority = nice + 20 + MAX_RT_PRIO;核心定義兩個巨集來實現此轉化:nice_to_prio() and prio_to_nice();實時和非實時程序都一樣可通過nice()和setpriority()改變,以影響基時間片

動態優先順序:範圍與靜態優先順序相同。動態優先順序是排程器選擇一個程序時實際參考的值。平均睡眠時間越大,bonus值越大,其動態優先順序越大;dynamic priority = max( 100, min((static priority - bonus + 5), 139));實時程序的動態優先順序不會改變

實時優先順序:取值範圍0-MAX_RT_PRIO-1。其大小可以通過sched_setscheduler()和sched_setparam()來改變

排程器類

允許不同的可動態新增的排程演算法並存,總排程器根據排程器類的優先順序,依次排程進行排程器類的中的程序,Stop_ask > RealTime > Fair > Idle_Task,通過sched_setscheduler可設定排程演算法

CFS:完全公平排程器,通過一個虛擬時鐘 vruntime= 實際執行時間 * 1024 / 程序權重(nice值為0,權重為1024),總是選擇 vruntime 最小的程序,讓其投入執行。他們被維護到一個以 vruntime 為順序的rbtree 中;分配的可執行時間 = 排程週期 *(程序權重 / 所有程序權重之和)

FIFO:是讓一個任務執行完再排程下一個任務,而順序就是依照建立的先後,只有更高優先順序的 SCHED_FIFO 或者 SCHED_RR 才能搶佔它的任務

RR:依據時間片來排程的,當時間片用完時,無論這個程序優先順序有多高,都不會在執行,而是進入就緒佇列,等待下一個時間片到來

程序切換

自願切換髮生的時候,程序不再處於執行狀態,比如由於等待IO而阻塞(TASK_UNINTERRUPTIBLE),或者因等待資源和特定事件而休眠(TASK_INTERRUPTIBLE),又或者被debug/trace設定為TASK_STOPPED/TASK_TRACED狀態。

強制切換髮生的時候,程序仍然處於執行狀態(TASK_RUNNING),通常是由於被優先順序更高的程序搶佔(preempt),或者程序的時間片用完了。

程序自願切換(Voluntary)和強制切換(Involuntary)的次數被統計在 /proc/<pid>/status,檢視此值,判斷程序對cpu的需求度。

觸發搶佔

給正在CPU上執行的當前程序設定一個請求重新排程的標誌(TIF_NEED_RESCHED),僅此而已,此時程序並沒有切換;觸發搶佔的時機如下:

週期性的時鐘中斷:呼叫scheduler_tick()檢查程序的時間片是否耗盡,如果耗盡則觸發搶佔

喚醒程序的時候:如果優先順序高於CPU上的當前程序,就會觸發搶佔;try_to_wake_up()最終通過check_preempt_curr()檢查是否觸發搶佔

新程序建立的時候:如果新程序的優先順序高於CPU上的當前程序,會觸發搶佔。相應的排程器核心層程式碼是sched_fork(),它再通過排程類的 task_fork方法觸發搶佔

程序修改nice值的時候:如果程序修改nice值導致優先順序高於CPU上的當前程序,也會觸發搶佔。核心程式碼參見 set_user_nice()

進行負載均衡的時候:程序排程器儘量使各個CPU之間的負載保持均衡,而負載均衡操作可能會需要觸發搶佔

執行搶佔

從系統呼叫(syscall)返回使用者態時

從中斷返回使用者態時

中斷返回:中斷處理程式返回核心空間之前會檢查TIF_NEED_RESCHED標誌,如果置位則呼叫preempt_schedule_irq()執行搶佔。preempt_schedule_irq()是對schedule()的包裝。

使能搶佔:當核心從non-preemptible(禁止搶佔)狀態變成preemptible(允許搶佔)的時候;
preempt_enable()中,會最終呼叫 preempt_schedule 來執行搶佔