當前位置:首頁 » 操作系統 » linux調度演算法

linux調度演算法

發布時間: 2022-06-28 17:33:24

linux內核同一個優先順序的任務怎麼調度的

  1. Linux內核中用task指代一切進程和線程。

  2. 調度的作用是安排所有可以運行的進程在CPU上的運行時間和次序

  3. 內核中主要有兩類調度演算法。其中的實時調度演算法中,對task有優先順序的概念,同一優先順序內的進程可以按照FIFO或RoundRobin的演算法進行調度。這兩種演算法都需要維護一個可運行進程的隊列。

② linux內核怎麼調度系統

1.調度器的概述

多任務操作系統分為非搶占式多任務和搶占式多任務。與大多數現代操作系統一樣,Linux採用的是搶占式多任務模式。這表示對CPU的佔用時間由操作系統決定的,具體為操作系統中的調度器。調度器決定了什麼時候停止一個進程以便讓其他進程有機會運行,同時挑選出一個其他的進程開始運行。

2.調度策略

在Linux上調度策略決定了調度器是如何選擇一個新進程的時間。調度策略與進程的類型有關,內核現有的調度策略如下:

#define SCHED_NORMAL 0#define SCHED_FIFO 1#define SCHED_RR 2#define SCHED_BATCH 3/* SCHED_ISO: reserved but not implemented yet */#define SCHED_IDLE 5

0: 默認的調度策略,針對的是普通進程。
1:針對實時進程的先進先出調度。適合對時間性要求比較高但每次運行時間比較短的進程。
2:針對的是實時進程的時間片輪轉調度。適合每次運行時間比較長得進程。
3:針對批處理進程的調度,適合那些非交互性且對cpu使用密集的進程。
SCHED_ISO:是內核的一個預留欄位,目前還沒有使用
5:適用於優先順序較低的後台進程。
註:每個進程的調度策略保存在進程描述符task_struct中的policy欄位

3.調度器中的機制

