【原創】(三)Linux進程調度器-進程切換

来源:https://www.cnblogs.com/LoyenWang/archive/2020/02/29/12386281.html
-Advertisement-
Play Games

背景 By 魯迅 By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex A53,雙核 3. 使用工具:Source Insight 3.5, Visio 1. 概述 進程切換:內核將CPU上正在運行的進程掛起,選擇下一個進程來運行。 ARM架構中,CPU上一次 ...


背景

  • Read the fucking source code! --By 魯迅
  • A picture is worth a thousand words. --By 高爾基

說明:

  1. Kernel版本:4.14
  2. ARM64處理器,Contex-A53,雙核
  3. 使用工具:Source Insight 3.5, Visio

1. 概述

進程切換:內核將CPU上正在運行的進程掛起,選擇下一個進程來運行。
ARM架構中,CPU上一次只能運行一個任務,內核需要為任務分配運行時間來進行調度,以便同時能處理多個任務請求。
如下圖所示:

當進行任務切換的時候,思考下兩個問題:

  1. 怎樣通過搶占來實現進程的切換?
  2. 當進程切換的時候,到底切換的什麼,是怎麼實現的?

這兩個問題,也是本文探討的主題了。

2. 搶占

2.1 用戶搶占

2.1.1 搶占觸發點

  • 可以觸發搶占的情況很多,比如進程的時間片耗盡、進程等待在某些資源上被喚醒時、進程優先順序改變等。Linux內核是通過設置TIF_NEED_RESCHED標誌來對進程進行標記的,設置該位則表明需要進行調度切換,而實際的切換將在搶占執行點來完成。

不看代碼來講結論,那都是耍流氓。先看一下兩個關鍵結構體:struct task_structstruct thread_info。我們在前邊的文章中也講過struct task_struct用於描述任務,該結構體的首個欄位放置的正是struct thread_infostruct thread_info結構體中flag欄位就可用於設置TIF_NEED_RESCHED,此外該結構體中的preempt_count也與搶占相關。

struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info      thread_info;
#endif
        ...
}

/*
 * low level task data that entry.S needs immediate access to.
 */
struct thread_info {
    unsigned long       flags;      /* low level flags */
    mm_segment_t        addr_limit; /* address limit */
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
    u64         ttbr0;      /* saved TTBR0_EL1 */
#endif
    int         preempt_count;  /* 0 => preemptable, <0 => bug */
};

#include <asm/current.h>
#define current_thread_info() ((struct thread_info *)current)   //通過該巨集可以直接獲取thread_info的信息
#endif

看看具體哪些函數過程中,設置了TIF_NEED_RESCHED標誌吧:

  • 內核提供了set_tsk_need_resched函數來將thread_infoflag欄位設置成TIF_NEED_RESCHED
  • 設置了TIF_NEED_RESCHED標誌,表明需要發生搶占調度;

2.1.2 搶占執行點

用戶搶占:搶占執行發生在進程處於用戶態。
搶占的執行,最明顯的標誌就是調用了schedule()函數,來完成任務的切換。
具體來說,在用戶態執行搶占在以下幾種情況:

  • 異常處理後返回到用戶態;
  • 中斷處理後返回到用戶態;
  • 系統調用後返回到用戶態;

如下圖:

  • ARMv8有4個Exception Level,其中用戶程式運行在EL0,OS運行在EL1,Hypervisor運行在EL2,Secure monitor運行在EL3;
  • 用戶程式在執行過程中,遇到異常或中斷後,將會跳到ENTRY(vectors)向量表處開始執行;
  • 返回用戶空間時進行標誌位判斷,設置了TIF_NEED_RESCHED則需要進行調度切換,沒有設置該標誌,則檢查是否有收到信號,有信號未處理的話,還需要進行信號的處理操作;

2.2 內核搶占

Linux內核有三種內核搶占模型,先上圖:

  • CONFIG_PREEMPT_NONE:不支持搶占,中斷退出後,需要等到低優先順序任務主動讓出CPU才發生搶占切換;
  • CONFIG_PREEMPT_VOLUNTARY:自願搶占,代碼中增加搶占點,在中斷退出後遇到搶占點時進行搶占切換;
  • CONFIG_PREEMPT:搶占,當中斷退出後,如果遇到了更高優先順序的任務,立即進行任務搶占;

2.2.1 搶占觸發點

  • 在內核中搶占觸發點,也是設置struct thread_infoflag欄位,設置TIF_NEED_RESCHED表明需要請求重新調度。
  • 搶占觸發點的幾種情況,在用戶搶占中已經分析過,不管是用戶搶占還是內核搶占,觸發點都是一致的;

2.2.2 搶占執行點

內核搶占:搶占執行發生在進程處於內核態。

總體而言,內核搶占執行點可以歸屬於兩大類:

  • 中斷執行完畢後進行搶占調度;
  • 主動調用preemp_enableschedule等介面的地方進行搶占調度;

