色偷偷91综合久久噜噜-色偷偷成人-色偷偷尼玛图亚洲综合-色偷偷人人澡久久天天-国内精品视频一区-国内精品视频一区二区三区

Hello! 歡迎來到小浪云!


聊聊Linux中CPU上下文切換


avatar
小浪云 2025-01-04 144

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

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

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

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

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

CPU上下文切換

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

CPU上下文切換的步驟:

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

CPU 的上下文切換分三種:進程上下文切換、線程上下文切換、中斷上下文切換。

上一任務的CPU上下文保存在哪?

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

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

進程上下文切換

內核空間和用戶空間

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

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

?

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

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

?

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

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

top命令查看CPU資源

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

其中各項數據表示內容:

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

系統(tǒng)調用

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

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

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

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

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

進程上下文切換 和 系統(tǒng)調用的區(qū)別

  1. 進程上下文切換是指,從一個進程切換到另一個進程;系統(tǒng)調用過程一直是同一個進程在運行,屬于進程之內的上下文切換

?

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

聊聊Linux中CPU上下文切換

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

進程切換的常見場景

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

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

線程上下文切換

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

關于進程和線程的區(qū)別:

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

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

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

中斷上下文切換

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

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

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

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

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

上下文切換的消耗

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

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

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

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

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

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

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

聊聊Linux中CPU上下文切換

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

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

  • r:等待運行的進程數。
  • b:休眠狀態(tài)下的進程數。

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

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

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

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

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

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

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

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

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

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

補充:pidstat命令查看進程的CPU上下文切換情況

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

在結果中你能看到如下內容:

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

參考資料:

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

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

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

相關閱讀

主站蜘蛛池模板: 久草青青在线 | 日本三级韩国三级香港三级a级 | 色黄网站aaaaaa级毛片 | 一区在线视频 | 日韩狠狠操 | 日韩女同| 亚洲男人的天堂在线视频 | 免费国产黄 | 亚洲精品第三页 | 99热这里只有精品一区二区三区 | 97婷婷色 | 91亚洲国产三上悠亚在线 | 色亚洲一区 | 爱操影院 | 日本高新1区2区3区 日本搞基网站 | 国产在线视频国产永久视频 | 99爱视频99爱在线观看免费 | 色综合久久精品中文字幕 | 4虎影视国产在线观看精品 4虎影院午夜在线观看 | 久久综合精品国产一区二区三区 | 色综合五月激情综合色一区 | 米奇色777狠狠欧美一区 | 色玖玖 | 视频在线观看黄 | 天天综合天天看夜夜添狠狠玩 | 特黄特色大片免费播放 | 亚洲综合在线成人一区 | 国产伦久视频免费观看 视频 | 一区二区网站在线观看 | 韩国美女视频黄是免费 | 一级片视频免费观看 | 四虎在线精品视频一二区 | 亚洲性久久 | 精品一区二区视频在线观看 | 奇米视频888| 亚洲精品不卡久久久久久 | 成人激情开心 | 一区二区三区高清 | 国产精品久久久久久福利漫画 | 亚洲丝袜中文字幕 | 国产精品国产三级国产普通话 |