內核引入調度類(struct sched_class)說明了調度器應該具有哪些功能。內核中每種調度策略都有該調度類的一個實例。(比如:基於公平調度類為:fair_sched_class,基於實時進程的調度類實例為:rt_sched_class),該實例也是針對每種調度策略的具體實現。調度類封裝了不同調度策略的具體實現,屏蔽了各種調度策略的細節實現。
調度器核心函數schele()只需要調用調度類中的介面,完成進程的調度,完全不需要考慮調度策略的具體實現。調度類連接了調度函數和具體的調度策略。

  • 武特師兄關於sche_class和sche_entity的解釋,一語中的。

  • 調度類就是代表的各種調度策略,調度實體就是調度單位,這個實體通常是一個進程,但是自從引入了cgroup後,這個調度實體可能就不是一個進程了,而是一個組

  • 4.schele()函數

    linux 支持兩種類型的進程調度,實時進程和普通進程。實時進程採用SCHED_FIFO 和SCHED_RR調度策略,普通進程採用SCHED_NORMAL策略。
    preempt_disable():禁止內核搶占
    cpu_rq():獲取當前cpu對應的就緒隊列。
    prev = rq->curr;獲取當前進程的描述符prev
    switch_count = &prev->nivcsw;獲取當前進程的切換次數。
    update_rq_clock() :更新就緒隊列上的時鍾
    clear_tsk_need_resched()清楚當前進程prev的重新調度標志。
    deactive_task():將當前進程從就緒隊列中刪除。
    put_prev_task() :將當前進程重新放入就緒隊列
    pick_next_task():在就緒隊列中挑選下一個將被執行的進程。
    context_switch():進行prev和next兩個進程的切換。具體的切換代碼與體系架構有關,在switch_to()中通過一段匯編代碼實現。
    post_schele():進行進程切換後的後期處理工作。

    5.pick_next_task函數

    選擇下一個將要被執行的進程無疑是一個很重要的過程,我們來看一下內核中代碼的實現
    對以下這段代碼說明:
    1.當rq中的運行隊列的個數(nr_running)和cfs中的nr_runing相等的時候,表示現在所有的都是普通進程,這時候就會調用cfs演算法中的pick_next_task(其實是pick_next_task_fair函數),當不相等的時候,則調用sched_class_highest(這是一個宏,指向的是實時進程),這下面的這個for(;;)循環中,首先是會在實時進程中選取要調度的程序(p = class->pick_next_task(rq);)。如果沒有選取到,會執行class=class->next;在class這個鏈表中有三種類型(fair,idle,rt).也就是說會調用到下一個調度類。

  • static inline struct task_struct *pick_next_task(struct rq *rq){ const struct sched_class *class; struct task_struct *p; /*

  • * Optimization: we know that if all tasks are in

  • * the fair class we can call that function directly:

  • *///基於公平調度的普通進程

  • if (likely(rq->nr_running == rq->cfs.nr_running)) {

  • p = fair_sched_class.pick_next_task(rq); if (likely(p)) return p;

  • }//基於實時調度的實時進程

  • class = sched_class_highest; for ( ; ; ) {

  • p = class->pick_next_task(rq); //實時進程的類

  • if (p) return p; /*

  • * Will never be NULL as the idle class always

  • * returns a non-NULL p:

  • */

  • class = class->next; //rt->next = fair; fair->next = idle

  • }

  • }

  • 在這段代碼中體現了Linux所支持的兩種類型的進程,實時進程和普通進程。回顧下:實時進程可以採用SCHED_FIFO 和SCHED_RR調度策略,普通進程採用SCHED_NORMAL調度策略。
    在這里首先說明一個結構體struct rq,這個結構體是調度器管理可運行狀態進程的最主要的數據結構。每個cpu上都有一個可運行的就緒隊列。剛才在pick_next_task函數中看到了在選擇下一個將要被執行的進程時實際上用的是struct rq上的普通進程的調度或者實時進程的調度,那麼具體是如何調度的呢?在實時調度中,為了實現O(1)的調度演算法,內核為每個優先順序維護一個運行隊列和一個DECLARE_BITMAP,內核根據DECLARE_BITMAP的bit數值找出非空的最高級優先隊列的編號,從而可以從非空的最高級優先隊列中取出進程進行運行。
    我們來看下內核的實現

  • struct rt_prio_array {

  • DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */

  • struct list_head queue[MAX_RT_PRIO];

  • };

  • 數組queue[i]裡面存放的是優先順序為i的進程隊列的鏈表頭。在結構體rt_prio_array 中有一個重要的數據構DECLARE_BITMAP,它在內核中的第一如下:

  • define DECLARE_BITMAP(name,bits)

  • unsigned long name[BITS_TO_LONGS(bits)]

  • 5.1對於實時進程的O(1)演算法

    這個數據是用來作為進程隊列queue[MAX_PRIO]的索引點陣圖。bitmap中的每一位與queue[i]對應,當queue[i]的進程隊列不為空時,Bitmap的相應位就為1,否則為0,這樣就只需要通過匯編指令從進程優先順序由高到低的方向找到第一個為1的位置,則這個位置就是就緒隊列中最高的優先順序(函數sched_find_first_bit()就是用來實現該目的的)。那麼queue[index]->next就是要找的候選進程。
    如果還是不懂,那就來看兩個圖

    由結果可以看出當nice的值越小的時候,其睡眠時間越短,則表示其優先順序升高了。

    7.關於獲取和設置優先順序的系統調用:sched_getscheler()和sched_setscheler

  • #include <sched.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#define DEATH(mess) { perror(mess); exit(errno); }void printpolicy (int policy){ /* SCHED_NORMAL = SCHED_OTHER in user-space */


  • if (policy == SCHED_OTHER) printf ("policy = SCHED_OTHER = %d ", policy); if (policy == SCHED_FIFO) printf ("policy = SCHED_FIFO = %d ", policy); if (policy == SCHED_RR) printf ("policy = SCHED_RR = %d ", policy);

  • }int main (int argc, char **argv){ int policy; struct sched_param p; /* obtain current scheling policy for this process */

  • //獲取進程調度的策略

  • policy = sched_getscheler (0);

  • printpolicy (policy); /* reset scheling policy */


  • printf (" Trying sched_setscheler... ");

  • policy = SCHED_FIFO;

  • printpolicy (policy);

  • p.sched_priority = 50; //設置優先順序為50

  • if (sched_setscheler (0, policy, &p))

  • DEATH ("sched_setscheler:"); printf ("p.sched_priority = %d ", p.sched_priority); exit (0);

  • }

  • 輸出結果:

  • [root@wang schele]# ./get_schele_policy policy = SCHED_OTHER = 0


  • Trying sched_setscheler...

  • policy = SCHED_FIFO = 1

  • p.sched_priority = 50

  • 可以看出進程的優先順序已經被改變。

③ linux內核進程調度子系統根據什麼演算法選擇最值得運行的進程

