久综合色-久综合网-玖草影视-玖草资源在线-亚洲黄色片子-亚洲黄色片在线观看

Hello! 歡迎來到小浪云!


聊聊Linux中CPU上下文切換


avatar
小浪云 2025-01-04 120

操作系統(tǒng)中,特別是在 linux 這樣的多任務(wù)操作系統(tǒng)中,cpu 上下文是一個重要的概念。多任務(wù)操作系統(tǒng)允許多個進(jìn)程在一個 cpu 上運(yùn)行,這些進(jìn)程之間相互獨(dú)立,互不干擾,給用戶造成了多任務(wù)“同時運(yùn)行”的錯覺。實際上,操作系統(tǒng)會在很短的時間內(nèi)讓 cpu 在各個任務(wù)之間輪流執(zhí)行,從而給用戶創(chuàng)造出多任務(wù)“同時運(yùn)行”的假象。

在每次 CPU 執(zhí)行任務(wù)之前,必須確定從哪里加載任務(wù),以及加載后從哪里開始運(yùn)行。為了實現(xiàn)這一點(diǎn),操作系統(tǒng)通過 CPU 中的寄存器和程序計數(shù)器來保存和恢復(fù)任務(wù)的執(zhí)行進(jìn)度信息。

CPU 寄存器是 CPU 內(nèi)部的高速緩存,存儲著非常快速的內(nèi)存數(shù)據(jù);而程序計數(shù)器則記錄了 CPU 正在執(zhí)行或即將執(zhí)行的指令位置。

在任務(wù)調(diào)度過程中,這些關(guān)鍵信息都保存在 CPU 的寄存器中。其中,下一條即將執(zhí)行的指令地址保存在程序計數(shù)器中。這些信息的集合被稱為 CPU 上下文,有時也被稱為硬件上下文。

當(dāng)某個進(jìn)程主動放棄 CPU 時間,或者系統(tǒng)分配的時間片用完時,就會發(fā)生 CPU 上下文切換。

CPU上下文切換

操作系統(tǒng)OS在切換運(yùn)行任務(wù)時,將上一任務(wù)的上下文保存起來,然后加載新任務(wù)的上下文到CPU寄存器,最后再跳轉(zhuǎn)到程序計數(shù)器所指的新位置上執(zhí)行新任務(wù)的這一動作,被稱為CPU上下文切換

CPU上下文切換的步驟:

  1. 將前一個 CPU 的上下文(也就是 CPU 寄存器和程序計數(shù)器里邊的內(nèi)容)保存起來;
  2. 然后加載新任務(wù)的上下文到寄存器和程序計數(shù)器;
  3. 最后跳轉(zhuǎn)到程序計數(shù)器所指的新位置,運(yùn)行新任務(wù)。
  4. 被保存起來的上下文會存儲到系統(tǒng)內(nèi)核中,等待任務(wù)重新調(diào)度執(zhí)行時再次加載進(jìn)來。

CPU 的上下文切換分三種:進(jìn)程上下文切換、線程上下文切換、中斷上下文切換。

上一任務(wù)的CPU上下文保存在哪?

我們知道因為CPU過于昂貴,其性能與其他儲存設(shè)備有數(shù)量級的差距,為了充分壓榨其性能,計算機(jī)將CPU的時間進(jìn)行分片,讓各個程序在CPU上輪轉(zhuǎn)執(zhí)行,被剝奪執(zhí)行權(quán)的程序,等后面CPU繼續(xù)執(zhí)行它的時候,這時需要一個數(shù)據(jù)結(jié)構(gòu)來保存相關(guān)信息,以便之后恢復(fù)繼續(xù)執(zhí)行,這個其實就是進(jìn)程。

