導航:首頁 > 編程系統 > 時鍾滴答linux

時鍾滴答linux

發布時間:2023-05-07 21:08:59

『壹』 linux系統的最小時間間隔是多少

默認間隔1分鍾;因為linux中的timeval 的tv_usec時間極小,因此用微秒級的

『貳』 進程調度的Linux 原理

1,SCHED_OTHER 分時調度策略,
2,SCHED_FIFO實時調度策略,先到先服務
3,SCHED_RR實時調度策略,時間片輪轉
實時進程將得到優先調用,實時進程根據實時優先順序決定調度權值,分時進程則通過nice和counter值決定權值,nice越小,counter越大,被調度的概率越大,也就是曾經使用了cpu最少的進程將會得到優先調度。
SHCED_RR和SCHED_FIFO的不同:
當採用SHCED_RR策略的進程的時間片用完,系統將重新分配時間片,並置於就緒隊列尾。放在隊列尾保證了所有具有相同優先順序的RR任務的調度公平。
SCHED_FIFO一旦佔用cpu則一直運行。一直運行直到有更高優先順序任務到達或自己放棄。
如果有相同優先順序的實時進程(根據優先順序計算的調度權值是一樣的)已經准備好,FIFO時必須等待該進程主動放棄後才可以運行這個優先順序相同的任務。而RR可以讓每個任務都執行一段時間。
相同點:
RR和FIFO都只用於實時任務。
創建時優先順序大於0(1-99)。
按照可搶占優先順序調度演算法進行。
就緒態的實時任務立即搶占非實時任務。
所有任務都採用linux分時調度策略時。
1,創建任務指定採用分時調度策略,並指定優先順序nice值(-20~19)。
2,將根據每個任務的nice值確定在cpu上的執行時間(counter)。
3,如果沒有等待資源,則將該任務加入到就緒隊列中。
4,調度程序遍歷就緒隊列中的任務,通過對每個任務動態優先順序的計算(counter+20-nice)結果,選擇計算結果最大的一個去運行,當這個時間片用完後(counter減至0)或者主動放棄cpu時,該任務將被放在就緒隊列末尾(時間片用完)或等待隊列(因等待資源而放棄cpu)中。
5,此時調度程序重復上面計算過程,轉到第4步。
6,當調度程序發現所有就緒任務計算所得的權值都為不大於0時,重復第2步。
所有任務都採用FIFO時,
1,創建進程時指定採用FIFO,並設置實時優先順序rt_priority(1-99)。
2,如果沒有等待資源,則將該任務加入到就緒隊列中。
3,調度程序遍歷就緒隊列,根據實時優先順序計算調度權值(1000+rt_priority),選擇權值最高的任務使用cpu,該FIFO任務將一直佔有cpu直到有優先順序更高的任務就緒(即使優先順序相同也不行)或者主動放棄(等待資源)。
4,調度程序發現有優先順序更高的任務到達(高優先順序任務可能被中斷或定時器任務喚醒,再或被當前運行的任務喚醒,等等),則調度程序立即在當前任務堆棧中保存當前cpu寄存器的所有數據,重新從高優先順序任務的堆棧中載入寄存器數據到cpu,此時高優先順序的任務開始運行。重復第3步。
5,如果當前任務因等待資源而主動放棄cpu使用權,則該任務將從就緒隊列中刪除,加入等待隊列,此時重復第3步。
所有任務都採用RR調度策略時
1,創建任務時指定調度參數為RR,並設置任務的實時優先順序和nice值(nice值將會轉換為該任務的時間片的長度)。
2,如果沒有等待資源,則將該任務加入到就緒隊列中。
3,調度程序遍歷就緒隊列,根據實時優先順序計算調度權值(1000+rt_priority),選擇權值最高的任務使用cpu。
4,如果就緒隊列中的RR任務時間片為0,則會根據nice值設置該任務的時間片,同時將該任務放入就緒隊列的末尾。重復步驟3。
5,當前任務由於等待資源而主動退出cpu,則其加入等待隊列中。重復步驟3。
系統中既有分時調度,又有時間片輪轉調度和先進先出調度
1,RR調度和FIFO調度的進程屬於實時進程,以分時調度的進程是非實時進程。
2,當實時進程准備就緒後,如果當前cpu正在運行非實時進程,則實時進程立即搶占非實時進程。
3,RR進程和FIFO進程都採用實時優先順序做為調度的權值標准,RR是FIFO的一個延伸。FIFO時,如果兩個進程的優先順序一樣,則這兩個優先順序一樣的進程具體執行哪一個是由其在隊列中的未知決定的,這樣導致一些不公正性(優先順序是一樣的,為什麼要讓你一直運行?),如果將兩個優先順序一樣的任務的調度策略都設為RR,則保證了這兩個任務可以循環執行,保證了公平。 調度程序運行時,要在所有處於可運行狀態的進程之中選擇最值得運行的進程投入運行。選擇進程的依據是什麼呢?在每個進程的task_struct 結構中有這么四項:
policy, priority , counter, rt_priority
這四項就是調度程序選擇進程的依據.其中,policy是進程的調度策略,用來區分兩種進程-實時和普通;priority是進程(實時和普通)的優先順序;counter 是進程剩餘的時間片,它的大小完全由priority決定;rt_priority是實時優先順序,這是實時進程所特有的,用於實時進程間的選擇。
首先,Linux 根據policy從整體上區分實時進程和普通進程,因為實時進程和普通進程度調度是不同的,它們兩者之間,實時進程應該先於普通進程而運行,然後,對於同一類型的不同進程,採用不同的標准來選擇進程:
對於普通進程,Linux採用動態優先調度,選擇進程的依據就是進程counter的大小。進程創建時,優先順序priority被賦一個初值,一般為0~70之間的數字,這個數字同時也是計數器counter的初值,就是說進程創建時兩者是相等的。字面上看,priority是「優先順序」、counter是「計數器」的意思,然而實際上,它們表達的是同一個意思-進程的「時間片」。Priority代表分配給該進程的時間片,counter表示該進程剩餘的時間片。在進程運行過程中,counter不斷減少,而priority保持不變,以便在counter變為0的時候(該進程用完了所分配的時間片)對counter重新賦值。當一個普通進程的時間片用完以後,並不馬上用priority對counter進行賦值,只有所有處於可運行狀態的普通進程的時間片(p->;;counter==0)都用完了以後,才用priority對counter重新賦值,這個普通進程才有了再次被調度的機會。這說明,普通進程運行過程中,counter的減小給了其它進程得以運行的機會,直至counter減為0時才完全放棄對CPU的使用,這就相對於優先順序在動態變化,所以稱之為動態優先調度。至於時間片這個概念,和其他不同操作系統一樣的,Linux的時間單位也是「時鍾滴答」,只是不同操作系統對一個時鍾滴答的定義不同而已(Linux為10ms)。進程的時間片就是指多少個時鍾滴答,比如,若priority為20,則分配給該進程的時間片就為20個時鍾滴答,也就是20*10ms=200ms。Linux中某個進程的調度策略(policy)、優先順序(priority)等可以作為參數由用戶自己決定,具有相當的靈活性。內核創建新進程時分配給進程的時間片預設為200ms(更准確的,應為210ms),用戶可以通過系統調用改變它。
對於實時進程,Linux採用了兩種調度策略,即FIFO(先來先服務調度)和RR(時間片輪轉調度)。因為實時進程具有一定程度的緊迫性,所以衡量一個實時進程是否應該運行,Linux採用了一個比較固定的標准。實時進程的counter只是用來表示該進程的剩餘時間片,並不作為衡量它是否值得運行的標准,這和普通進程是有區別的。上面已經看到,每個進程有兩個優先順序,實時優先順序就是用來衡量實時進程是否值得運行的。
這一切看來比較麻煩,但實際上Linux中的實現相當簡單。Linux用函數goodness()來衡量一個處於可運行狀態的進程值得運行的程度。該函數綜合了上面提到的各個方面,給每個處於可運行狀態的進程賦予一個權值(weight),調度程序以這個權值作為選擇進程的唯一依據。
Linux根據policy的值將進程總體上分為實時進程和普通進程,提供了三種調度演算法:一種傳統的Unix調度程序和兩個由POSIX.1b(原名為POSIX.4)操作系統標准所規定的「實時」調度程序。但這種實時只是軟實時,不滿足諸如中斷等待時間等硬實時要求,只是保證了當實時進程需要時一定只把CPU分配給實時進程。
非實時進程有兩種優先順序,一種是靜態優先順序,另一種是動態優先順序。實時進程又增加了第三種優先順序,實時優先順序。優先順序是一些簡單的整數,為了決定應該允許哪一個進程使用CPU的資源,用優先順序代表相對權值-優先順序越高,它得到CPU時間的機會也就越大。
? 靜態優先順序(priority)-不隨時間而改變,只能由用戶進行修改。它指明了在被迫和其他進程競爭CPU之前,該進程所應該被允許的時間片的最大值(但很可能的,在該時間片耗盡之前,進程就被迫交出了CPU)。
? 動態優先順序(counter)-只要進程擁有CPU,它就隨著時間不斷減小;當它小於0時,標記進程重新調度。它指明了在這個時間片中所剩餘的時間量。
? 實時優先順序(rt_priority)-指明這個進程自動把CPU交給哪一個其他進程;較高權值的進程總是優先於較低權值的進程。如果一個進程不是實時進程,其優先順序就是0,所以實時進程總是優先於非實時進程的(但實際上,實時進程也會主動放棄CPU)。
當policy分別為以下值時:
1) SCHED_OTHER:這是普通的用戶進程,進程的預設類型,採用動態優先調度策略,選擇進程的依據主要是根據進程goodness值的大小。這種進程在運行時,可以被高goodness值的進程搶先。
2) SCHED_FIFO:這是一種實時進程,遵守POSIX1.b標準的FIFO(先入先出)調度規則。它會一直運行,直到有一個進程因I/O阻塞,或者主動釋放CPU,或者是CPU被另一個具有更高rt_priority的實時進程搶先。在Linux實現中,SCHED_FIFO進程仍然擁有時間片-只有當時間片用完時它們才被迫釋放CPU。因此,如同POSIX1.b一樣,這樣的進程就象沒有時間片(不是採用分時)一樣運行。Linux中進程仍然保持對其時間片的記錄(不修改counter)主要是為了實現的方便,同時避免在調度代碼的關鍵路徑上出現條件判斷語句 if (!(current->;;policy&;;SCHED_FIFO)){...}-要知道,其他大量非FIFO進程都需要記錄時間片,這種多餘的檢測只會浪費CPU資源。(一種優化措施,不該將執行時間佔10%的代碼的運行時間減少到50%;而是將執行時間佔90%的代碼的運行時間減少到95%。0.9+0.1*0.5=0.95>;;0.1+0.9*0.9=0.91)
3) SCHED_RR:這也是一種實時進程,遵守POSIX1.b標準的RR(循環round-robin)調度規則。除了時間片有些不同外,這種策略與SCHED_FIFO類似。當SCHED_RR進程的時間片用完後,就被放到SCHED_FIFO和SCHED_RR隊列的末尾。
只要系統中有一個實時進程在運行,則任何SCHED_OTHER進程都不能在任何CPU運行。每個實時進程有一個rt_priority,因此,可以按照rt_priority在所有SCHED_RR進程之間分配CPU。其作用與SCHED_OTHER進程的priority作用一樣。只有root用戶能夠用系統調用sched_setscheler,來改變當前進程的類型(sys_nice,sys_setpriority)。
此外,內核還定義了SCHED_YIELD,這並不是一種調度策略,而是截取調度策略的一個附加位。如同前面說明的一樣,如果有其他進程需要CPU,它就提示調度程序釋放CPU。特別要注意的就是這甚至會引起實時進程把CPU釋放給非實時進程。 真正執行調度的函數是schele(void),它選擇一個最合適的進程執行,並且真正進行上下文切換,使得選中的進程得以執行。而reschele_idle(struct task_struct *p)的作用是為進程選擇一個合適的CPU來執行,如果它選中了某個CPU,則將該CPU上當前運行進程的need_resched標志置為1,然後向它發出一個重新調度的處理機間中斷,使得選中的CPU能夠在中斷處理返回時執行schele函數,真正調度進程p在CPU上執行。在schele()和reschele_idle()中調用了goodness()函數。goodness()函數用來衡量一個處於可運行狀態的進程值得運行的程度。此外,在schele()函數中還調用了schele_tail()函數;在reschele_idle()函數中還調用了reschele_idle_slow()。這些函數的實現對理解SMP的調度非常重要,下面一一分析這些函數。先給出每個函數的主要流程圖,然後給出源代碼,並加註釋。
goodness()函數分析
goodness()函數計算一個處於可運行狀態的進程值得運行的程度。一個任務的goodness是以下因素的函數:正在運行的任務、想要運行的任務、當前的CPU。goodness返回下面兩類值中的一個:1000以下或者1000以上。1000或者1000以上的值只能賦給「實時」進程,從0到999的值只能賦給普通進程。實際上,在單處理器情況下,普通進程的goodness值只使用這個范圍底部的一部分,從0到41。在SMP情況下,SMP模式會優先照顧等待同一個處理器的進程。不過,不管是UP還是SMP,實時進程的goodness值的范圍是從1001到1099。
goodness()函數其實是不會返回-1000的,也不會返回其他負值。由於idle進程的counter值為負,所以如果使用idle進程作為參數調用goodness,就會返回負值,但這是不會發生的。
goodness()是個簡單的函數,但是它是linux調度程序不可缺少的部分。運行隊列中的每個進程每次執行schele時都要調度它,因此它的執行速度必須很快。
//在/kernel/sched.c中
static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)
{ int weight;
if (p->;;policy != SCHED_OTHER) {/*如果是實時進程,則*/
weight = 1000 + p->;;rt_priority;
goto out;
}
/* 將counter的值賦給weight,這就給了進程一個大概的權值,counter中的值表示進程在一個時間片內,剩下要運行的時間.*/
weight = p->;;counter;
if (!weight) /* weight==0,表示該進程的時間片已經用完,則直接轉到標號out*/
goto out;
#ifdef __SMP__
/*在SMP情況下,如果進程將要運行的CPU與進程上次運行的CPU是一樣的,則最有利,因此,假如進程上次運行的CPU與當前CPU一致的話,權值加上PROC_CHANGE_PENALTY,這個宏定義為20。*/
if (p->;;processor == this_cpu)
weight += PROC_CHANGE_PENALTY;
#endif
if (p->;;mm == this_mm) /*進程p與當前運行進程,是同一個進程的不同線程,或者是共享地址空間的不同進程,優先選擇,權值加1*/
weight += 1;
weight += p->;;priority; /* 權值加上進程的優先順序*/
out:
return weight; /* 返回值作為進程調度的唯一依據,誰的權值大,就調度誰運行*/
}
schele()函數分析
schele()函數的作用是,選擇一個合適的進程在CPU上執行,它僅僅根據'goodness'來工作。對於SMP情況,除了計算每個進程的加權平均運行時間外,其他與SMP相關的部分主要由goodness()函數來體現。
流程:
①將prev和next設置為schele最感興趣的兩個進程:其中一個是在調用schele時正在運行的進程(prev),另外一個應該是接著就給予CPU的進程(next)。注意:prev和next可能是相同的-schele可以重新調度已經獲得cpu的進程.
②中斷處理程序運行「下半部分」.
③內核實時系統部分的實現,循環調度程序(SCHED_RR)通過移動「耗盡的」RR進程-已經用完其時間片的進程-到隊列末尾,這樣具有相同優先順序的其他RR進程就可以獲得CPU了。同時,這補充了耗盡進程的時間片。
④由於代碼的其他部分已經決定了進程必須被移進或移出TASK_RUNNING狀態,所以會經常使用schele,例如,如果進程正在等待的硬體條件已經發生,所以如果必要,這個switch會改變進程的狀態。如果進程已經處於TASK_RUNNING狀態,它就無需處理了。如果它是可以中斷的(等待信號),並且信號已經到達了進程,就返回TASK_RUNNING狀態。在所以其他情況下(例如,進程已經處於TASK_UNINTERRUPTIBLE狀態了),應該從運行隊列中將進程移走。
⑤將p初始化為運行隊列的第一個任務;p會遍歷隊列中的所有任務。
⑥c記錄了運行隊列中所有進程最好的「goodness」-具有最好「goodness」的進程是最易獲得CPU的進程。goodness的值越高越好。
⑦遍歷執行任務鏈表,跟蹤具有最好goodness的進程。
⑧這個循環中只考慮了唯一一個可以調度的進程。在SMP模式下,只有任務不在cpu上運行時,即can_schele宏返回為真時,才會考慮該任務。在UP情況下,can_schele宏返回恆為真.
⑨如果循環結束後,得到c的值為0。說明運行隊列中的所有進程的goodness值都為0。goodness的值為0,意味著進程已經用完它的時間片,或者它已經明確說明要釋放CPU。在這種情況下,schele要重新計算進程的counter;新counter的值是原來值的一半加上進程的靜態優先順序(priortiy),除非進程已經釋放CPU,否則原來counter的值為0。因此,schele通常只是把counter初始化為靜態優先順序。(中斷處理程序和由另一個處理器引起的分支在schele搜尋goodness最大值時都將增加此循環中的計數器,因此由於這個原因計數器可能不會為0。顯然,這很罕見。)在counter的值計算完成後,重新開始執行這個循環,找具有最大goodness的任務。
⑩如果schele已經選擇了一個不同於前面正在執行的進程來調度,那麼就必須掛起原來的進程並允許新的進程運行。這時調用switch_to來進行切換。