2.3 preempt_count

  • Linux內核中使用struct thread_info中的preempt_count欄位來控制搶占。
  • preempt_count的低8位用於控制搶占,當大於0時表示不可搶占,等於0表示可搶占。
  • preempt_enable()會將preempt_count值減1,並判斷是否需要進行調度,在條件滿足時進行切換;
  • preempt_disable()會將preempt_count值加1;

此外,preemt_count欄位還用於判斷進程處於各類上下文以及開關控制等,如圖:

3. 上下文切換

  • 進程上下文:包含CPU的所有寄存器值、進程的運行狀態、堆棧中的內容等,相當於進程某一時刻的快照,包含了所有的軟硬體信息;
  • 進程切換時,完成的就是上下文的切換,進程上下文的信息會保存在每個struct task_struct結構體中,以便在切換時能完成恢復工作;

進程上下文切換的入口就是__schedule(),分析也圍繞這函數展開。

3.1 __schedule()

__schedule()函數調用分析如下:

主要的邏輯:

  • 根據CPU獲取運行隊列,進而得到運行隊列當前的task,也就是切換前的prev;
  • 根據prev的狀態進行處理,比如pending信號的處理等,如果該任務是一個worker線程還需要將其睡眠,並喚醒同CPU上的另一個worker線程;
  • 根據調度類來選擇需要切換過去的下一個task,也就是next
  • context_switch完成進程的切換;

3.2 context_switch()

context_switch()的調用分析如下:

核心的邏輯有兩部分:

  • 進程的地址空間切換:切換的時候要判斷切入的進程是否為內核線程,1)所有的用戶進程都共用一個內核地址空間,而擁有不同的用戶地址空間;2)內核線程本身沒有用戶地址空間。在進程在切換的過程中就需要對這些因素來考慮,涉及到頁表的切換,以及cache/tlb的刷新等操作。
  • 寄存器的切換:包括CPU的通用寄存器切換、浮點寄存器切換,以及ARM處理器相關的其他一些寄存器的切換;

進程的切換,帶來的開銷不僅是頁表切換和硬體上下文的切換,還包含了Cache/TLB刷新後帶來的miss的開銷。在實際的開發中,也需要去評估新增進程帶來的調度開銷。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 作者: 魔法軟糖 日期: 2020-02-27 引言 ************************************* .ini 文件是Initialization File的縮寫,即配置文件 。是windows的系統配置文件所採用的存儲格式。 它具有方便易用的特點,和註冊表的鍵值有著類似 ...
  • 最近開始試著玩Unity3D,要為場景中的物體編輯腳本。Unity3D推薦的腳本語言是C#,在Unity打開C#就會使用Visual Studio來進行編輯。 啟動Visual Studio之後註意到,Unity類和方法名都沒有代碼補全,而且Unity似乎也編譯不過: 在網上找了一圈,發現並沒有人遇 ...
  • 在 C 中 Object 是所有類的基類,所有的結構和類都直接或間接的派生自它。前面這段話可以說所有的 C 開發人員都知道,但是我相信其中有一部分程式員並不清楚甚至不知道我們常用的 ToString 、 Equals 和 GetHashCode 虛方法都來自於 Object 類,並且我們可以對它們進 ...
  • 前言 今天這篇博客是接我的上一篇博客 https://www.cnblogs.com/y-yp/p/12191258.html,繼續介紹一下MMF在Linux上的用法 ps:本來本地調試完case,想放到伺服器上跑跑看,結果竟然報"PlatformNotSupportedException",然後仔 ...
  • selinux概念 由美國國家安全局(NSA)和SCC聯合開發的,強制訪問控制的安全模塊。2000年以GPL開源,linux2.6內核後集成在內核里。 不啟用selinux時,訪問模式叫:DAC(discretionary access control)自由訪問控制 在DAC模式下的進程能夠訪問哪些 ...
  • 出現這個錯誤時,這多半是你所編譯的項目是在64位機器上生成32位的項目,你需要安裝對應的gcc 32位的庫;此時檢查gcc一定有-m32的存在; 你系統中gcc沒有安裝multilib 庫;使用這個庫可以在64位的機器上產生32位的程式或者庫文件; 你可以選擇:apt install gcc-mul ...
  • 1.SetUID 一.SetUID的功能 SetUID主要是給命令提供一個root許可權,就是命令運行時擁有root用戶許可權,命令運行結束後root許可權消失 passwd cat 二.設定SetUID的方法 4代表SUID chmod 4755 文件名 chmod u+s 文件名 三.取消SetUID ...
  • 1.ACL許可權簡介與開啟 一.ACL許可權是為瞭解決所有者/所屬組/其他人三種身份不足的問題 二.查看分區ACL許可權是否開啟 dumpe2fs命令是查詢指定分區詳細文件系統信息的命令 dumpe2fs h /dev/sda3 Default mount options: user_xattr acl顯 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...