CPU上下文會被保存在進(jìn)程的內(nèi)核空間(kernel space)上。OS在給每個進(jìn)程分配虛擬內(nèi)存空間時,會分配一個內(nèi)核空間,這部分內(nèi)存只能由內(nèi)核代碼訪問。OS在切換CPU上下文前,會先將當(dāng)前CPU的通用寄存器、PC等進(jìn)程現(xiàn)場信息保存在進(jìn)程的內(nèi)核空間上,待下次切換時,再取出重新裝載到CPU上,以恢復(fù)任務(wù)的運(yùn)行。聊聊Linux中CPU上下文切換

進(jìn)程上下文切換

內(nèi)核空間和用戶空間

我們知道為了限制不同的指令的訪問能力,提升安全,Linux 按照特權(quán)等級,把進(jìn)程的運(yùn)行空間分為內(nèi)核空間和用戶空間 。進(jìn)程既可以在用戶空間運(yùn)行,又可以在內(nèi)核空間中運(yùn)行。進(jìn)程在用戶空間運(yùn)行時,被稱為進(jìn)程的用戶態(tài),而陷入內(nèi)核空間的時候,被稱為進(jìn)程的內(nèi)核態(tài)。

  1. 內(nèi)核空間(Ring 0):具有最高權(quán)限,可以直接訪問所有資源(讀取文件)

?

常見的內(nèi)核操作:分配內(nèi)存、IO操作、創(chuàng)建子進(jìn)程……

  1. 用戶空間(Ring 3):只能訪問受限資源,不能直接訪問內(nèi)存等硬件設(shè)備,必須通過系統(tǒng)調(diào)用進(jìn)入到內(nèi)核中,才能訪問這些特權(quán)資源

?

常見的用戶態(tài)空間程序:數(shù)據(jù)庫、web服務(wù)器、shell腳本Java程序或者其他常見語言的程序……

我們一起看下Linux整體架構(gòu)圖:聊聊Linux中CPU上下文切換

top命令查看CPU資源

linux系統(tǒng)使用top命令查看cpu時,能看到用戶態(tài)和內(nèi)核態(tài)占用的cpu資源聊聊Linux中CPU上下文切換

其中各項數(shù)據(jù)表示內(nèi)容:

us 用戶空間占用CPU百分比
sy 內(nèi)核空間占用CPU百分比
ni 用戶進(jìn)程空間內(nèi)改變過優(yōu)先級的進(jìn)程占用CPU百分比
id 空閑CPU百分比
wa 等待輸入輸出的CPU時間百分比
hi 硬件中斷
si 軟件中斷
st 實時

系統(tǒng)調(diào)用

對于一個進(jìn)程來說,比如web服務(wù)的進(jìn)程,一般是運(yùn)行在用戶態(tài)的,但是當(dāng)需要訪問內(nèi)存、磁盤等硬件設(shè)備的時候需要先進(jìn)入到內(nèi)核態(tài)中,也就是從用戶態(tài)到內(nèi)核態(tài)的轉(zhuǎn)變,而這種轉(zhuǎn)變需要借助系統(tǒng)調(diào)用來實現(xiàn)。系統(tǒng)調(diào)用是內(nèi)核向用戶進(jìn)程提供服務(wù)的唯一方法。

比如查看文件時,需要執(zhí)行多次系統(tǒng)調(diào)用:open()打開文件,read()讀取文件內(nèi)容,write()將文件內(nèi)容輸出到控制臺,最后close()關(guān)閉文件等。系統(tǒng)調(diào)用的過程如下:

  1. 把 CPU 寄存器里原來用戶態(tài)的指令位置保存起來;
  2. 為了執(zhí)行內(nèi)核代碼,CPU 寄存器需要更新為內(nèi)核態(tài)指令的新位置,最后跳轉(zhuǎn)到內(nèi)核態(tài)運(yùn)行內(nèi)核任務(wù);
  3. 系統(tǒng)調(diào)用結(jié)束后,CPU 寄存器需要恢復(fù)原來保存的用戶態(tài),然后再切換到用戶空間,繼續(xù)運(yùn)行進(jìn)程;

我們可以發(fā)現(xiàn)一次系統(tǒng)調(diào)用的過程,其實是發(fā)生了兩次 CPU 上下文切換(用戶態(tài)-內(nèi)核態(tài)-用戶態(tài))。