『叄』 配置Linux的時鍾同步

Ubuntu系統默認的時鍾同步伺服器是ntp.ubuntu.com,Debian則是謹州0.debian.pool.ntp.org等, 各Linux發行版都有自己的NTP官方伺服器。身在中國,使用這些都會有高延遲,但對時鍾同步這件事來說影響不大。

在某些環境下,比如公司內網、雲上子網等,是與互聯網隔絕的。這時要想做時鍾同步,就只能自己配置了。

本文介紹如何自己配置時鍾同步,不介紹如何自建NTP伺服器。

一般timesync是預裝的。如果沒有,可以使用以下命令手動安裝。

sudo apt install systemd-timesyncd 它和ntp是沖突的,二者只能安裝一個。

修改/etc/systemd/timesyncd.conf,把NTP設為華為內綠區可達的NTP伺服器。

修改完成後,需要restart後這個配置才生效。

如果以上systemd-timesyncd.service因為什麼原因而不存在,則可通過以下命令修復:

一般查看日期與時間是使用date。使用timedatectl可以查看到更多時鍾同步相關信息。

以下給出一些阿里雲的NTP列表,可以通過ping擇優使用。

以上就是 良許教程網 為各位朋友分享的配置Linux的時鍾同步。

最後,最近很多小夥伴找我要 Linux學習路線圖 ,於是胡首我根據自己的經驗,利用業余時間熬夜肝了一個月,整理了一份電子書。無論你是面試還是自我提升,相信都會對你有幫助!目錄如下:

免費送給大家,只求大家金指給我點祥做蔽個贊!

電子書 | Linux開發學習路線圖

也希望有小夥伴能加入我,把這份電子書做得更完美!

推薦閱讀:

『肆』 在Linux操作系統下用Shell編寫一時鍾提示程序,要求能顯示出上午好、中午好、下午好!!急待高手解決

腳本我懶得寫。 一分都沒有。
我給你個提示就行了。 你自己寫。

編寫一個腳本,液碼數 內容如下:
#!/bin/bash
if 當前時間 < 11:00 -a 當前時間 >=6:00 ; then
wall <<EOF
上午好
EOF
elif 當前時間 >=11:00 -a 當前時間 <13:00 ; then
wall <<EOF
中午好
EOF
elif 當前時間 >=13:00 -a 當前時間模陪 <18:00 ; then
wall <<EOF
下午好
EOF
fi
------------------------分割線-------------------------

然後用鬧首 crontab 定時 執行上面的腳本文件

『伍』 linux下的幾種時鍾和定時器機制

1. RTC(Real Time Clock)

所有PC都有RTC. 它和CPU和其他晶元獨立。它在電腦關機之後還可以正常運行。RTC可以在IRQ8上產生周期性中斷. 頻率在2Hz--8192HZ.

Linux只是把RTC用來獲取時間和日期. 當然它允許進程通過對/dev/rtc設備來對它進行編程。Kernel通過0x70和0x71 I/O埠來訪問RTC。

 