你可以查看相關linux書籍關於這部分的介紹。
操作系統這一門課程回答了你的答案。
據我的了解,應該是多級反饋輪轉調度的演算法。
每個進程都是按時間片運行的。每個進程都被分配了優先順序。
每個進程位於調度隊列的某一級上。操作系統根據這個多級隊列來調度。
每個隊列按照FIFO的方式調度。
就這么多了。你可以去圖書館借書看看。

④ 請教linux下用戶態進程調度問題

在進行Linux系統操作的時候,有時候會遇到一次用戶態進程死循環,即系統反應遲鈍、進程掛死等問題,那麼遇到這些問題又該如何解決呢?下面小編就給大家介紹下一次用戶態進程死循環的問題該如何處理。
Linux下如何處理一次用戶態進程死循環問題
1、問題現象
業務進程(用戶態多線程程序)掛死,操作系統反應遲鈍,系統日誌沒有任何異常。從進程的內核態堆棧看,看似所有線程都卡在了內核態的如下堆棧流程中:
[root@vmc116 ~]# cat /proc/27007/task/11825/stack
[《ffffffff8100baf6》] retint_careful+0x14/0x32
[《ffffffffffffffff》] 0xffffffffffffffff
2、問題分析
1)內核堆棧分析
從內核堆棧看,所有進程都阻塞在 retint_careful上,這個是中斷返回過程中的流程,代碼(匯編)如下:
entry_64.S
代碼如下:
ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
/* Restore saved previous stack */
popq %rsi
CFI_DEF_CFA rsi,SS+8-RBP /* reg/off reset after def_cfa_expr */
leaq ARGOFFSET-RBP(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET
。。。
retint_careful:
CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
pushq_cfi %rdi
SCHEDULE_USER
popq_cfi %rdi
GET_THREAD_INFO(%rcx)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
jmp retint_check
這其實是用戶態進程在用戶態被中斷打斷後,從中斷返回的流程,結合retint_careful+0x14/0x32,進行反匯編,可以確認阻塞的點其實就在
SCHEDULE_USER
這其實就是調用schele()進行調度,也就是說當進程走到中斷返回的流程中時,發現需要調度(設置了TIF_NEED_RESCHED),於是在這里發生了調度。
有一個疑問:為什麼在堆棧中看不到schele()這一級的棧幀呢?
因為這里是匯編直接調用的,沒有進行相關棧幀壓棧和上下文保存操作。
2)進行狀態信息分析
從top命令結果看,相關線程實際一直處於R狀態,CPU幾乎完全耗盡,而且絕大部分都消耗在用戶態:
[root@vmc116 ~]# top
top - 09:42:23 up 16 days, 2:21, 23 users, load average: 84.08, 84.30, 83.62
Tasks: 1037 total, 85 running, 952 sleeping, 0 stopped, 0 zombie
Cpu(s): 97.6%us, 2.2%sy, 0.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32878852k total, 32315464k used, 563388k free, 374152k buffers
Swap: 35110904k total, 38644k used, 35072260k free, 28852536k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27074 root 20 0 5316m 163m 14m R 10.2 0.5 321:06.17 z_itask_templat
27084 root 20 0 5316m 163m 14m R 10.2 0.5 296:23.37 z_itask_templat
27085 root 20 0 5316m 163m 14m R 10.2 0.5 337:57.26 z_itask_templat
27095 root 20 0 5316m 163m 14m R 10.2 0.5 327:31.93 z_itask_templat
27102 root 20 0 5316m 163m 14m R 10.2 0.5 306:49.44 z_itask_templat
27113 root 20 0 5316m 163m 14m R 10.2 0.5 310:47.41 z_itask_templat
25730 root 20 0 5316m 163m 14m R 10.2 0.5 283:03.37 z_itask_templat
30069 root 20 0 5316m 163m 14m R 10.2 0.5 283:49.67 z_itask_templat
13938 root 20 0 5316m 163m 14m R 10.2 0.5 261:24.46 z_itask_templat
16326 root 20 0 5316m 163m 14m R 10.2 0.5 150:24.53 z_itask_templat
6795 root 20 0 5316m 163m 14m R 10.2 0.5 100:26.77 z_itask_templat
27063 root 20 0 5316m 163m 14m R 9.9 0.5 337:18.77 z_itask_templat
27065 root 20 0 5316m 163m 14m R 9.9 0.5 314:24.17 z_itask_templat
27068 root 20 0 5316m 163m 14m R 9.9 0.5 336:32.78 z_itask_templat
27069 root 20 0 5316m 163m 14m R 9.9 0.5 338:55.08 z_itask_templat
27072 root 20 0 5316m 163m 14m R 9.9 0.5 306:46.08 z_itask_templat
27075 root 20 0 5316m 163m 14m R 9.9 0.5 316:49.51 z_itask_templat
。。。
3)進程調度信息
從相關線程的調度信息看:
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15681811525768 129628804592612 3557465
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682016493013 129630684625241 3557509
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682843570331 129638127548315 3557686
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683323640217 129642447477861 3557793
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683698477621 129645817640726 3557875
發現相關線程的調度統計一直在增加,說明相關線程一直是在被調度運行的,結合其狀態也一直是R,推測很可能在用戶態發生了死循環(或者非睡眠死鎖)。
這里又有問題:為什麼從top看每個線程的CPU佔用率只有10%左右,而不是通常看到的死循環進程導致的100%的佔用率?
因為線程數很多,而且優先順序都一樣,根據CFS調度演算法,會平均分配時間片,不會讓其中一個線程獨佔CPU。結果為多個線程間輪流調度,消耗掉了所有的cpu。。
另一個問題:為什麼這種情況下,內核沒有檢測到softlockup?
因為業務進程的優先順序不高,不會影響watchdog內核線程(最高優先順序的實時線程)的調度,所以不會產生softlockup的情況。
再一個問題:為什麼每次查看線程堆棧時,總是阻塞在retint_careful,而不是其它地方?
因為這里(中斷返回的時候)正是調度的時機點,在其它時間點不能發生調度(不考慮其它情況~),而我們查看線程堆棧的行為,也必須依賴於進程調度,所以我們每次查看堆棧時,正是查看堆棧的進程(cat命令)得到調度的時候,這時正是中斷返回的時候,所以正好看到的阻塞點為retint_careful。
4)用戶態分析
從上面的分析看,推測應該是用戶態發生了死鎖。
用戶態確認方法:
部署debug信息,然後gdb attach相關進程,確認堆棧,並結合代碼邏輯分析。
最終確認該問題確為用戶態進程中產生了死循環。