需要注意的是:系統(tǒng)調(diào)用過程中,不涉及虛擬內(nèi)存等進(jìn)程用戶態(tài)的資源,也不會切換進(jìn)程,也就是系統(tǒng)調(diào)用過程中一直是同一個進(jìn)程在運(yùn)行。系統(tǒng)調(diào)用過程也通常稱為特權(quán)模式切換

進(jìn)程上下文切換 和 系統(tǒng)調(diào)用的區(qū)別

  1. 進(jìn)程上下文切換是指,從一個進(jìn)程切換到另一個進(jìn)程;系統(tǒng)調(diào)用過程一直是同一個進(jìn)程在運(yùn)行,屬于進(jìn)程之內(nèi)的上下文切換

?

需要注意的是:進(jìn)程是由內(nèi)核來管理和調(diào)度的,進(jìn)程的切換只能發(fā)生在內(nèi)核態(tài),保存上下文和恢復(fù)上下文的過程并不免費(fèi),需要消耗一定資源

聊聊Linux中CPU上下文切換

  1. 進(jìn)程的上下文不僅包括了虛擬內(nèi)存、全局變量等用戶空間的資源,還包括了內(nèi)核、寄存器等內(nèi)核空間的狀態(tài)。而系統(tǒng)調(diào)用這里沒有涉及到虛擬內(nèi)存等這些進(jìn)程用戶態(tài)的資源
  2. 因此進(jìn)程的上下文切換就比系統(tǒng)調(diào)用時多了一步:在保存當(dāng)前進(jìn)程的內(nèi)核狀態(tài)和 CPU 寄存器之前,需要先把該進(jìn)程的虛擬內(nèi)存、棧等保存下來;而加載了下一進(jìn)程的內(nèi)核態(tài)后,還需要刷新進(jìn)程的虛擬內(nèi)存和用戶棧。

進(jìn)程切換的常見場景

進(jìn)程切換時需要切換上下文,換句話說,只有在進(jìn)程調(diào)度的時候,才需要切換上下文。Linux 為每個 CPU 都維護(hù)了一個就緒隊列,將活躍進(jìn)程(即正在運(yùn)行和正在等待 CPU 的進(jìn)程)按照優(yōu)先級和等待 CPU 的時間排序,然后選擇最需要 CPU 的進(jìn)程,也就是優(yōu)先級最高和等待 CPU 時間最長的進(jìn)程來運(yùn)行。進(jìn)程切換的場景有:

  1. 進(jìn)程時間片耗盡,為了保證所有進(jìn)程可以得到公平調(diào)度,CPU 時間被劃分為一段段的時間片,這些時間片再被輪流分配給各個進(jìn)程。當(dāng)某個進(jìn)程的時間片耗盡了,就會被系統(tǒng)掛起,切換到其它正在等待 CPU 的進(jìn)程運(yùn)行。
  2. 進(jìn)程在系統(tǒng)資源不足(比如內(nèi)存不足)時,要等到資源滿足后才可以運(yùn)行,這個時候進(jìn)程也會被掛起,并由系統(tǒng)調(diào)度其他進(jìn)程運(yùn)行。
  3. 進(jìn)程通過睡眠函數(shù) sleep 主動把自己掛起,CPU會重新調(diào)度;
  4. 當(dāng)有CPU發(fā)現(xiàn)優(yōu)先級更高的進(jìn)程運(yùn)行時,為了去運(yùn)行高優(yōu)先級進(jìn)程,當(dāng)前進(jìn)程會被掛起;
  5. 發(fā)生硬中斷,CPU 上的進(jìn)程會被掛起,然后去執(zhí)行內(nèi)核中的中斷服務(wù)進(jìn)程。

線程上下文切換