2. TSC(Time Stamp Counter)

80x86上的微處理器都有CLK輸入針腳. 從奔騰系列開始. 微處理器支持一個計數器. 每當一個時鍾信號來的時候. 計數器加1. 可以通過匯編指令rdtsc來得到計數器的值。通過calibrate_tsc可以獲得CPU的頻率. 它是通過計算大約5毫秒里tsc寄存器裡面的增加值來確認的。或者可以通過cat /proc/cpuinfo來獲取cpu頻率。tsc可以提供比PIT更精確的時間度量。

 

3. PIT(Programmable internval timer)

除了RTC和TSC. IBM兼容機提供了PIT。PIT類似微波爐的鬧鍾機制. 當時間到的時候. 提供鈴聲. PIT不是產生鈴聲. 而是產生一種特殊中斷. 叫定時器中斷或者時鍾中斷。它用來告訴內核一個間隔過去了。這個時間間隔也叫做一個滴答數。可以通過編譯內核是選擇內核頻率來確定。如內核頻率設為1000HZ,則時間間隔或滴答為1/1000=1微秒。滴答月短. 定時精度更高. 但是用戶模式的時間更短. 也就是說用戶模式下程序執行會越慢。滴答的長度以納秒形式存在tick_nsec變數裡面。PIT通過8254的0x40--0x43埠來訪問。它產生中斷號為IRQ 0.

