Linux內核實現中斷和中斷處理(二)

来源:http://www.cnblogs.com/lenomirei/archive/2016/06/08/5564131.html
-Advertisement-
Play Games

第一部分移步傳送門召喚!!:http://www.cnblogs.com/lenomirei/p/5562086.html 上回說了Linux內核實現中斷會把中斷分為兩部分進行處理,上回講了上部分,這回講下部分的設計思路 下半部的實現機制 軟中斷 tasklet:是通過軟中斷實現的,但和軟中斷有所不 ...


第一部分移步傳送門召喚!!:http://www.cnblogs.com/lenomirei/p/5562086.html

上回說了Linux內核實現中斷會把中斷分為兩部分進行處理,上回講了上部分,這回講下部分的設計思路

  • 下半部的實現機制
    • 軟中斷
    • tasklet:是通過軟中斷實現的,但和軟中斷有所不同
    • 工作隊列

講上面幾個實現機制之前先講一個古老的方法,現在版本的內核雖然已經不再食用了,但是思想還在繼續使用

最早的Linux只提供了“bottom half”這種機制實現下半部分,被稱為BH,實現簡單粗暴,設置一個全局變數(32位整數),表示一個32個節點的鏈表隊列,哪位設置為1證明哪個bottom half就可以執行了。

 

 

  • 軟中斷

第一個先將軟中斷實現下半部分機制,要想將這個機制,必須得先說明軟中斷的實現方式,軟中斷實在編譯期間靜態分配的,kernel/softirq.c中定義了一個包含有32個結構體的數組static struct softirq_action softirq_vec[NR_SOFTIRQS],並且有一個對應的32位整數u32 pending,用來表示每個軟中斷的狀態(不要嫌少,一般根本用不了那麼多,一般9個10個就夠用了,為什麼這麼少?很少有用軟中斷處理下半部分的,能用tasklet的地方絕不會使用軟中斷)

把軟中斷放進剛纔說的32個長度的結構體數組中就完成了軟中斷的註冊,想要執行軟中斷必須先標記註冊好的軟中斷,這個過程被稱為觸發軟中斷,通常,中斷處理程式(就是上半部分)會在返回之前標記它的軟中斷,所以不必擔心,然後在合適的時刻就會執行該軟中斷

合適的時刻:1.從一個硬體中斷代碼處返回時;2.在ksoftirqd內核線程中;3.在那些顯示檢查和執行待處理的軟中斷的代碼中;

不管是上面哪個時刻,軟中斷最終都是會被執行的,調用do_softirq()該函數會迴圈遍歷(迴圈檢查pending的每一個位,所以迴圈最多只能執行32次)

  • tasklet

因為takslet是使用軟中斷實現的,所以tasklet本身就是個軟中斷,我們是通過tasklet來實現下半部的機制的,所以在處理方式上和軟中斷十分的相似,tasklet由tasklet結構體表示,每一個結構體單獨代表一個tasklet,它的定義如下

 

1 struct tasklet_struct
2 {
3      stauct tasklet_struct *next;//鏈表中的下一個節點
4      unsigned long state;//tasklet的狀態
5      atomic_t count;//引用計數器
6      void (*func)(unsigned long);//tasklet處理函數
7      unsigned long data;//給tasklet處理函數的參數
8 };

 

其中tasklet的狀態一共只有三種:0,TASKLET_STATE_SCHED,TASKLET_STATE_RUN,只能在這三種之間取值,0表示啥也沒有等待調度,SCHED表示已經調度,RUN表示該tasklet正在運行。

已經被調度的tasklet結構體存放在兩種單處理器數據結構當中,分別是tasklet_vec(普通優先順序的tasklet)和tasklet_hi_vec(高優先順序的tasklet),幾乎沒區別,只是優先順序不一樣,調度的步驟如下

  1. 檢查tasklet的狀態是否為TASKLET_STATE_SCHED,如果是,就證明不需要調度了,直接返回
  2. 調用_tasklet_schedule()函數進行調度
  3. 保存中斷狀態,禁止本地中斷,防止數據被其他中斷拿去更改
  4. 頭插加入鏈表,就剛纔說的那兩個優先順序不同的鏈表
  5. 喚起tasklet中斷(封裝好的軟中斷)
  6. 恢復中斷並返

運行的步驟如下:

  1. 禁止中斷,檢測兩個鏈表裡面有沒有東西
  2. 把當前處理器的該鏈表設置為NULL(意思就是我要把鏈表裡的東西全弄完,先置成NULL)
  3. 允許相應中斷
  4. 迴圈遍歷tasklet鏈表上的每一個節點
  5. 如果是多處理器系統,查看節點狀態如果是RUN就證明在其他處理器上運行中,直接跳到下一個節點(因為同一時間里,相同類型的tasklet只有一個能執行)
  6. 如果當前節點的狀態不是RUN,就設置成RUN,以防其他處理器調用
  7. 檢查count是不是0(看看別人是否正在占用)如果不是0則被禁止,跳到下一個掛起的tasklet去
  8. 安全確保,開始執行
  9. 一直迴圈,直到沒有tasklet了(因為我們把鏈表置為NULL了,必須把拿出來的東西處理完)

 

 

其實tasklet給人的感覺就是一個對軟中斷的封裝的簡單介面而已。。 