對操作系統(tǒng)來說,進(jìn)程是資源分配的基本單位,而線程則是任務(wù)調(diào)度的基本單位。內(nèi)核中的任務(wù)調(diào)度實際是在調(diào)度線程,進(jìn)程只是給線程提供虛擬內(nèi)存、全局變量等資源。線程上下文切換時,共享相同的虛擬內(nèi)存和全局變量等資源不需要修改。而線程自己的私有數(shù)據(jù),如棧和寄存器等,上下文切換時需要保存。

關(guān)于進(jìn)程和線程的區(qū)別:

  • 當(dāng)進(jìn)程中只有一個線程時,可以認(rèn)為進(jìn)程就等于線程。
  • 當(dāng)進(jìn)程擁有多個線程時,這些線程會共享父進(jìn)程的資源(即共享相同的虛擬內(nèi)存和全局變量等資源)。這些資源在上下文切換時是不需要修改的。
  • 另外,線程也有自己的私有數(shù)據(jù),比如棧和寄存器等,這些在上下文切換時也是需要保存的。

因此線程上下文切換有兩種情況:

  • 前后兩個線程屬于不同進(jìn)程,因為資源不共享,所以切換過程就跟進(jìn)程上下文切換是一樣的;
  • 前后兩個線程屬于同一個進(jìn)程,因為虛擬內(nèi)存是共享的,所以在切換時,虛擬內(nèi)存這些資源就保持不動,只需要切換線程的私有數(shù)據(jù)、寄存器等不共享的數(shù)據(jù)。

中斷上下文切換

上下文切換有時也因硬件中斷而觸發(fā)。硬件中斷是指硬件設(shè)備(如鍵盤、鼠標(biāo)、調(diào)試解調(diào)器、系統(tǒng)時鐘)給內(nèi)核發(fā)送的一個信號,該信號表示一個事件(如按鍵、鼠標(biāo)移動、從網(wǎng)絡(luò)連接接收到數(shù)據(jù))發(fā)生了。

為了快速響應(yīng)硬件的事件,中斷處理會打斷進(jìn)程的正常調(diào)度和執(zhí)行,然后調(diào)用中斷處理程序,響應(yīng)設(shè)備事件。在打斷其他進(jìn)程時,需要先將進(jìn)程當(dāng)前的狀態(tài)保存下來,等中斷結(jié)束后,進(jìn)程仍然可以恢復(fù)回來。

跟進(jìn)程上下文不同,中斷上下文切換不涉及進(jìn)程的用戶態(tài)。所以,即便中斷過程打斷了一個正處在用戶態(tài)的進(jìn)程,也不需要保存和恢復(fù)這個進(jìn)程的虛擬內(nèi)存、全局變量等用戶態(tài)資源。中斷上下文,只包括內(nèi)核態(tài)中斷服務(wù)程序執(zhí)行所必需的狀態(tài),也就是 CPU 寄存器、內(nèi)核棧、硬件中斷參數(shù)等。

中斷上下文切換并不涉及到進(jìn)程的用戶態(tài)。所以即便中斷過程打斷了一個正處在用戶態(tài)的進(jìn)程,也不需要保存和恢復(fù)這個進(jìn)程的虛擬內(nèi)存、全局變量等用戶態(tài)資源。中斷上下文,其實只包括內(nèi)核態(tài)中斷服務(wù)程序執(zhí)行所必須的狀態(tài),包括 CPU 寄存器、內(nèi)核堆棧、硬件中斷參數(shù)等。

對同一個 CPU 來說,中斷處理比進(jìn)程擁有更高的優(yōu)先級,所以中斷上下文切換不會與進(jìn)程上下文切換同時發(fā)生。并且,由于中斷會打斷正常進(jìn)程的調(diào)度和執(zhí)行,所以大部分中斷處理程序都短小精悍,以便可以盡快完成。

上下文切換的消耗

上下文切換通常是計算密集型的。也就是說,它需要相當(dāng)可觀的處理器時間,在每秒幾十上百次的切換中,每次切換都需要納秒量級的時間。所以,上下文切換對系統(tǒng)來說意味著消耗大量的 CPU 時間,事實上,可能是操作系統(tǒng)中時間消耗最大的操作。