下面是關於pIT裡面的一些宏定義:

HZ:每秒中斷數。

CLOCK_TICK_RATE:值是1,193,182. 它是8254晶元內部振盪器頻率。

LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用來編程PIT。

setup_pit_timer()如下:

spin_lock_irqsave(&i8253_lock, flags);

outb_p(0x34,0x43);

udelay(10);

outb_p(LATCH & 0xff, 0x40);

udelay(10);

outb (LATCH >> 8, 0x40);

spin_unlock_irqrestore(&i8253_lock, flags);

 

 

4. CPU Local Timer

最近的80x86架構的微處理器上的local apic提供了cpu local timer.他和pit區別在於它提供了one-shot和periodic中斷。它可以使中斷發送到特定cpu。one-shot中斷常用在實時系統裡面。

『陸』 如何在Linux下調整系統時鍾

# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
//修改時區 //f刪除復現有的目標文件 //s 做象徵制性的鏈接,而不是硬鏈接
# date -s 『2016-12-14 11:45:00』 //設置時間
# clock -w //將時間寫入CMOS
# cat /etc/sysconfig/clock //查看所屬時區和是否使用UTC時間
備註: 時區需要修改 並且 需要修改CMOS
然後只是用date -s 修改時間的話重啟系統後時間會還原

『柒』 linux修改時間

修改linux的系統時間的方法如下:

1、利用date命令設定系統的日期與時間,語法「date -s "年月橡銷改日 時:分秒"」。在Linux中,可以利用date命令修改系統時間。date命斗腔令可以用來顯示或設定系統的日期與時間。例如把date -s 「2003-04-14 cst」,cst指時區,時間設定用date -s 18:10。

2、執行「hwclock --systohc」命令保存設置,關機重啟。當我們進行完 Linux 時間的校時後,還需要以 hwclock 來更新 BIOS 的時間,因為每次重新啟動的時梁判候,系統會重新由 BIOS 將時間讀出來,所以, BIOS 才是重要的時間依據吶。

Linux系統時間有兩種

日歷時間。該值是自協調世界時(UTC)1970年1月1日00:00:00這個特定時間以來所經過的秒數累計值。基本數據類型用time_t保存。最後通過轉換才能得到我們平時所看到的24小時制或者12小時間制的時間。

進程時間。也被稱為CPU時間,用以度量進程使用的中央處理器資源。進程時間以時鍾滴答計算。

『捌』 時間嘀嗒的設定原理和更改方法是什麼