每個處理器都有一組輔助處理軟中斷(當然也就包括tasklet)的內核線程,那麼什麼時候執行這些軟中斷呢,上面在軟中斷部分也闡述了,但是這樣有個問題,那就是軟中斷如果繼續調軟中斷,就會不停的執行軟中斷。。這樣在處理器負載很嚴重的時候就不太好了,會導致用戶空間進程饑餓,還有一種方案,那就是並不立即處理軟中斷,而是等待一段時間,但是在處理器比較閑的時候這麼做很顯然不太好,因為完全可以立即執行你卻讓處理器閑著。作為改進,當大量軟中斷出現的時候,內核會喚醒一組內核線程來處理這些負載,關鍵來了,這些帶著軟中斷的線程的優先順序會被設置到最低的優先順序上(nice值取最高為19),這樣的會在處理器比較忙的時候,這些軟中斷不會跟用戶空間進程爭奪處理器資源,而且最終一定會被執行,處理器空閑的時候也可以直接得到運行。

  • 工作隊列

工作隊列是另外一種比較新的將工作推後的形式,和之前的兩種處理方式不同,它會把工作交給一個內核線程去執行,這就意!味!著!是由進程上下文來處理了!就可以睡眠了!!(中斷是不允許睡眠的)所以很簡單就可以在這兩種方法之間做出選擇。

每一個處理器都有一個對應的工作者線程

 

1 struct workqueue_struct
2 {
3      struct cpu_work_queue_struct cpu_wq[NR_CPUS];
4      struct list_head list;
5      const char *name;
6      int sinqlethread;
7      int freezeable;
8      int rt;
9 };

 

 

1 struct cpu_workqueue_struct
2 {
3      spinlck_t lock;//鎖保護這種結構
4      struct list_head worklist;//工作列表
5      wait_queue_head_t more_work;
6      struct work_struct *current_struct;
7      struct workqueue_struct *wq;//關聯工作隊列結構
8      task_t *thread;//關聯線程
9 };

 

表示工作的數據結構

 

1 struct work_struct
2 {
3      atomic_long_t data;
4      struct list_head entry;
5      work_func_t func;
6 };

 

 

這些工作的結構體被連城鏈表,當鏈表上的所有工作都做完了之後,線程就會休眠

實現方式也很簡單,

  1. 線程首先把自己設置為休眠狀態(只是設置,並沒有立即進入休眠)並把自己加入等待隊列
  2. 如果工作鏈表是空的,就用schedule()調度函數進入睡眠狀態
  3. 如果鏈表中有對象,線程就不會睡眠了,就把自己的狀態改為TASK_RUNNING,然後從等待隊列中出來
  4. 如果鏈表非空,執行那些被退後的下半部分應該乾的工作(就是迴圈一直找。。。)

來個結構圖

 

  • 下半部機制的選擇

這三種看上去都不錯,那麼應該怎麼選擇呢

如果你對共用有很高的要求,雖然比較麻煩,但還是使用軟中斷吧,因為可以各種操作(雖然保障這些很麻煩)

如果你不是對共用有那麼高的要求,推薦使用tasklet,因為兩種同類型的tasklet不能同時並行

如果你想在進程上下文中解決下半部分的問題,使用工作隊列吧,當然如果你想睡眠,你也沒得選了

* 全劇終*


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

-Advertisement-
Play Games
更多相關文章
  • 表空間是資料庫的邏輯組織形式,在一個資料庫中可以創建多個表空間。 表空間的主要作用是將不同用途的數據分離開來,以提高數據的安全性,並提高系統的性能。表空間在資料庫中起著非常重要的作用。 一方面,表空間在邏輯結構上由多個段組成,數據都存儲在表空間的段中,另一方面,表空間在物理結構上對應著多個數據文件, ...
  • 一、增:有4種方法 1.使用insert插入單行數據: 語法:insert [into] <表名> [列名] values <列值> insert into sheet1 values ('000000','000000','0','張三','000000','000000','000000','0 ...
  • 添加數據: 課程表: 添加數據: 成績表: 添加數據: 教師表: 添加數據: ...
  • 由於MySQL的版本不同,所以會有不同的安裝方式。在下以Linux系統下MySQL5.1.19版本為例,進行安裝,初學還望指正。 一、安裝編譯軟體(簡單的yum安裝) gcc gcc-c++ ncurses ncurses-devel cmake 二、修改hosts可以解析主機名 echo "127 ...
  • /* 本文是基於搬瓦工vps的centos-6-x86_64的Linux系統搭建。 需準備的工具:1、putty(用於連接Linux系統) 2、WinSCP(搬瓦工官方提供的ftp上傳下載工具) */ 1、使用WinSCP工具連接Linux進行文件管理 然後將jdk的tar.gz文件和tomcat的 ...
  • 系統鏡像及環境要求: 1) 適用於windows系列版本及開發者的相關教程 請參考本文1.0開始安裝步驟 2) Centos 6系列及Aliyun Linux 6系列以上版本 請參考本文2.0開始安裝步驟 3) Centos 5系列及Aliyun Linux 5系列版本,請參考本文3.0開始安裝步驟 ...
  • 本文是Linux Shell系列教程的第(八)篇,更多shell教程請看:Linux Shell系列教程 在上一篇:Linux Shell系列教程之(七)Shell輸出這篇文章中,已經對Shell printf命令有了一個簡略的介紹,本篇給大家詳細介紹下Shell中的printf命令。 一、Shel ...
  • 到目前為止,Robomongo仍是MongoDB最好的客戶端管理工具,如需在Ubuntu上安裝Robomongo,可直接從官網下載.tar.gz壓縮包進行解壓,然後直接運行bin目錄下的robomongo文件即可啟動界面。例如我將下載下來的.tar.gz壓縮包解壓到/usr/local/share目 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...