Linux相比與其他操作系統(tǒng)(包括其他類 unix 系統(tǒng))有很多的優(yōu)點(diǎn),其中有一項就是,其上下文切換和模式切換的時間消耗非常少。

根據(jù)Tsuna的測試報告,每次上下文切換都需要幾十納秒到數(shù)微妙的CPU時間,這個時間還是相當(dāng)可觀的。不管是哪種場景導(dǎo)致的上下文切換,你都應(yīng)該知道:

  1. CPU上下文切換,是保證Linux系統(tǒng)正常工作的核心功能,一般情況下不需要開發(fā)人員特別關(guān)注。
  2. 但過多的上下文切換,會把CPU時間消耗在寄存器、內(nèi)核棧以及虛擬內(nèi)存等數(shù)據(jù)的保存和恢復(fù)上,從而縮短進(jìn)程真正運(yùn)行的時間,耗費(fèi)大量的 CPU,甚至嚴(yán)重降低系統(tǒng)的整體性能。

補(bǔ)充:vmstat命令查看整體CPU上下文切換情況

上面已經(jīng)介紹到CPU上下文切換分為進(jìn)程上下文切換、線程上下文切換、中斷上下文切換,那么過多的上下文切換會把CPU的時間消耗在寄存器、內(nèi)核棧以及虛擬內(nèi)存等數(shù)據(jù)的保存和恢復(fù)上,縮短進(jìn)程真正運(yùn)行的時間,成為系統(tǒng)性能大幅下降的一個因素

所以我們可以使用vmstat這個工具來查詢系統(tǒng)的上下文切換情況,vmstat是一個常用的系統(tǒng)性能分析工具,可以用來分析CPU上下文切換和中斷的次數(shù) 執(zhí)行如下的命令:vmstat 5 (每隔5s輸出一組數(shù)據(jù))

聊聊Linux中CPU上下文切換

該命令輸出信息中,各個字段以及含義:

procs:procs 中有 r 和 b 列,它報告進(jìn)程統(tǒng)計信息。在上面的輸出中,在運(yùn)行隊列(r)中有兩個進(jìn)程在等待 CPU 并有零個休眠進(jìn)程(b)。通常,它不應(yīng)該超過處理器(或核心)的數(shù)量,如果你發(fā)現(xiàn)異常,最好使用 top 命令進(jìn)一步地排除故障。

  • r:等待運(yùn)行的進(jìn)程數(shù)。
  • b:休眠狀態(tài)下的進(jìn)程數(shù)。

memory:memory 下有報告內(nèi)存統(tǒng)計的 swpd、free、buff 和 cache 列。你可以用 free -m 命令看到同樣的信息。在上面的內(nèi)存統(tǒng)計中,統(tǒng)計數(shù)據(jù)以千字節(jié)表示,這有點(diǎn)難以理解,最好添加 M 參數(shù)來看到以兆字節(jié)為單位的統(tǒng)計數(shù)據(jù)。

  • swpd:使用的虛擬內(nèi)存量。
  • free:空閑內(nèi)存量。
  • buff:用作緩沖區(qū)的內(nèi)存量。
  • cache:用作高速緩存的內(nèi)存量。
  • inact:非活動內(nèi)存的數(shù)量。
  • active:活動內(nèi)存量。

swap:swap 有 si 和 so 列,用于報告交換內(nèi)存統(tǒng)計信息。你可以用 free -m 命令看到相同的信息。

  • si:從磁盤交換的內(nèi)存量(換入,從 swap 移到實際內(nèi)存的內(nèi)存)。
  • so:交換到磁盤的內(nèi)存量(換出,從實際內(nèi)存移動到 swap 的內(nèi)存)。

I/O:I/O 有 bi 和 bo 列,它以“塊讀取”和“塊寫入”的單位來報告每秒磁盤讀取和寫入的塊的統(tǒng)計信息。如果你發(fā)現(xiàn)有巨大的 I/O 讀寫,最好使用 iotop 和 iostat 命令來查看。

  • bi:從塊設(shè)備接收的塊數(shù)。
  • bo:發(fā)送到塊設(shè)備的塊數(shù)。