延時函數會涉及到系統滴答時鍾,所以有必要介紹下系統滴答時鍾的原理。系統里有一個計數變數OSTickCtr。系統滴答時鍾是由滴答定時器產生的,其實也就是通過一個定時器來產生特定時間間隔的中斷,每產生一個系統時鍾中斷這個森缺桐變數就自加1。而延時函數就是用這個OSTickCtr來產生延時的,比如OSTimeDly()函數在相對延時模式下延時20個時鍾節拍,當前OSTickCtr=100,那麼當OSTickCtr==120的時候延時結束。當然,通過與OSTickCtr掛鉤來延時是不準確的,比如滴答定時器每5ms產生一個中斷,然後OSTickCtr++。比如當前OSTickCtr==100開始延時,因為不知道過1毫秒還是4毫秒OSTickCtr會加到101。所以這個延時精度取決於系統心跳時扮辯鍾的頻率。
系統時鍾是在os_cfg_app.h文件裡面設置的,OS_CFG_TICK_RATE_HZ代表系統心跳的頻率,注意這個是頻率,此坦不是周期。本工程用的系統心跳頻率為200HZ,也就是5ms一個心跳。
當程序調用OSTimeDly()或者OSTimeDlyHMSM()這兩個延時函數時,系統會把當前任務掛起來,然後去運行別的任務,等到延時結束後程序才會回到當前任務運行。這個和不帶系統的軟體延時有點區別,不帶系統的軟體延時程序會卡在當前位置一直等待延時結束,但是帶系統的延時函數在延時期間系統會去運行別的任務,而不會讓系統傻傻地等啥都不幹。

『玖』 為什麼Linux CFS調度器沒有帶來驚艷的碾壓效果| CSDN博文精選

任何領域,革命性的碾壓式推陳出新並不是沒有,但是概率極低,人們普遍的狂妄在於,總是認為自己所置身的環境正在發生著某種碾壓式的變革,但其實,最終大概率不過是一場平庸。

作者 | dog250

責編 | 劉靜

出品 | CSDN博客

但凡懂Linux內核的,都知道Linux內核的CFS進程調度演算法,無論是從2.6.23將其初引入時的論文,還是各類源碼分析,文章,以及Linux內核專門的圖書,都給人這樣一種感覺,即 CFS調度器是革命性的,它將徹底改變進程調度演算法。 預期中,人們期待它會帶來令人驚艷的效果。

然而這是錯覺。

人們希望CFS速勝,但是分析來分析去, 卻只是在某些方面比O(1)調度器稍微好一點點 。甚至在某些方面比不上古老的4.4BSD調度器。可是人們卻依然對其趨之若鶩,特別是源碼分析,汗牛塞屋!

為什麼CFS對別的調度演算法沒有帶來碾壓的效果呢?

首先,在真實世界,碾壓是不存在的,人與人,事與事既然被放在了同一個重量級梯隊比較,其之間的差別沒有想像的那麼大,根本就不在誰碾壓誰。不能被小說電視劇電影蒙蔽了,此外,徐曉冬大擺拳暴打雷雷也不算數,因為他們本就不是一個梯隊。

任何領域,革命性的碾壓式推陳出新並不是沒有,但是概率極低,人們普遍的狂妄在於,總是認為自己所置身的環境正在發生著某種碾壓式的變革,但其實,最終大概率不過是一場平庸。

最終就出現了角力,僵持。

其次,我們應該看到,CFS調度器聲稱它會給互動式進程帶來福音,在這方面CFS確實比O(1)做得好,但是驚艷的效果來自於粉絲的認同。Linux系統交互進程本來就不多,Linux更多地被裝在伺服器,而在伺服器看來,吞吐是要比交互響應更加重要的。

那麼以交互為主的Android系統呢?我們知道,Android也是採用了CFS調度器,也有一些事BFS,為什麼同樣沒有帶來驚艷的效果呢?

我承認,2008年前後出現CFS時廳陸兆還沒有Android,等到Android出現時,其採用的Linux內核已經默認了CFS調度器,我們看下Android版本,Linux內核版本以及發行時間的關系:

Linux內核在2.6.23就採用了CFS調度器。所以一個原因就是沒有比較。Android系統上,CFS沒有機會和O(1)做比較。

另悉槐外,即便回移一個O(1)調度器到Android系統去和CFS做AB,在我看來,CFS同樣不會驚艷,原因很簡單,Android系統幾乎都是交互進程,卻前台進程永遠只有一個,你幾乎感受不到進程的切換卡頓,換句話說,即便CFS對待互動式進程比O(1)好太多,你也感受不到,因為對於手機,平板而言,你切換 APP 的時間遠遠大於進程切換的時間粒度。

那麼,CFS到底好在哪裡?

簡單點說,CFS的意義在於, 在一個混雜著大量計算型進程和IO交互進程的系統中,CFS調度器對待IO交扮租互進程要比O(1)調度器更加友善和公平 。理解這一點至關重要。

其實,CFS調度器的理念非常古老,就說在業界,CFS的思想早就被應用在了磁碟IO調度,數據包調度等領域,甚至最最古老的SRV3以及4.3BSD UNIX系統的進程調度中早就有了CFS的身影,可以說,Linux只是 使用CFS調度器 ,而不是 設計了CFS調度器

就以4.3BSD調度器為例,我們看一下其調度原理。

