改善Linux內核實時性方法的研究與實現

2020-12-17 電子產品世界

  0 引言

本文引用地址:http://www.eepw.com.cn/article/261723.htm

  由於Linux具有功能強大、原始碼開放、支持多種硬體平臺、模塊化的設計方案以及豐富的開發工具支持等特點,在實際系統中,得到了廣泛的應用。但由於其最初的設計目標為通用分時作業系統,對於實時系統而言,Linux仍然存在核心不可搶佔、關中斷、時鐘粒度粗糙等缺陷。為了使其應用於嵌入式系統,實時控制等領域,越來越多的廠家和研究機構熱衷於改善其實時性,構建基於Linux的實時作業系統。

  在Linux 2.4和以前的版本,內核是不可搶佔的,也就是說,如果當前任務運行在內核態,即使當前有更緊急的任務需要運行,當前任務也不能被搶佔。因此那個緊急任務必須等到當前任務執行完內核態的操作返回用戶態後或當前任務因需要等待某些條件滿足而主動讓出CPU才能被考慮執行,這很明顯嚴重影響搶佔延遲。在 Linux 2.6中,內核已經可以搶佔,因而實時性得到了加強。但是內核中仍有大量的不可搶佔區域, 如由自旋鎖spinlock保護的臨界區,以及一些失效搶佔的臨界區。另一個影響Linux實時性的因素就是關中斷,同步操作中使用的關中斷指令增大了中斷延遲,這樣很多由中斷驅動的實時任務得不到及時的執行,系統的實時性能得不到保障。因此提高Linux的可搶佔性,改進其中斷機制有利於改善內核的實時性。

  本文詳細闡述了這些措施的原理並基於標準Linux2.6內核加以實現,最後通過測試,驗證了此改進方法的效果。

  1 中斷線程化

  1.1 Linux中斷對內核實時性的影響

  中斷處理是由內核執行的最敏感的任務之一,當內核正打算去做一些別的事情時,中斷隨時會到來,中斷當前的任務進而執行中斷處理程序。因此內核的目標就是讓中斷儘可能快的處理完,盡其所能把更多的處理工作向後推遲。為此Linux把中斷的處理分成上半部分和下半部分。上半部分立即執行,下半部分將喚醒相應的和中斷處理相關的進程稍後執行。雖然這種機制使得中斷處理變得更加高效和易於維護,但是對於系統如果有嚴重的網絡負載或其他I/O負載時,中斷將非常頻繁,內核當前的實時任務會被不停中斷,這對於Linux的實時應用來說是不可接受的。

  另外,Linux為了使內核同步而採用了關中斷,在內核的關中斷區域,中斷是被屏蔽的。即使此時有通過中斷驅動的實時任務也得不到響應,增加了實時任務的中斷延遲。實時化後的Linux中,自旋鎖被互斥鎖取代,而中斷處理代碼中大量運用了自旋鎖,中斷處理代碼就有可能因為得不到鎖而需要被掛到該鎖的等待隊列上去。但是只有可調度的進程才可這麼做,如果中斷處理代碼仍然使用原來的自旋鎖,那麼互斥鎖取代自旋鎖改進內核實時性的努力將大打折扣。

  線程化的中斷管理可以有效的解決這些問題。中斷線程化後,中斷將作為內核線程運行而且賦予不同的實時優先級,實時任務可以有比中斷線程更高的優先級,這樣,實時任務就可以作為最高優先級的執行單元來運行,即使在嚴重負載下仍有實時性保證。另一方面中斷處理線程也可以因為在內核同步中得不到鎖而掛載到鎖的等待隊列中。很多關中斷就不必真正的禁止硬體中斷了,而是禁止內核進程搶佔,這樣就可以減小中斷延遲。

  1.2 設計與實現

  Linux提供了kthread_create創建內核線程,該內核線程在內核空間執行,因此在調度時沒有用戶空間和內核空間切換,使得其運行更為高效。中斷線程化要做的工作是創建中斷線程以及中斷的處理。中斷線程是在系統初始化或者調用requestirq函數時通過 kthread_create函數創建的。其過程等同於如下功能代碼:

  

 

  對於非緊急中斷,kthread_create為其創建一個內核線程,並且根據中斷號為其賦予一定的靜態實時優先級和設置其調度策略。中斷到來後,內核並不是直接進入中斷服務函數,而是通過設置調度標誌告知內核,內核調度程序比較該中斷線程的優先級和當前運行任務的優先級,作出調度決策。因此當前正在運行的高優先級的實時任務不會受中斷的太大的影響,保證了實時任務運行的可靠性和準確性,中斷線程將會其他合適的時刻被調度執行,而且 Linux2.6內核的O(1)調度機制也不會因為內核線程數的增加在調度時間上額外增加調度開銷。對於緊急的中斷(比如時鐘中斷),內核保持原來的中斷處理方式,而不為其創建中斷線程,這樣保證了緊急中斷的快速響應。

  2 自旋鎖改互斥鎖

  2.1 新的自旋鎖設計

  為了同步不同內核控制路徑對共享資源的訪問,標準Linux內核提供了很多內核同步原語,其中自旋鎖spinlock是一種廣泛應用於可搶佔內核,SMP環境下的內核同步機制。在spinlock的保持期間,內核是搶佔失效的。被自旋鎖保護的區域稱為臨界區,內核中大量使用了spinlock,存在大量的內核不可搶佔的臨界區,這將嚴重影響系統的實時性,我們使用新的實時互斥鎖rt_mutex來替換spinlock,即讓臨界區內內核可搶佔。其結構體如下:

  

 

  類型raw_spinlock_t就是原來的spinlock_t。新的自旋鎖還是使用spinlock_t來標記。在結構struct rt_mutex中的wait_list欄位就是優先級化的等待隊列。Owner欄位為擁有該鎖的進程的環境信息。mutex比spinlock優越的地方有這麼幾點:(1)當遇到一個鎖住的臨界區時,任務被掛起到鎖的優先級等待隊列wait_list中,臨界區解鎖時等待任務被激活。(2)內核將一個鎖住的臨界區和一個任務關聯,當獲得互斥鎖時將任務的標識存入鎖中。(3)臨界區可以在被保護的同時不禁止搶佔。(4)在被鎖住的臨界區中可以實現優先級繼承。

  2.2 實時互斥鎖的操作

  並不是所有內核中的自旋鎖都可以轉換為互斥鎖的,一些底層的臨界區必須是不可搶佔的,所以必須由不可搶佔的自旋鎖保護,比如:保護硬體寄存器的鎖、調度器的運行隊列鎖、和其它不可搶佔自旋鎖嵌套的鎖。實時內核中,不可搶佔的自旋鎖與RT互斥鎖共存,不可搶佔的自旋鎖被重命為 raw_spinlock_t。spin_lock函數利用gcc的內嵌技術根據鎖的類型通過預處理選擇具體的鎖執行函數。預處理器使用 __builtin_types_compatible函數,由宏TYPE_EQUAL調用:

linux作業系統文章專題:linux作業系統詳解(linux不再難懂)

linux相關文章:linux教程


相關焦點

  • Linux2.6下自主設計的PROFIBUS-DP單主站的實時性研究
    2.1 Linux2.6的實時性分析 Linux2.6內核相對以前的Linux內核在實時性方面有了很大的增強,包括O(1)調度器、可搶佔式內核、改進的線程模型以及對新的NPTL(Native Posix Threading Library)的支持。
  • Linux 系統內核的調試
    本文將首先介紹 Linux 內核上的一些內核代碼監視和錯誤跟蹤技術,這些調試和跟蹤方法因所要求的使用環境和使用方法而各有不同,然後重點介紹三種 Linux 內核的原始碼級的調試方法。  調試是軟體開發過程中一個必不可少的環節,在 Linux 內核開發的過程中也不可避免地會面對如何調試內核的問題。
  • Linux 內核學習:環境搭建和內核編譯
    內核學習之一:環境搭建--安裝Debian7.3本系列文章假設讀者已對linux有一定的了解,其實學習linux內核不需要有很深的關於linux的知識,只需要了解以下內容:linux基礎知識及基本shell命令;現代作業系統的基本概念;C語言和gcc基本使用。
  • 一張圖看懂Linux內核中Percpu變量的實現
    但你知道嗎,不僅是在程式語言中,在linux內核中,也有一個類似的機制,用來實現類似的目的,它叫做percpu變量。percpu變量,顧名思義,就是對於同一個變量,每個cpu都有自己的一份,它可以被用來存放一些cpu獨有的數據,比如cpu的id,cpu上正在運行的線程等等,因該機制可以非常方便的解決一些特定問題,所以在內核編程中被廣泛使用。
  • 一張圖看懂linux內核中percpu變量的實現
    但你知道嗎,不僅是在程式語言中,在linux內核中,也有一個類似的機制,用來實現類似的目的,它叫做percpu變量。percpu變量,顧名思義,就是對於同一個變量,每個cpu都有自己的一份,它可以被用來存放一些cpu獨有的數據,比如cpu的id,cpu上正在運行的線程等等,因該機制可以非常方便的解決一些特定問題,所以在內核編程中被廣泛使用。
  • Linux內核編譯初體驗
    下載內核在ftp://ftp.kernel.org/pub/linux/kernel/下載原版內核本文引用地址:http://www.eepw.com.cn/article/201611/319326.htm此處使用linux-2.6.22.6.tar.bz22.
  • Linux 內核如何處理中斷|Linux 中國
    本文字數:2640,閱讀時長大約:4分鐘 https://linux.cn/article-12965-1.html 作者:Stephan Avenwedde 譯者:萌新阿巖 中斷是現代 CPU 工作方式中重要的部分。
  • Linux內核學習:簡單的字符設備驅動
    學習Linux內核最好的入門方式之一是從字符設備驅動開始模仿(來自於《奔跑吧 Linux內核——入門篇》)。對於我們日常生活中存在的大量設備,如攝像頭,USB充電器,藍牙,Wi-Fi等,這些設備在電氣特性和實現原理均不相同,對Linux系統來說如何抽象和描述他們呢?Linux很早就根據設備共同特徵將其劃分為三大類型:1,字符設備;塊設備;網絡設備。
  • Linux內核啟動-內核解壓縮
    本文引用地址:http://www.eepw.com.cn/article/148792.htm從內核的生成過程來看內核的連結主要有三步:第一步是把內核的原始碼編譯成.o文件,然後連結,這一步,連結的是arch/i386/kernel/head.S,生成的是vmlinux。
  • linux-3.18內核系統調用
    否則,如果某個用戶應用試圖調用這些已經被淘汰的系統調用,所得到的結果,比如打開了一個文件,就會與預期完全不同,這將令人感到非常奇怪。其實,sys_ni_syscall中的"ni"即表示"not implemented(沒有實現)"。
  • Linux 內核的測試和調試(6)
    注意不要以附件形式發送補丁,而是以純文本形式粘貼在郵件裡面。確保你的郵件客戶端可以發送純文本信息,你可以試試給自己發送一份補丁郵件來測試你的郵件客戶端的功能。收到自己的郵件後,運行 checkpatch 命令並給自己的內核源碼打上你的補丁。如果這兩部都能通過,你就可以給 Linux 郵箱列表發送補丁了。使用 git send-email 命令是提交補丁最安全的方式,可以避免你的郵箱的兼容性問題。
  • 嵌入式linux內核的編譯步驟
    嵌入式linux內核的編譯步驟 華清遠見 發表於 2020-06-19 09:30:24   編譯嵌入式Linux內核都是通過make的不同命令來實現的,它的執行配置文件是
  • 深入理解Linux內核鍊表
    在Linux內核中使用了大量的鍊表結構來組織數據,包括設備列表以及各種功能模塊中的數據組織。這些鍊表大多採用在[include/linux/list.h]實現的一個相當精彩的鍊表數據結構。本文的後繼部分就將通過示例詳細介紹這一數據結構的組織和使用。
  • linux內核移植-移植2.6.35.4內核到s3c2440
    本來是想移植最新的內核2.6.39但是總是在編譯快完成的時候報錯,有人說是新的內核對arm平臺的支持不好,所以就降低了一下版本,這裡移植2.6.35.4內核一、準備工作1、下載 解壓內核從官網上下載linux-2.6.35的內核, ftp://ftp.kernel.org/pub/linux/kernel/v2.6/ ,文件不大,約85M。
  • Ubuntu中升級Linux內核
    從這段話中所表達出的意思可以了解,Linux Kernel 4.3版本已經開始進行,Linus Torvalds也收到了一些新的請求,但具體如何改進還要進一步研究確定。  ●支持ARCv2和HS38 CPU內核  ●增加了隊列自旋鎖的支持  ●許多其他的改進和驅動更新。
  • linux配置、編譯內核實用工具
    Make  Make是一種幫助大型軟體工程的編譯工作實現自動化的程式語言。正確地使用Make可以大大減少因編譯程序而花費的時間,因為它可以消除不必要的再編譯。
  • ARM Linux內核啟動要求
    arm.linux.org.uk/developer/booting.php本文引用地址:http://www.eepw.com.cn/article/201611/316973.htmAuthor: Russell KingInitial date: May 18, 2002Revision:1 - 17 September 20042
  • Linux內核常用的動態調試手段
    @u-jeff ~]# cat /sys/kernel/debug/tracing/kprobe_events p:probe/do_sys_open _text+2391184 filename_string=+0(%si):string flags_u32=%dx:u32第二類就是使用trace event:比如像lin
  • linux內核啟動流程
    Linux內核啟動及文件系統加載過程   當u-boot開始執行bootcmd命令,就進入Linux內核啟動階段,與u-boot類似,普通Linux內核的啟動過程也可以分為兩個階段,但針對壓縮了的內核如uImage就要包括內核自解壓過程了。本文以linux-2.6.37版源碼為例分三個階段來描述內核啟動全過程。
  • 使用Kdump檢查Linux內核崩潰
    讓我們先看一下 kdump 的基本使用方法,和 kdump/kexec 在內核中是如何實現。 kdump 是獲取崩潰的 Linux 內核轉儲的一種方法,但是想找到解釋其使用和內部結構的文檔可能有點困難。