⑤ Linux如何進行進程調度引入線程機制後,進程管理內容包括哪些

進程調度的演算法有很多,簡單來說就是每個進程都有一個自己的時間片,時間到了,就會被掛起,然後系統挑選下一個合適的進程來執行。至於誰合適,那就要看演算法了,優先順序,是不是飢餓,I/O型還是運算型,都要考慮的。
調度演算法比較復雜龐大,不是這里說的清楚的。
進程切換的過程大概就是保存當前上下文,也就是各種寄存器的狀態,包括指令寄存器。然後把下一個進程的上下文載入上來。
有了線程機制之後,進程管理主要管理線程之間的數據共享,管理進程地址空間,進程的交換空間。因為這些資源是屬於進程的,線程之間是共享的。
​現代操作系統調度基本是圍繞線程進行的,進程更多的是起到資源管理分配的作用。

⑥ Linux內核的進程調度改進演算法設計(C語言)

運用操作系統里的概念,改進進程調度的策略,具體可查看一些Linux內核相關的操作系統書,裡面有不少通用演算法。
問題是,這個能搞出來嗎,貌似很難啊。。。

⑦ linux 進程調度演算法問題 主進程fork了 4個子進程a b c d 優先順序相等 一種

cb這是第一個fork的子進程產生的第一個fork父進程進入elseif先執行子進程輸出b這是第一個fork的父進程產生的父進程輸出ab所以一共是三個進程父——>父(產生父子)父——>子(終)

⑧ linux環境下的進程調度演算法有哪些

第一部分: 實時調度演算法介紹

對於什麼是實時系統,POSIX 1003.b作了這樣的定義:指系統能夠在限定的響應時間內提供所需水平的服務。而一個由Donald Gillies提出的更加為大家接受的定義是:一個實時系統是指計算的正確性不僅取決於程序的邏輯正確性,也取決於結果產生的時間,如果系統的時間約束條件得不到滿足,將會發生系統出錯。

實時系統根據其對於實時性要求的不同,可以分為軟實時和硬實時兩種類型。硬實時系統指系統要有確保的最壞情況下的服務時間,即對於事件的響應時間的截止期限是無論如何都必須得到滿足。比如航天中的宇宙飛船的控制等就是現實中這樣的系統。其他的所有有實時特性的系統都可以稱之為軟實時系統。如果明確地來說,軟實時系統就是那些從統計的角度來說,一個任務(在下面的論述中,我們將對任務和進程不作區分)能夠得到有確保的處理時間,到達系統的事件也能夠在截止期限到來之前得到處理,但違反截止期限並不會帶來致命的錯誤,像實時多媒體系統就是一種軟實時系統。