4.3BSD採用了1秒搶占制,每間隔1秒,會對整個系統進程進行優先順序排序,然後找到優先順序最高的投入運行,非常簡單的一個思想,現在看看它是如何計算優先順序的。

首先,每一個進程j均擁有一個CPU滴答的度量值Cj,每一個時鍾滴答,當前在運行的進程的CPU度量值C會遞增:

當一個1秒的時間區間ii過去之後,Cj被重置,該進程jj的優先順序採用下面的公式計算:

可以計算,在一個足夠長的時間段內,兩個進程運行的總時間比例,將和它們的Base_PrioBase_Prio優先順序的比例相等。

4.3BSD的優先順序公平調度是CPU滴答驅動的。

現在看Linux的CFS,CFS採用隨時搶占制。每一個進程j均攜帶一個 虛擬時鍾VCj ,每一個時鍾滴答,當前進程k的VCk會重新計算,同時調度器選擇VC最小的進程運行,計算方法非常簡單:

可見, Linux的CFS簡直就是4.3BSD進程調度的自驅無級變速版本!

如果你想了解CFS的精髓,上面的就是了。換成語言描述,CFS的精髓就是 「 n個進程的系統,任意長的時間周期TT,每一個進程運行T/n的時間!

當然,在現實和實現中,會有80%的代碼處理20%的剩餘問題,比如如何獎勵睡眠太久的進程等等,但是這些都不是精髓。

綜上,我們總結了:

所以無論從概念還是從效果,Linux CFS調度器均沒有帶來令人眼前一亮的哇塞效果。但是還缺點什麼。嗯,技術上的解釋。

分析和解釋任何一個機制之前,必然要先問,這個機制的目標是什麼,它要解決什麼問題,這樣才有意義。而不能僅僅是明白了它是怎麼工作的。

那麼Linux CFS調度器被採用,它的目標是解決什麼問題的呢?它肯定是針對O(1)演算法的一個問題而被引入並取代O(1),該問題也許並非什麼臭名昭著,但是確實是一枚釘子,必須拔除。

O(1)調度器的本質問題在於 進程的優先順序和進程可運行的時間片進行了強映射!

也就是說,給定一個進程優先順序,就會計算出一個時間片與之對應,我們忽略獎懲相關的動態優先順序,看一下原始O(1)演算法中一個進程時間片的計算:

直觀點顯示:

針對上述問題,2.6內核的O(1)O(1)引入了雙斜率來解決:

直觀圖示如下:

貌似問題解決了,但是如果單單揪住上圖的某一個優先順序子區間來看,還是會有問題,這就是相對優先順序的問題。我們看到,高優先順序的時間片是緩慢增減的,而低優先順序的時間片卻是陡然增減,同樣都是相差同樣優先順序的進程,其優先順序分布影響了它們的時間片分配。

本來是治瘸子,結果腿好了,但是胳臂壞了。

本質上來講,這都源自於下面兩個原因:

固定的優先順序映射到固定的時間片。

相對優先順序和絕對優先順序混雜。

那麼這個問題如何解決?

優先順序和時間片本來就是兩個概念,二者中間還得有個變數溝通才可以。優先順序高只是說明該進程能運行的久一些,但是到底久多少,並不是僅僅優先順序就能決定的,還要綜合考慮,換句話距離來說,如果只有一個進程,那麼即便它優先順序再低,它也可以永久運行,如果系統中有很多的進程,即便再高優先順序的進程也要讓出一些時間給其它進程。

所以,考慮到系統中總體的進程情況,將優先順序轉換為權重,將時間片轉換為份額,CFS就是了。最終的坐標系應該是 權重佔比/時間片 坐標系而不是 權重(或者優先順序)/時間片 。應該是這個平滑的樣子:

看來,Linux CFS只是為了解決O(1)O(1)中一個 「靜態優先順序/時間片映射」 問題的,那麼可想而知,它又能帶來什麼驚艷效果呢?這里還有個「但是」,這個O(1)O(1)調度器的問題其實在計算密集型的守護進程看來,並不是問題,反而是好事,畢竟高優先順序進程可以 無條件持續運行很久而不切換 。這對於吞吐率的提高,cache利用都是有好處的。無非也就侵擾了交互進程唄,又有何妨。

當然,使用調優CFS的時候,難免也要遇到IO睡眠獎懲等剩餘的事情去設計一些trick演算法,這破費精力。

對了,還要設置你的內核為HZ1000哦,這樣更能體現CFS的平滑性,就像它宣稱的那樣。我難以想像,出了Ubuntu,Suse等花哨的桌面發行版之外,還有哪個Linux需要打開HZ1000,伺服器用HZ250不挺好嗎?

關於調度的話題基本就說完了,但是在進入下一步固有的噴子環節之前,還有兩點要強調:

在CPU核數越來越多的時代,人們更應該關心 把進程調度到哪裡CPU核上 而不是 某個CPU核要運行哪個進程