system:system 有 in 和 cs 列,它報告每秒的系統(tǒng)操作。

  • in:每秒的系統(tǒng)中斷數(shù),包括時鐘中斷。
  • cs:系統(tǒng)為了處理所以任務(wù)而上下文切換的數(shù)量。

CPU:CPU 有 us、sy、id 和 wa 列,報告(所用的) CPU 資源占總 CPU 時間的百分比。如果你發(fā)現(xiàn)異常,最好使用 top 和 free 命令。

  • us:處理器在非內(nèi)核程序消耗的時間。
  • sy:處理器在內(nèi)核相關(guān)任務(wù)上消耗的時間。
  • id:處理器的空閑時間。
  • wa:處理器在等待IO操作完成以繼續(xù)處理任務(wù)上的時間。

補(bǔ)充:pidstat命令查看進(jìn)程的CPU上下文切換情況

執(zhí)行如下的命令:pidstat,查看進(jìn)程的CPU上下文切換情況 如果沒有安裝,yum install sysstat安裝即可聊聊Linux中CPU上下文切換

在結(jié)果中你能看到如下內(nèi)容:

  • PID – 被監(jiān)控的任務(wù)的進(jìn)程號
  • %usr – 當(dāng)在用戶層執(zhí)行(應(yīng)用程序)時這個任務(wù)的cpu使用率,和 nice 優(yōu)先級無關(guān)。注意這個字段計算的cpu時間不包括在虛擬處理器中花去的時間。
  • %system – 這個任務(wù)在系統(tǒng)層使用時的cpu使用率。
  • %guest – 任務(wù)花費(fèi)在虛擬機(jī)上的cpu使用率(運(yùn)行在虛擬處理器)。
  • %CPU – 任務(wù)總的cpu使用率。在SMP環(huán)境(多處理器)中,如果在命令行中輸入-I參數(shù)的話,cpu使用率會除以你的cpu數(shù)量。
  • CPU – 正在運(yùn)行這個任務(wù)的處理器編號。
  • Command – 這個任務(wù)的命令名稱。

參考資料:

《Linux內(nèi)核設(shè)計與實現(xiàn)》

《Linux性能優(yōu)化實戰(zhàn)》

http://ifeve.com/context-switch-definition https://www.it610.com/article/1289356670568308736.htm

相關(guān)閱讀

主站蜘蛛池模板: 在线欧美一区 | 亚洲 欧美 手机 在线观看 | 久久99国产综合精品 | 欧美成人福利视频 | 国产日韩欧美一区二区 | 欧美午夜不卡 | 色多多最新地址福利地址 | 欧美高清在线视频一区二区 | 国产在线一区二区三区在线 | 日韩视频一区二区 | 在线看片a | xxx国产hd| 免费看特级毛片 | 国产精品系列在线一区 | 欧美一级毛片免费网站 | 欧美另类videosgrstv变态 欧美另类高清xxxxx | 九九九热在线精品免费全部 | 日本精品一区二区三区在线视频 | 爱久久精品国产 | 亚洲欧美日韩精品久久亚洲区色播 | 韩国一级a毛片 | 精品日韩在线视频一区二区三区 | 福利一二三区 | 久久99国产亚洲高清观看韩国 | 亚洲精品综合一区在线 | 日韩欧美印度一级毛片 | 性欧美欧美之巨大69 | 国产成人精品免费视频软件 | 久久九九精品视频 | 国产成人一区二区三区精品久久 | 亚洲精品欧美精品中文字幕 | 91国偷自产一区二区三区 | 亚洲天堂视频网站 | 日韩亚洲国产综合久久久 | 国产精品亚洲一区二区三区 | 精品欧美高清一区二区免费 | 国产精品亚洲欧美云霸高清 | 亚洲美女综合网 | 永久毛片 | 婷婷的久久五月综合先锋影音 | 国产免费一区二区三区免费视频 |