一個計算機系統為了提供對於實時性的支持,它的操作系統必須對於CPU和其他資源進行有效的調度和管理。在多任務實時系統中,資源的調度和管理更加復雜。本文下面將先從分類的角度對各種實時任務調度演算法進行討論,然後研究普通的 Linux操作系統的進程調度以及各種實時Linux系統為了支持實時特性對普通Linux系統所做的改進。最後分析了將Linux操作系統應用於實時領域中時所出現的一些問題,並總結了各種實時Linux是如何解決這些問題的。

1. 實時CPU調度演算法分類

各種實時操作系統的實時調度演算法可以分為如下三種類別[Wang99][Gopalan01]:基於優先順序的調度演算法(Priority-driven scheling-PD)、基於CPU使用比例的共享式的調度演算法(Share-driven scheling-SD)、以及基於時間的進程調度演算法(Time-driven scheling-TD),下面對這三種調度演算法逐一進行介紹。

1.1. 基於優先順序的調度演算法

基於優先順序的調度演算法給每個進程分配一個優先順序,在每次進程調度時,調度器總是調度那個具有最高優先順序的任務來執行。根據不同的優先順序分配方法,基於優先順序的調度演算法可以分為如下兩種類型[Krishna01][Wang99]:

靜態優先順序調度演算法:

這種調度演算法給那些系統中得到運行的所有進程都靜態地分配一個優先順序。靜態優先順序的分配可以根據應用的屬性來進行,比如任務的周期,用戶優先順序,或者其它的預先確定的策略。RM(Rate-Monotonic)調度演算法是一種典型的靜態優先順序調度演算法,它根據任務的執行周期的長短來決定調度優先順序,那些具有小的執行周期的任務具有較高的優先順序。

動態優先順序調度演算法:

這種調度演算法根據任務的資源需求來動態地分配任務的優先順序,其目的就是在資源分配和調度時有更大的靈活性。非實時系統中就有很多這種調度演算法,比如短作業優先的調度演算法。在實時調度演算法中, EDF演算法是使用最多的一種動態優先順序調度演算法,該演算法給就緒隊列中的各個任務根據它們的截止期限(Deadline)來分配優先順序,具有最近的截止期限的任務具有最高的優先順序。

1.2. 基於比例共享調度演算法

雖然基於優先順序的調度演算法簡單而有效,但這種調度演算法提供的是一種硬實時的調度,在很多情況下並不適合使用這種調度演算法:比如象實時多媒體會議系統這樣的軟實時應用。對於這種軟實時應用,使用一種比例共享式的資源調度演算法(SD演算法)更為適合。

比例共享調度演算法指基於CPU使用比例的共享式的調度演算法,其基本思想就是按照一定的權重(比例)對一組需要調度的任務進行調度,讓它們的執行時間與它們的權重完全成正比。

我們可以通過兩種方法來實現比例共享調度演算法[Nieh01]:第一種方法是調節各個就緒進程出現在調度隊列隊首的頻率,並調度隊首的進程執行;第二種做法就是逐次調度就緒隊列中的各個進程投入運行,但根據分配的權重調節分配個每個進程的運行時間片。

比例共享調度演算法可以分為以下幾個類別:輪轉法、公平共享、公平隊列、彩票調度法(Lottery)等。

比例共享調度演算法的一個問題就是它沒有定義任何優先順序的概念;所有的任務都根據它們申請的比例共享CPU資源,當系統處於過載狀態時,所有的任務的執行都會按比例地變慢。所以為了保證系統中實時進程能夠獲得一定的CPU處理時間,一般採用一種動態調節進程權重的方法。

1.3. 基於時間的進程調度演算法

對於那些具有穩定、已知輸入的簡單系統,可以使用時間驅動(Time-driven:TD)的調度演算法,它能夠為數據處理提供很好的預測性。這種調度演算法本質上是一種設計時就確定下來的離線的靜態調度方法。在系統的設計階段,在明確系統中所有的處理情況下,對於各個任務的開始、切換、以及結束時間等就事先做出明確的安排和設計。這種調度演算法適合於那些很小的嵌入式系統、自控系統、感測器等應用環境。