單核時代一路走過來的Linux,發展迅猛,這無可厚非,但是成就一個操作系統內核的並不單單是技術,還有別的。這些當然程序員們很不愛聽,程序員最煩非技術方面的東西了,程序員跟誰都比寫代碼,程序員特別喜歡噴領導不會寫代碼雲雲。

Linux在純技術方面並不優秀,Linux總體上優秀的原因是因為有一群非代碼不明志的程序員在讓它變得越來越優秀,另一方面還要歸功於開源和社區。Linux的學習門檻極低,如果一個公司能不費吹灰之力招聘到一個Linux程序員的話,那它幹嘛還要費勁九牛二虎之力去招聘什麼高端的BSD程序員呢?最終的結果就是,Linux用的人極多,想換也換不掉了。

但無論如何也沒法彌補Linux內核上的一些原則性錯誤。

Linux內核還是以原始的主線為base,以講Linux內核的書為例,經典的Robert Love的《Linux內核設計與實現》,以及《深入理解Linux內核》,在講進程調度的時候,關於多核負載均衡的筆墨都是少之又少甚至沒有,如此經典的著作把很多同好引向了那萬劫不復的代碼深淵。於是乎,鋪天蓋地的CFS源碼分析紛至沓來。

但其實,拋開這么一個再普通不過的Linux內核,現代操作系統進入了多核時代,其核心正是在cache利用上的革新,帶來的轉變就是進程調度和內存管理的革新。review一下Linux內核源碼,這些改變早就已經表現了出來。

可悲的是,關於Linux內核的經典書籍卻再也沒有更新,所有的從傳統學校出來的喜歡看書學習的,依然是抱著10年前的大部頭在啃。

http :// www. ece.ubc.ca/~sasha/papers/eurosys16-final29.pdf

浙江溫州皮鞋濕,下雨進水不會胖。

作者:CSDN博主「dog250」,本文首發於作者CSDN博客https://blog.csdn.net/dog250/article/details/957298 30 。

【END】

『拾』 硬體時鍾

有幾個概率需虛基枯要了解

1.時間周期(Clock Cycle)的頻率:晶體振盪器在1秒以內時鍾周期的個數=1秒以內時鍾脈沖的個數,Linux裡面用

#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */

單位為HZ

2.時鍾滴答(Clock Tick):

當PIT通道0的計數器減到0值時,它就在IRQ0上產生一次時鍾中斷,也即一次時鍾滴答。PIT通道0的計數器的初始值決定了要過多少時鍾鋒橋周期才產生一次時鍾中斷。

3.時鍾滴答的頻率(HZ):1秒以內產生時間滴答個數

HZ在arm和i386上定義為100,ALPHA和IA62為1024 ,IBM Power PC為1000

i386 1個時鍾滴答時間為1000ms/100=10ms。

4.時鍾滴答的時間間隔(tick)

long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */   單位為us ,tick=10ms,也可以通過HZ來計算

linux中#define TICK_SIZE= tick

1s=1,000,000us

(5)宏LATCH:Linux用宏LATCH來定義要寫到PIT通道0的計數器中的值,它表示PIT將沒隔多少個時鍾周期產生一次時鍾中斷。

    LATCH=(1秒之內的時鍾周期個數)÷(1秒之內的時鍾中斷次數)=(CLOCK_TICK_RATE)÷(HZ)

Linux為取整 #define LATCH=(CLOCK_TICK_RATE + HZ/2) / HZ。

時鍾周期理解:時鍾脈沖,電平從0到1(或者相反)。

CLOCK_TICK_RATE和HZ都是 頻率 :1秒以內時鍾周期 頻率 ,1秒以內時鍾滴答 頻率 。

TSC使用CPU頻率,在現代計算機中CPU可能降頻也可能超率,TSC時鍾不準確。

順序為HPET > APCI PMT>PIC>TSC

local cpu APIC只在單CPU場景上使用,如進程差洞調度時間.

參考:

http://www.dedecms.com/knowledge/servers/linux-bsd/2012/0913/14187.html

閱讀全文

與時鍾滴答linux相關的資料

熱點內容
雙網卡上不同網路 瀏覽:94
拳皇game怎麼打壓縮文件 瀏覽:748
有哪些兩級配送物流網路 瀏覽:8
sql目錄名加文件名 瀏覽:446
小學編程教材哪個好 瀏覽:179
英語詞典蘋果app 瀏覽:344
黨的文件保管採用什麼辦法 瀏覽:45
老版本的百度雲盤 瀏覽:201
一指彈app怎麼用 瀏覽:249
ps怎麼提取文件名 瀏覽:540
蘋果7plus網路連接超時 瀏覽:959
權重6網站賣多少 瀏覽:151
bzb網站有哪些 瀏覽:687
機械類專業要學什麼編程 瀏覽:89
SQL中打開excel文件 瀏覽:468
藍牙可以傳word文件嗎 瀏覽:65
三星能自己升級系統嗎 瀏覽:265
12款新福克斯手動擋bcm升級 瀏覽:330
js內容尾部增加內容 瀏覽:803
sqlldr控制文件詳解 瀏覽:614

友情鏈接