linux进程调度之 FIFO 和 RR 调度策略
生活随笔
收集整理的這篇文章主要介紹了
linux进程调度之 FIFO 和 RR 调度策略
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉載 http://blog.chinaunix.net/uid-24774106-id-3379478.html? linux進程調度之 FIFO 和 RR 調度策略?2012-10-19 18:16:43
? ? 在用戶空間,或者應用編程領域 ,Linux提供了一些API或者系統調用來影響Linux的內核調度器,或者是獲取內核調度器的信息。比如可以獲取或者設置進程的調度策略、優先級,獲取CPU時間片大小的信息。 ? ? ? 這些接口一旦在應用程序中調用,就像給湖面扔進一顆石子,對內核帶來了那些的影響,其實這是我內心很激動很想分享的東西,但是內容好沒有組織好,所以本文的主題暫不深入涉及這些系統調用及對應的內核層的代碼。 ? ? ? 嚴格地說,對于優先級對于實時進程和普通進程的意義是不一樣的。 ? ? 1 在一定程度上,實時進程優先級高,實時進程存在,就沒有普通進程占用CPU的機會,(但是前一篇博文也講過了,實時組調度出現在內核以后,允許普通進程占用少量的CPU時間,取決于配置)。 ? ? 2 對于實時進程而言,高優先級的進程存在,低優先級的進程是輪不上的,沒機會跑在CPU上,所謂實時進程的調度策略,指的是相同優先級之間的調度策略。如果是FIFO實時進程在占用CPU,除非出現以下事情,否則FIFO一條道跑到黑。 ? ? ?a)FIFO進程良心發現,調用了系統調用sched_yield 自愿讓出CPU ? ? ?b) 更高優先級的進程橫空出世,搶占FIFO進程的CPU。有些人覺得很奇怪,怎么FIFO占著CPU,為啥還能有更高優先級的進程出現呢。別忘記,我們是多核多CPU ,如果其他CPU上出現了一個比FIFO優先級高的進程,可能會push到FIFO進程所在的CPU上。 ? ? ?c)FIFO進程停止(TASK_STOPPED or TASK_TRACED狀態)或者被殺死(EXIT_ZOMBIE or EXIT_DEAD狀態) ? ? d) FIFO進程執行了阻塞調用并進入睡眠(TASK_INTERRUPTIBLE OR TASK_UNINTERRUPTIBLE)。 ? ?? ? ? 如果是進程的調度策略是時間片輪轉RR,那么,除了前面提到的abcd,RR實時進程耗盡自己的時間片后,自動退到對應優先級實時隊列的隊尾,重新調度。 ? ? ? 下面我們就是來探究FIFO策略和RR策略的特點。為了降低理解的難度,我將我們啟動的實時進程綁定到同一個核上。
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/time.h> #include<sys/types.h> #include<sys/sysinfo.h> #include<time.h> #define __USE_GNU #include<sched.h> #include<ctype.h> #include<string.h> #define COUNT 300000 #define MILLION 1000000L #define NANOSECOND 1000 void test_func() { ????int?i?=?0; ????unsigned long long result?=?0;; ????for(i?=?0;?i<8000?;i++) ????{ ????????result?+=?2; ????} } int?main(int?argc,char*?argv[]) { ????int?i; ????struct timespec sleeptm; ????long interval; ????struct timeval tend,tstart; ????struct tm lcltime?=?{0}; ????struct sched_param param; ????int?ret?=?0; ????if(argc?!=?3) ????{ ????????fprintf(stderr,"usage:./test sched_method sched_priority\n"); ????????return?-1; ????} ????cpu_set_t mask?; ????CPU_ZERO(&mask); ????CPU_SET(1,&mask); ????if?(sched_setaffinity(0,?sizeof(mask),?&mask)?==?-1)? ????{? ????????printf("warning: could not set CPU affinity, continuing...\n"); ????}? ????int?sched_method?=?atoi(argv[1]); ????int?sched_priority?=?atoi(argv[2]); ????/*????if(sched_method?>?2?||?sched_method?<?0) ????????{ ????????fprintf(stderr,"sched_method scope [0,2]\n"); ????????return?-2; ????????} ????????if(sched_priority?>?99?||?sched_priority?<?1) ????????{ ????????fprintf(stderr,"sched_priority scope [1,99]\n"); ????????return?-3; ????????} ????????if(sched_method?==?1?||?sched_method?==?2)*/ ????{ ????????param.sched_priority?=?sched_priority; ????????ret?=?sched_setscheduler(getpid(),sched_method,¶m); ????????if(ret) ????????{ ????????????fprintf(stderr,"set scheduler to %d %d failed %m\n"); ????????????return?-4; ????????} ????} ????int?scheduler?=?sched_getscheduler(getpid()); ????fprintf(stderr,"the scheduler of PID(%ld) is %d, priority (%d),BEGIN time is :%ld\n", ????????????getpid(),scheduler,sched_priority,time(NULL)); ????sleep(2); ????sleeptm.tv_sec?=?0; ????sleeptm.tv_nsec?=?NANOSECOND; ????for(i?=?0;i<COUNT;i++) ????{ ????????test_func(); ????} ? ????interval?=?MILLION*(tend.tv_sec?-?tstart.tv_sec) ? ? ? ? ? ? ? ?+(tend.tv_usec-tstart.tv_usec); ????fprintf(stderr," PID = %d\t priority: %d\tEND TIME is %ld\n",getpid(),sched_priority,time(NULL)); ????return 0; } ? ??上面這個程序有幾點需要說明的地方 ? ? 1 為了降低復雜度,綁定到了同一個核上,我做實驗的機器是四核(通過cat /proc/cpuinfo可以看到) ? ? 2 ?sleep(2),是給其他進程得到調度的機會,否則無法模擬出多個不同優先級的實時進程并行的場景。sleep過后,就沒有阻塞性的系統調用了,高優先級的就會占據CPU(FIFO),同等優先級的進程輪轉(RR)?
struct sched_param?{ /*?...?*/ int?sched_priority; /*?...?*/ }; int sched_setscheduler (pid_t pid, int policy, const struct sched_param *sp);
sched_setscheduler函數的第二個參數調度方法 :
#define SCHED_OTHER 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #ifdef __USE_GNU # define SCHED_BATCH 3 #endif ? ??SCHED_OTHER表示普通進程,對于普通進程,第三個參數sp->sched_priority只能是0 ? ?SCHED_FIFO 和SCHED_RR表示實時進程的調度策略,第三個參數的取值范圍為[1,99]。 ? ?如果sched_setscheduler 優先級設置的值和調度策略不符合的話,會返回失敗的。 ? ? ?內核中有這么一段注釋: /* ?????*?Valid priorities?for?SCHED_FIFO?and?SCHED_RR are ?????*?1..MAX_USER_RT_PRIO-1,?valid priority?for?SCHED_NORMAL, ?????*?SCHED_BATCH?and?SCHED_IDLE?is?0. ?????*/ ??? LINUX系統提供了其他的系統調用來獲取不同策略優先級的取值范圍: #include?<sched.h> int?sched_get_priority_min?(int?policy); int?sched_get_priority_max?(int?policy);
另外需要指出的一點是,應用層和內核層的優先級含義是不同的: ? ?首先說實時進程:實時進程的優先級設置可以通過sched_setsheduler設置,也可以通過sched_setparam設置優先級的大小。int?sched_setparam?(pid_t pid,?const?struct sched_param?*sp); ? ? 在用戶層或者應用層,1表示優先級最低,99表示優先級最高。但是在內核中,[0,99]表示的實時進程的優先級,0最高,99最低。[100,139]是普通進程折騰的范圍。應用層比較天真率直,就看大小,數字大,則優先級高。ps查看進程的優先級也是如此。有意思的是,應用層實時進程最高優先級的99,在ps看進程優先級的時候,輸出的是139. ? ? ? 下面是ps -C test -o pid,pri,cmd,time,psr 的輸出: PID ? PRI ?CMD ? ? ? ? ? ??TIME? ? ?PSR ?6303 139?./test 1 99 ?00:00:04 ? ? ? 1 ? ??雖說本文主要講的是實時進程,但是需要插句話。對于普通進程,是通過nice系統調用來調整優先級的。從內核角度講[100,139]是普通進程的優先級的范圍,100最高,139最低,默認是120。普通進程的優先級的作用和實時進程不同,普通進程優先級表示的是占的CPU時間。深入linux內核架構中提到,普通優先級越高(100最高,139最低),享受的CPU time越多,相鄰的兩個優先級,高一級的進程比低一級的進程多占用10%的CPU,比如內核優先級數值為120的進程要比數值是121的進程多占用10%的CPU。 ? ? ? 內核中有一個數組:prio_to_weight[20]表示的是默認優先級120的權重,數值為1024,prio_to_weight[21]表示nice值為1,優先級為121的進程的權重,數值為820。這就到了CFS的原理了 static?const?int?prio_to_weight[40]?=?{ ?/*?-20?*/?88761,?71755,?56483,?46273,?36291, ?/*?-15?*/?29154,?23254,?18705,?14949,?11916, ?/*?-10?*/?9548,?7620,?6100,?4904,?3906, ?/*?-5?*/?3121,?2501,?1991,?1586,?1277, ?/*?0?*/?1024,?820,?655,?526,?423, ?/*?5?*/?335,?272,?215,?172,?137, ?/*?10?*/?110,?87,?70,?56,?45, ?/*?15?*/?36,?29,?23,?18,?15, }; 假如有1臺電腦,10個人玩,怎么才公平。 1 約定好時間片,每人玩1小時,玩完后記賬,張XX 1小時,誰玩的時間短,誰去玩 ? ? 2 引入優先級的概念,李四有緊急情況,需要提高他玩電腦的時間,怎么辦,玩1個小時,記賬半小時,那么同等情況下,李四會比其他人被選中玩電腦的頻率要高,就體現了這個優先級的概念。 ? ? 3 ?王五也有緊急情況,但是以考察,不如李四的緊急,好吧,玩1個小時,記賬45分鐘。 ? ? 4 ?情況有變化,聽說這里有電腦,突然又來了10個人,如果按照每人玩1小時的時間片,排在最后的那哥們早就開始罵人了,怎么辦?時間片動態變化,根據人數來確定時間片。人越多,每個人玩的時間越少,防止哥們老撈不著玩,耐心耗盡,開始罵人。 ? ? ? 這個記賬就是我們prio_to_weight的作用。我就不多說了,prio_to_weight[20]就是基準,玩一小時,記賬一小時,數組20以前的值是特權一級,玩1小時記賬20分鐘之類的享有特權的,數組20之后是倒霉蛋,玩1小時,記賬1.5小時之類的倒霉蛋。 CFS這種調度好在大家都能撈著玩。 ? ? ? 扯到優先級多說了幾句,現在回到正題。我將上面的C程序編譯成可執行程序test,然后寫了一個腳本comp.sh。
[root@localhost sched]# cat comp.sh #/bin/sh ./test $1 99 & usleep 1000; ./test $1 70 & usleep 1000; ./test $1 70 & usleep 1000; ./test $1 70 & usleep 1000; ./test $1 50 & usleep 1000; ./test $1 30 & usleep 1000; ./test $1 10 & ? ? ???因為test進程有sleep 2秒,所以可以給comp.sh啟動其他test的機會。可以看到有 99級(最高優先級)的實時進程,3個70級的實時進程,50級,30級,10級的各一個。 ? ? ? 對于FIFO而言,一旦sleep過后,高優先級運行,低優先級是沒戲運行的,同等優先級的進程,先運行的不運行完,后運行的也沒戲。 ? ? ?對于RR而言,高優先級的先運行,同等優先級的進程過家家,你玩完,我玩,我玩完你再玩,每個進程耗費一個時間片的時間。對于Linux,RR時間片是100ms: ? #define DEF_TIMESLICE????????(100?*?HZ?/?1000) ?? ? ? 下面我們驗證: 我寫了兩個觀察腳本,來觀察實時進程的調度情況: ? ? ? 第一個腳本比較簡單,觀察進程的CPU 占用的time,用ps工具就可以了:
[root@localhost sched]# cat getpsinfo.sh #!/bin/sh for((i = 0; i < 40; i++)) do ? ? ps -C test -o pid,pri,cmd,time,psr >>psinfo.log 2>&1 ? ? sleep 2; done ? ? 第二個腳本比較復雜是systemtap腳本,觀察名字為test的進程相關的上下文切換,誰替換了test,或者test替換了誰,同時記錄下test進程的退出: [root@localhost sched]#?cat cswmon_spec.stp? global time_offset probe begin?{?time_offset?=?gettimeofday_us()?} probe scheduler.ctxswitch?{ ????if(next_task_name?==?"test"?||prev_task_name?==?"test") ????{ ? ? ? ? ?t?=?gettimeofday_us() ? ? ? ? ?printf(" time_off (%8d )%20s(%6d)(pri=%4d)(state=%d)->%20s(%6d)(pri=%4d)(state=%d)\n", ? ? ? ? ? ? ? ? ? t-time_offset, ? ? ? ? ? ? ? ? ? prev_task_name, ? ? ? ? ? ? ? ? ? prev_pid, ? ? ? ? ? ? ? ? ? prev_priority, ? ? ? ? ? ? ? ? ??(prevtsk_state), ? ? ? ? ? ? ? ? ? next_task_name, ? ? ? ? ? ? ? ? ? next_pid, ? ? ? ? ? ? ? ? ? next_priority, ? ? ? ? ? ? ? ? ??(nexttsk_state)) ????} } probe scheduler.process_exit { ????if(execname()?==?"test") ????printf("task :%s PID(%d) PRI(%d) EXIT\n",execname(),pid,priority); } probe timer.s($1)?{ ????printf("--------------------------------------------------------------\n") ????????exit(); } ? ? A) ? ?FIFO調度策略的輸出:
終端1 : stap ./cswmon_spec.stp 70 終端2 : ./getpsinfo.sh 終端3 ./comp.sh 1 輸出結果如下:
? ? 99優先級跑完了,才輪到70優先級,但是雖說有3個70優先級,但是先跑的那個進程跑完了,第二個優先級為70的才能跑。因為輸出結果用代碼無法漂亮的展示,所以我截了圖,截圖又不能把這個輸出都截下來,所以我很蛋疼。有需要結果的,我以附件形式附在最后。 ? ? 看下第二個腳本的輸出:
time_off ( 689546 ) test( 6305)(pri= 120)(state=0)-> migration/2( 11)(pri= 0)(state=0) time_off ( 689977 ) stap( 5895)(pri= 120)(state=0)-> test( 6305)(pri= 120)(state=0) time_off ( 690067 ) test( 6305)(pri= 29)(state=1)-> stap( 5895)(pri= 120)(state=0) time_off ( 697899 ) test( 6303)(pri= 120)(state=0)-> migration/2( 11)(pri= 0)(state=0) time_off ( 698042 ) test( 6307)(pri= 120)(state=0)-> migration/0( 3)(pri= 0)(state=0) time_off ( 699114 ) stap( 5895)(pri= 120)(state=0)-> test( 6303)(pri= 120)(state=0) time_off ( 699307 ) test( 6303)(pri= 0)(state=1)-> test( 6307)(pri= 120)(state=0) time_off ( 699371 ) test( 6307)(pri= 29)(state=1)-> stap( 5895)(pri= 120)(state=0) time_off ( 699392 ) test( 6309)(pri= 120)(state=0)-> migration/3( 15)(pri= 0)(state=0) time_off ( 699966 ) events/1( 20)(pri= 120)(state=1)-> test( 6309)(pri= 120)(state=0) time_off ( 700034 ) test( 6309)(pri= 29)(state=1)-> stap( 5895)(pri= 120)(state=0) time_off ( 707379 ) test( 6311)(pri= 120)(state=0)-> migration/3( 15)(pri= 0)(state=0) time_off ( 707587 ) test( 6313)(pri= 120)(state=0)-> migration/0( 3)(pri= 0)(state=0) time_off ( 712021 ) stap( 5895)(pri= 120)(state=0)-> test( 6311)(pri= 120)(state=0) time_off ( 712145 ) test( 6311)(pri= 49)(state=1)-> test( 6313)(pri= 120)(state=0) time_off ( 712252 ) test( 6313)(pri= 69)(state=1)-> stap( 5895)(pri= 120)(state=0) time_off ( 727057 ) test( 6315)(pri= 120)(state=0)-> migration/0( 3)(pri= 0)(state=0) time_off ( 727952 ) stap( 5895)(pri= 120)(state=0)-> test( 6315)(pri= 120)(state=0) time_off ( 728047 ) test( 6315)(pri= 89)(state=1)-> stap( 5895)(pri= 120)(state=0) time_off ( 2690181 ) stap( 5895)(pri= 120)(state=0)-> test( 6305)(pri= 29)(state=0) time_off ( 2699316 ) test( 6305)(pri= 29)(state=0)-> test( 6303)(pri= 0)(state=0) task :test PID(6303) PRI(0) EXIT time_off (13057854 ) test( 6303)(pri= 0)(state=64)-> watchdog/1( 10)(pri= 0)(state=0) time_off (13057864 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6305)(pri= 29)(state=0) time_off (15333340 ) test( 6305)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (15333354 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6305)(pri= 29)(state=0) time_off (18743409 ) test( 6305)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (18743422 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6305)(pri= 29)(state=0) time_off (22154757 ) test( 6305)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (22154771 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6305)(pri= 29)(state=0) task :test PID(6305) PRI(29) EXIT time_off (22466855 ) test( 6305)(pri= 29)(state=64)-> test( 6307)(pri= 29)(state=0) time_off (25563548 ) test( 6307)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (25563566 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6307)(pri= 29)(state=0) time_off (28973602 ) test( 6307)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (28973616 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6307)(pri= 29)(state=0) task :test PID(6307) PRI(29) EXIT time_off (31846121 ) test( 6307)(pri= 29)(state=64)-> test( 6309)(pri= 29)(state=0) time_off (32383671 ) test( 6309)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (32383683 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6309)(pri= 29)(state=0) time_off (35793735 ) test( 6309)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (35793747 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6309)(pri= 29)(state=0) time_off (39203797 ) test( 6309)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (39203809 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6309)(pri= 29)(state=0) task :test PID(6309) PRI(29) EXIT time_off (41200440 ) test( 6309)(pri= 29)(state=64)-> test( 6311)(pri= 49)(state=0) time_off (42613866 ) test( 6311)(pri= 49)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (42613898 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6311)(pri= 49)(state=0) time_off (46024070 ) test( 6311)(pri= 49)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (46024082 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6311)(pri= 49)(state=0) time_off (49434004 ) test( 6311)(pri= 49)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (49434017 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6311)(pri= 49)(state=0) task :test PID(6311) PRI(49) EXIT ? ? 可以清楚的可到,同樣是70優先級(內核態是29),6305退出以前,6307根本就撈不著跑。同樣6307退出一樣,6309根本就撈不著跑。這就是FIFO。 ? B) RR的情況
終端1 : stap ./cswmon_spec.stp 70 終端2 : ./getpsinfo.sh 終端3 ./comp.sh 1
? ? ? 實時優先級是70的三個進程齊頭并進。再看第二個腳本的輸出:
time_off ( 4188015 ) test( 6428)(pri= 0)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off ( 4188025 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6428)(pri= 0)(state=0) time_off ( 7612014 ) test( 6428)(pri= 0)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off ( 7612024 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6428)(pri= 0)(state=0) task :test PID(6428) PRI(0) EXIT time_off (10679062 ) test( 6428)(pri= 0)(state=64)-> test( 6430)(pri= 29)(state=0) time_off (10964413 ) test( 6430)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (10964422 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6430)(pri= 29)(state=0) time_off (11709024 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (12736030 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (13779022 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (13879021 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (13984075 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (14084020 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (14184023 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (14284024 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (14374486 ) test( 6434)(pri= 29)(state=0)-> watchdog/1( 10)(pri= 0)(state=0) time_off (14374502 ) watchdog/1( 10)(pri= 0)(state=1)-> test( 6434)(pri= 29)(state=0) time_off (14384097 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (14484066 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (14584023 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (14684020 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (14786032 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (14886020 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (14986026 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (15089023 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (15192030 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (15292026 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (15396085 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (15496022 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) time_off (15596027 ) test( 6434)(pri= 29)(state=0)-> test( 6430)(pri= 29)(state=0) time_off (15696153 ) test( 6430)(pri= 29)(state=0)-> test( 6432)(pri= 29)(state=0) time_off (15796022 ) test( 6432)(pri= 29)(state=0)-> test( 6434)(pri= 29)(state=0) ? ? 用戶態實時優先級為99,內核態優先級為0的進程6428退出后,3個用戶態實時優先級為70的進程6430,6432,6434你方唱罷我登場,每個人都"唱"多久呢?看相鄰2條記錄的時間差,基本都在100ms左右,這就是時間片。 ? ? ? 后記:如果放開綁定到一個CPU的限制,同時加大實時進程的個數,多個實時進程在CPU之間PULL和PUSH,是更復雜的情況,呵呵,希望拋磚引玉,能有人模擬下這種情況。 ? ? ? 附件為測試代碼及輸出: ? ???study_sched.txt??? 參考文獻 1 深入linux 內核架構 2 linux system program 3 systemtap example
分類:?LINUX
?
? ? 作者:manuscola.bean@gmail.com
? ? 博客地址:bean.blog.chinaunix.net ?最近花了10幾天的時間,將linux進程調度相關的內核代碼看了兩遍左右,也看了一些講述linux進程調度的一些文章,總想寫個系列文章,把進程調度全景剖析一遍,但是總是感覺力不逮己,自己都不敢下筆寫文章了。算了,還是不難為自己了,就隨便寫寫自己的心得好了。? ? 在用戶空間,或者應用編程領域 ,Linux提供了一些API或者系統調用來影響Linux的內核調度器,或者是獲取內核調度器的信息。比如可以獲取或者設置進程的調度策略、優先級,獲取CPU時間片大小的信息。 ? ? ? 這些接口一旦在應用程序中調用,就像給湖面扔進一顆石子,對內核帶來了那些的影響,其實這是我內心很激動很想分享的東西,但是內容好沒有組織好,所以本文的主題暫不深入涉及這些系統調用及對應的內核層的代碼。 ? ? ? 嚴格地說,對于優先級對于實時進程和普通進程的意義是不一樣的。 ? ? 1 在一定程度上,實時進程優先級高,實時進程存在,就沒有普通進程占用CPU的機會,(但是前一篇博文也講過了,實時組調度出現在內核以后,允許普通進程占用少量的CPU時間,取決于配置)。 ? ? 2 對于實時進程而言,高優先級的進程存在,低優先級的進程是輪不上的,沒機會跑在CPU上,所謂實時進程的調度策略,指的是相同優先級之間的調度策略。如果是FIFO實時進程在占用CPU,除非出現以下事情,否則FIFO一條道跑到黑。 ? ? ?a)FIFO進程良心發現,調用了系統調用sched_yield 自愿讓出CPU ? ? ?b) 更高優先級的進程橫空出世,搶占FIFO進程的CPU。有些人覺得很奇怪,怎么FIFO占著CPU,為啥還能有更高優先級的進程出現呢。別忘記,我們是多核多CPU ,如果其他CPU上出現了一個比FIFO優先級高的進程,可能會push到FIFO進程所在的CPU上。 ? ? ?c)FIFO進程停止(TASK_STOPPED or TASK_TRACED狀態)或者被殺死(EXIT_ZOMBIE or EXIT_DEAD狀態) ? ? d) FIFO進程執行了阻塞調用并進入睡眠(TASK_INTERRUPTIBLE OR TASK_UNINTERRUPTIBLE)。 ? ?? ? ? 如果是進程的調度策略是時間片輪轉RR,那么,除了前面提到的abcd,RR實時進程耗盡自己的時間片后,自動退到對應優先級實時隊列的隊尾,重新調度。 ? ? ? 下面我們就是來探究FIFO策略和RR策略的特點。為了降低理解的難度,我將我們啟動的實時進程綁定到同一個核上。
sched_setscheduler函數的第二個參數調度方法 :
另外需要指出的一點是,應用層和內核層的優先級含義是不同的: ? ?首先說實時進程:實時進程的優先級設置可以通過sched_setsheduler設置,也可以通過sched_setparam設置優先級的大小。
? ? 99優先級跑完了,才輪到70優先級,但是雖說有3個70優先級,但是先跑的那個進程跑完了,第二個優先級為70的才能跑。因為輸出結果用代碼無法漂亮的展示,所以我截了圖,截圖又不能把這個輸出都截下來,所以我很蛋疼。有需要結果的,我以附件形式附在最后。 ? ? 看下第二個腳本的輸出:
? ? ? 實時優先級是70的三個進程齊頭并進。再看第二個腳本的輸出:
轉載于:https://www.cnblogs.com/diegodu/p/3924927.html
總結
以上是生活随笔為你收集整理的linux进程调度之 FIFO 和 RR 调度策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java和C++在细节上的差异(转)
- 下一篇: Apache FtpServer配置步骤