這種調度演算法的優點是任務的執行有很好的可預測性,但最大的缺點是缺乏靈活性,並且會出現有任務需要被執行而CPU卻保持空閑的情況。

2. 通用Linux系統中的CPU調度

通用Linux系統支持實時和非實時兩種進程,實時進程相對於普通進程具有絕對的優先順序。對應地,實時進程採用SCHED_FIFO或者SCHED_RR調度策略,普通的進程採用SCHED_OTHER調度策略。

在調度演算法的實現上,Linux中的每個任務有四個與調度相關的參數,它們是rt_priority、policy、priority(nice)、counter。調度程序根據這四個參數進行進程調度。

在SCHED_OTHER 調度策略中,調度器總是選擇那個priority+counter值最大的進程來調度執行。從邏輯上分析,SCHED_OTHER調度策略存在著調度周期(epoch),在每一個調度周期中,一個進程的priority和counter值的大小影響了當前時刻應該調度哪一個進程來執行,其中 priority是一個固定不變的值,在進程創建時就已經確定,它代表了該進程的優先順序,也代表這該進程在每一個調度周期中能夠得到的時間片的多少; counter是一個動態變化的值,它反映了一個進程在當前的調度周期中還剩下的時間片。在每一個調度周期的開始,priority的值被賦給 counter,然後每次該進程被調度執行時,counter值都減少。當counter值為零時,該進程用完自己在本調度周期中的時間片,不再參與本調度周期的進程調度。當所有進程的時間片都用完時,一個調度周期結束,然後周而復始。另外可以看出Linux系統中的調度周期不是靜態的,它是一個動態變化的量,比如處於可運行狀態的進程的多少和它們priority值都可以影響一個epoch的長短。值得注意的一點是,在2.4以上的內核中, priority被nice所取代,但二者作用類似。

可見SCHED_OTHER調度策略本質上是一種比例共享的調度策略,它的這種設計方法能夠保證進程調度時的公平性--一個低優先順序的進程在每一個epoch中也會得到自己應得的那些CPU執行時間,另外它也提供了不同進程的優先順序區分,具有高priority值的進程能夠獲得更多的執行時間。

對於實時進程來說,它們使用的是基於實時優先順序rt_priority的優先順序調度策略,但根據不同的調度策略,同一實時優先順序的進程之間的調度方法有所不同:

SCHED_FIFO:不同的進程根據靜態優先順序進行排隊,然後在同一優先順序的隊列中,誰先准備好運行就先調度誰,並且正在運行的進程不會被終止直到以下情況發生:1.被有更高優先順序的進程所強佔CPU;2.自己因為資源請求而阻塞;3.自己主動放棄CPU(調用sched_yield);

SCHED_RR:這種調度策略跟上面的SCHED_FIFO一模一樣,除了它給每個進程分配一個時間片,時間片到了正在執行的進程就放棄執行;時間片的長度可以通過sched_rr_get_interval調用得到;

由於Linux系統本身是一個面向桌面的系統,所以將它應用於實時應用中時存在如下的一些問題:

Linux系統中的調度單位為10ms,所以它不能夠提供精確的定時;

當一個進程調用系統調用進入內核態運行時,它是不可被搶占的;

Linux內核實現中使用了大量的封中斷操作會造成中斷的丟失;

由於使用虛擬內存技術,當發生頁出錯時,需要從硬碟中讀取交換數據,但硬碟讀寫由於存儲位置的隨機性會導致隨機的讀寫時間,這在某些情況下會影響一些實時任務的截止期限;

雖然Linux進程調度也支持實時優先順序,但缺乏有效的實時任務的調度機制和調度演算法;它的網路子系統的協議處理和其它設備的中斷處理都沒有與它對應的進程的調度關聯起來,並且它們自身也沒有明確的調度機制;

3. 各種實時Linux系統

3.1. RT-Linux和RTAI

RT -Linux是新墨西哥科技大學(New Mexico Institute of Technology)的研究成果[RTLinuxWeb][Barabanov97]。它的基本思想是,為了在Linux系統中提供對於硬實時的支持,它實現了一個微內核的小的實時操作系統(我們也稱之為RT-Linux的實時子系統),而將普通Linux系統作為一個該操作系統中的一個低優先順序的任務來運行。另外普通Linux系統中的任務可以通過FIFO和實時任務進行通信。RT-Linux的框架如圖 1所示:

圖 1 RT-Linux結構

RT -Linux的關鍵技術是通過軟體來模擬硬體的中斷控制器。當Linux系統要封鎖CPU的中斷時時,RT-Linux中的實時子系統會截取到這個請求,把它記錄下來,而實際上並不真正封鎖硬體中斷,這樣就避免了由於封中斷所造成的系統在一段時間沒有響應的情況,從而提高了實時性。當有硬體中斷到來時, RT-Linux截取該中斷,並判斷是否有實時子系統中的中斷常式來處理還是傳遞給普通的Linux內核進行處理。另外,普通Linux系統中的最小定時精度由系統中的實時時鍾的頻率決定,一般Linux系統將該時鍾設置為每秒來100個時鍾中斷,所以Linux系統中一般的定時精度為 10ms,即時鍾周期是10ms,而RT-Linux通過將系統的實時時鍾設置為單次觸發狀態,可以提供十幾個微秒級的調度粒度。

RT-Linux實時子系統中的任務調度可以採用RM、EDF等優先順序驅動的演算法,也可以採用其他調度演算法。

RT -Linux對於那些在重負荷下工作的專有系統來說,確實是一個不錯的選擇,但他僅僅提供了對於CPU資源的調度;並且實時系統和普通Linux系統關系不是十分密切,這樣的話,開發人員不能充分利用Linux系統中已經實現的功能,如協議棧等。所以RT-Linux適合與工業控制等實時任務功能簡單,並且有硬實時要求的環境中,但如果要應用與多媒體處理中還需要做大量的工作。

義大利的RTAI( Real-Time Application Interface )源於RT-Linux,它在設計思想上和RT-Linux完全相同。它當初設計目的是為了解決RT-Linux難於在不同Linux版本之間難於移植的問題,為此,RTAI在 Linux 上定義了一個實時硬體抽象層,實時任務通過這個抽象層提供的介面和Linux系統進行交互,這樣在給Linux內核中增加實時支持時可以盡可能少地修改 Linux的內核源代碼。

3.2. Kurt-Linux

Kurt -Linux由Kansas大學開發,它可以提供微秒級的實時精度[KurtWeb] [Srinivasan]。不同於RT-Linux單獨實現一個實時內核的做法,Kurt -Linux是在通用Linux系統的基礎上實現的,它也是第一個可以使用普通Linux系統調用的基於Linux的實時系統。

Kurt-Linux將系統分為三種狀態:正常態、實時態和混合態,在正常態時它採用普通的Linux的調度策略,在實時態只運行實時任務,在混合態實時和非實時任務都可以執行;實時態可以用於對於實時性要求比較嚴格的情況。

為了提高Linux系統的實時特性,必須提高系統所支持的時鍾精度。但如果僅僅簡單地提高時鍾頻率,會引起調度負載的增加,從而嚴重降低系統的性能。為了解決這個矛盾, Kurt-Linux採用UTIME所使用的提高Linux系統中的時鍾精度的方法[UTIMEWeb]:它將時鍾晶元設置為單次觸發狀態(One shot mode),即每次給時鍾晶元設置一個超時時間,然後到該超時事件發生時在時鍾中斷處理程序中再次根據需要給時鍾晶元設置一個超時時間。它的基本思想是一個精確的定時意味著我們需要時鍾中斷在我們需要的一個比較精確的時間發生,但並非一定需要系統時鍾頻率達到此精度。它利用CPU的時鍾計數器TSC (Time Stamp Counter)來提供精度可達CPU主頻的時間精度。

對於實時任務的調度,Kurt-Linux採用基於時間(TD)的靜態的實時CPU調度演算法。實時任務在設計階段就需要明確地說明它們實時事件要發生的時間。這種調度演算法對於那些循環執行的任務能夠取得較好的調度效果。

Kurt -Linux相對於RT-Linux的一個優點就是可以使用Linux系統自身的系統調用,它本來被設計用於提供對硬實時的支持,但由於它在實現上只是簡單的將Linux調度器用一個簡單的時間驅動的調度器所取代,所以它的實時進程的調度很容易受到其它非實時任務的影響,從而在有的情況下會發生實時任務的截止期限不能滿足的情況,所以也被稱作嚴格實時系統(Firm Real-time)。目前基於Kurt-Linux的應用有:ARTS(ATM Reference Traffic System)、多媒體播放軟體等。另外Kurt-Linux所採用的這種方法需要頻繁地對時鍾晶元進行編程設置。

3.3. RED-Linux

RED -Linux是加州大學Irvine分校開發的實時Linux系統[REDWeb][ Wang99],它將對實時調度的支持和Linux很好地實現在同一個操作系統內核中。它同時支持三種類型的調度演算法,即:Time-Driven、 Priority-Dirven、Share-Driven。

為了提高系統的調度粒度,RED-Linux從RT-Linux那兒借鑒了軟體模擬中斷管理器的機制,並且提高了時鍾中斷頻率。當有硬體中斷到來時,RED-Linux的中斷模擬程序僅僅是簡單地將到來的中斷放到一個隊列中進行排隊,並不執行真正的中斷處理程序。

另外為了解決Linux進程在內核態不能被搶占的問題, RED-Linux在Linux內核的很多函數中插入了搶占點原語,使得進程在內核態時,也可以在一定程度上被搶占。通過這種方法提高了內核的實時特性。

RED-Linux的設計目標就是提供一個可以支持各種調度演算法的通用的調度框架,該系統給每個任務增加了如下幾項屬性,並將它們作為進程調度的依據:

Priority:作業的優先順序;

Start-Time:作業的開始時間;

Finish-Time:作業的結束時間;

Budget:作業在運行期間所要使用的資源的多少;

通過調整這些屬性的取值及調度程序按照什麼樣的優先順序來使用這些屬性值,幾乎可以實現所有的調度演算法。這樣的話,可以將三種不同的調度演算法無縫、統一地結合到了一起。

⑨ 誰有linux i/o 調度演算法deadline,anticipatory,noop,cfq中各個調優參數的具體作用。

1.Deadline scheler Deadline scheler 用 deadline 演算法保證對於既定的 IO 請求以最小的延遲時間,從這一點理解,對於 DSS 應用應該會是很適合的。
2.Anticipatory scheler(as) 曾經一度是 Linux 2.6 Kernel 的 IO scheler 。Anticipatory 的中文含義是」預料的, 預想的」, 這個詞的確揭示了這個演算法的特點,簡單的說,有個 IO 發生的時候,如果又有進程請求 IO 操作,則將產生一個默認的 6 毫秒猜測時間,猜測下一個 進程請求 IO 是要干什麼的。這對於隨即讀取會造成比較大的延時,對資料庫應用很糟糕,而對於 Web Server 等則會表現的不錯。這個演算法也可以簡單理解為面向低速磁碟的,因為那個」猜測」實際上的目的是為了減少磁頭移動時間。
3.Completely Fair Queuing 雖然這世界上沒有完全公平的事情,但是並不妨礙開源愛好者們設計一個完全公平的 IO 調度演算法。Completely Fair Queuing (cfq, 完全公平隊列) 在 2.6.18 取代了 Anticipatory scheler 成為 Linux Kernel 默認的 IO scheler 。cfq 對每個進程維護一個 IO 隊列,各個進程發來的 IO 請求會被 cfq 以輪循方式處理。也就是對每一個 IO 請求都是公平的。這使得 cfq 很適合離散讀的應用(eg: OLTP DB)。我所知道的企業級 Linux 發行版中,SuSE Linux 好像是最先默認用 cfq 的.
4.NOOP Noop 對於 IO 不那麼操心,對所有的 IO請求都用 FIFO 隊列形式處理,默認認為 IO 不會存在性能問題。這也使得 CPU 也不用那麼操心。當然,對於復雜一點的應用類型,使用這個調度器,用戶自己就會非常操心。

⑩ Linux上CFS調度演算法與實時調度演算法的區別

1、實時調度優先於CFS。
2、CFS是按照各進程靜態優先順序的比例進行時間的分配,在一個周期內各進程都有運行機會;實時調度總是調度實時優先順序最高的進程運行,運行時間和機會上都不公平。

熱點內容
在系統編程 發布:2024-04-19 08:54:55 瀏覽:234
visualstudio反編譯 發布:2024-04-19 08:44:46 瀏覽:319
ise怎麼配置晶元 發布:2024-04-19 08:27:31 瀏覽:997
免費搭建在線查詢伺服器 發布:2024-04-19 08:17:28 瀏覽:46
vs資料庫實例 發布:2024-04-19 08:14:54 瀏覽:295
vfp9反編譯 發布:2024-04-19 08:11:31 瀏覽:381
火車軟卧無線密碼是多少 發布:2024-04-19 07:38:59 瀏覽:423
vb系統文件夾 發布:2024-04-19 07:29:58 瀏覽:740
qt怎麼添加文件夾 發布:2024-04-19 07:22:53 瀏覽:256
sql查詢表是否存在 發布:2024-04-19 06:11:48 瀏覽:623