⑴ linux內核同步問題
Linux內核設計與實現 十、內核同步方法
手把手教Linux驅動5-自旋鎖、信號量、互斥體概述
== 基礎概念: ==
並發 :多個執行單元同時進行或多個執行單元微觀串列執行,宏觀並行執行
競態 :並發的執行單元對共享資源(硬體資源和軟體上的全局變數)的訪問而導致的竟態狀態。
臨界資源 :多個進程訪問的資源
臨界區 :多個進程訪問的代碼段
== 並發場合: ==
1、單CPU之間進程間的並發 :時間片輪轉,調度進程。 A進程訪問列印機,時間片用完,OS調度B進程訪問列印機。
2、單cpu上進程和中斷之間並發 :CPU必須停止當前進程的執行中斷;
3、多cpu之間
4、單CPU上中斷之間的並發
== 使用偏向: ==
==信號量用於進程之間的同步,進程在信號量保護的臨界區代碼裡面是可以睡眠的(需要進行進程調度),這是與自旋鎖最大的區別。==
信號量又稱為信號燈,它是用來協調不同進程間的數據對象的,而最主要的應用是共享內存方式的進程間通信。本質上,信號量是一個計數器,它用來記錄對某個資源(如共享內存)的存取狀況。它負責協調各個進程,以保證他們能夠正確、合理的使用公共資源。它和spin lock最大的不同之處就是:無法獲取信號量的進程可以睡眠,因此會導致系統調度。
1、==用於進程與進程之間的同步==
2、==允許多個進程進入臨界區代碼執行,臨界區代碼允許睡眠;==
3、信號量本質是==基於調度器的==,在UP和SMP下沒有區別;進程獲取不到信號量將陷入休眠,並讓出CPU;
4、不支持進程和中斷之間的同步
5、==進程調度也是會消耗系統資源的,如果一個int型共享變數就需要使用信號量,將極大的浪費系統資源==
6、信號量可以用於多個線程,用於資源的計數(有多種狀態)
==信號量加鎖以及解鎖過程:==
sema_init(&sp->dead_sem, 0); / 初始化 /
down(&sema);
臨界區代碼
up(&sema);
==信號量定義:==
==信號量初始化:==
==dowm函數實現:==
==up函數實現:==
信號量一般可以用來標記可用資源的個數。
舉2個生活中的例子:
==dowm函數實現原理解析:==
(1)down
判斷sem->count是否 > 0,大於0則說明系統資源夠用,分配一個給該進程,否則進入__down(sem);
(2)__down
調用__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);其中TASK_UNINTERRUPTIBLE=2代表進入睡眠,且不可以打斷;MAX_SCHEDULE_TIMEOUT休眠最長LONG_MAX時間;
(3)list_add_tail(&waiter.list, &sem->wait_list);
把當前進程加入到sem->wait_list中;
(3)先解鎖後加鎖;
進入__down_common前已經加鎖了,先把解鎖,調用schele_timeout(timeout),當waiter.up=1後跳出for循環;退出函數之前再加鎖;
Linux內核ARM構架中原子變數的底層實現研究
rk3288 原子操作和原子位操作
原子變數適用於只共享一個int型變數;
1、原子操作是指不被打斷的操作,即它是最小的執行單位。
2、最簡單的原子操作就是一條條的匯編指令(不包括一些偽指令,偽指令會被匯編器解釋成多條匯編指令)
==常見函數:==
==以atomic_inc為例介紹實現過程==
在Linux內核文件archarmincludeasmatomic.h中。 執行atomic_read、atomic_set這些操作都只需要一條匯編指令,所以它們本身就是不可打斷的。 需要特別研究的是atomic_inc、atomic_dec這類讀出、修改、寫回的函數。
所以atomic_add的原型是下面這個宏:
atomic_add等效於:
result(%0) tmp(%1) (v->counter)(%2) (&v->counter)(%3) i(%4)
注意:根據內聯匯編的語法,result、tmp、&v->counter對應的數據都放在了寄存器中操作。如果出現上下文切換,切換機制會做寄存器上下文保護。
(1)ldrex %0, [%3]
意思是將&v->counter指向的數據放入result中,並且(分別在Local monitor和Global monitor中)設置獨占標志。
(2)add %0, %0, %4
result = result + i
(3)strex %1, %0, [%3]
意思是將result保存到&v->counter指向的內存中, 此時 Exclusive monitors會發揮作用,將保存是否成功的標志放入tmp中。
(4) teq %1, #0
測試strex是否成功(tmp == 0 ??)
(5)bne 1b
如果發現strex失敗,從(1)再次執行。
Spinlock 是內核中提供的一種比較常見的鎖機制,==自旋鎖是「原地等待」的方式解決資源沖突的==,即,一個線程獲取了一個自旋鎖後,另外一個線程期望獲取該自旋鎖,獲取不到,只能夠原地「打轉」(忙等待)。由於自旋鎖的這個忙等待的特性,註定了它使用場景上的限制 —— 自旋鎖不應該被長時間的持有(消耗 CPU 資源),一般應用在==中斷上下文==。
1、spinlock是一種死等機制
2、信號量可以允許多個執行單元進入,spinlock不行,一次只能允許一個執行單元獲取鎖,並且進入臨界區,其他執行單元都是在門口不斷的死等
3、由於不休眠,因此spinlock可以應用在中斷上下文中;
4、由於spinlock死等的特性,因此臨界區執行代碼盡可能的短;
==spinlock加鎖以及解鎖過程:==
spin_lock(&devices_lock);
臨界區代碼
spin_unlock(&devices_lock);
==spinlock初始化==
==進程和進程之間同步==
==本地軟中斷之間同步==
==本地硬中斷之間同步==
==本地硬中斷之間同步並且保存本地中斷狀態==
==嘗試獲取鎖==
== arch_spinlock_t結構體定義如下: ==
== arch_spin_lock的實現如下: ==
lockval(%0) newval(%1) tmp(%2) &lock->slock(%3) 1 << TICKET_SHIFT(%4)
(1)ldrex %0, [%3]
把lock->slock的值賦值給lockval;並且(分別在Local monitor和Global monitor中)設置獨占標志。
(2)add %1, %0, %4
newval =lockval +(1<<16); 相當於next+1;
(3)strex %2, %1, [%3]
newval =lockval +(1<<16); 相當於next+1;
意思是將newval保存到 &lock->slock指向的內存中, 此時 Exclusive monitors會發揮作用,將保存是否成功的標志放入tmp中。
(4) teq %2, #0
測試strex是否成功
(5)bne 1b
如果發現strex失敗,從(1)再次執行。
通過上面的分析,可知關鍵在於strex的操作是否成功的判斷上。而這個就歸功於ARM的Exclusive monitors和ldrex/strex指令的機制。
(6)while (lockval.tickets.next != lockval.tickets.owner)
如何lockval.tickets的next和owner是否相等。相同則跳出while循環,否則在循環內等待判斷;
* (7)wfe()和smp_mb() 最終調用#define barrier() asm volatile ("": : :"memory") *
阻止編譯器重排,保證編譯程序時在優化屏障之前的指令不會在優化屏障之後執行。
== arch_spin_unlock的實現如下: ==
退出鎖時:tickets.owner++
== 出現死鎖的情況: ==
1、擁有自旋鎖的進程A在內核態阻塞了,內核調度B進程,碰巧B進程也要獲得自旋鎖,此時B只能自旋轉。 而此時搶占已經關閉,(單核)不會調度A進程了,B永遠自旋,產生死鎖。
2、進程A擁有自旋鎖,中斷到來,CPU執行中斷函數,中斷處理函數,中斷處理函數需要獲得自旋鎖,訪問共享資源,此時無法獲得鎖,只能自旋,產生死鎖。
== 如何避免死鎖: ==
1、如果中斷處理函數中也要獲得自旋鎖,那麼驅動程序需要在擁有自旋鎖時禁止中斷;
2、自旋鎖必須在可能的最短時間內擁有
3、避免某個獲得鎖的函數調用其他同樣試圖獲取這個鎖的函數,否則代碼就會死鎖;不論是信號量還是自旋鎖,都不允許鎖擁有者第二次獲得這個鎖,如果試圖這么做,系統將掛起;
4、鎖的順序規則(a) 按同樣的順序獲得鎖;b) 如果必須獲得一個局部鎖和一個屬於內核更中心位置的鎖,則應該首先獲取自己的局部鎖 ;c) 如果我們擁有信號量和自旋鎖的組合,則必須首先獲得信號量;在擁有自旋鎖時調用down(可導致休眠)是個嚴重的錯誤的;)
== rw(read/write)spinlock: ==
加鎖邏輯:
1、假設臨界區內沒有任何的thread,這個時候任何的讀線程和寫線程都可以鍵入
2、假設臨界區內有一個讀線程,這時候信賴的read線程可以任意進入,但是寫線程不能進入;
3、假設臨界區有一個寫線程,這時候任何的讀、寫線程都不可以進入;
4、假設臨界區內有一個或者多個讀線程,寫線程不可以進入臨界區,但是寫線程也無法阻止後續的讀線程繼續進去,要等到臨界區所有的讀線程都結束了,才可以進入,可見:==rw(read/write)spinlock更加有利於讀線程;==
== seqlock(順序鎖): ==
加鎖邏輯:
1、假設臨界區內沒有任何的thread,這個時候任何的讀線程和寫線程都可以鍵入
2、假設臨界區內沒有寫線程的情況下,read線程可以任意進入;
3、假設臨界區有一個寫線程,這時候任何的讀、寫線程都不可以進入;
4、假設臨界區內只有read線程的情況下,寫線程可以理解執行,不會等待,可見:==seqlock(順序鎖)更加有利於寫線程;==
讀寫速度 : CPU > 一級緩存 > 二級緩存 > 內存 ,因此某一個CPU0的lock修改了,其他的CPU的lock就會失效;那麼其他CPU就會依次去L1 L2和主存中讀取lock值,一旦其他CPU去讀取了主存,就存在系統性能降低的風險;
mutex用於互斥操作。
互斥體只能用於一個線程,資源只有兩種狀態(佔用或者空閑)
1、mutex的語義相對於信號量要簡單輕便一些,在鎖爭用激烈的測試場景下,mutex比信號量執行速度更快,可擴展
性更好,
2、另外mutex數據結構的定義比信號量小;、
3、同一時刻只有一個線程可以持有mutex
4、不允許遞歸地加鎖和解鎖
5、當進程持有mutex時,進程不可以退出。
• mutex必須使用官方API來初始化。
• mutex可以睡眠,所以不允許在中斷處理程序或者中斷下半部中使用,例如tasklet、定時器等
==常見操作:==
struct mutex mutex_1;
mutex_init(&mutex_1);
mutex_lock(&mutex_1)
臨界區代碼;
mutex_unlock(&mutex_1)
==常見函數:==
=
⑵ 什麼是linux kernel有什麼作用
Linux內核(英語:Linux kernel)是一種開源的類Unix操作系統宏內核。
工作於平板電腦、智能手機及智能手錶的Android操作系統同樣通過Linux內核提供的服務完成自身功能。
一個計算機系統是一個硬體和軟體的共生體,它們互相依賴,不可分割。計算機的硬體,含有外圍設備、處理器、內存、硬碟和其他的電子設備組成計算機的發動機。但是沒有軟體來操作和控制它,自身是不能工作的。
完成這個控制工作的軟體就稱為操作系統,在Linux的術語中被稱為「內核」,也可以稱為「核心」。Linux內核的主要模塊(或組件)分以下幾個部分:存儲管理、CPU和進程管理、文件系統、設備管理和驅動、網路通信,以及系統的初始化(引導)、系統調用等。
整個Linux操作系統家族基於該內核部署在傳統計算機平台(如個人計算機和伺服器,以Linux發行版的形式)和各種嵌入式平台,如路由器、無線接入點、專用小交換機、機頂盒、FTA接收器、智能電視、數字視頻錄像機、網路附加存儲(NAS)等。
工作於平板電腦、智能手機及智能手錶的Android操作系統同樣通過Linux內核提供的服務完成自身功能。盡管於桌面電腦的佔用率較低,基於Linux的操作系統統治了幾乎從移動設備到主機的其他全部領域。截至2017年11月,世界前500台最強的超級計算機全部使用Linux。
(2)linux內核基礎擴展閱讀:
編程語言
Linux是用C語言中的GCC版(這種C語言有對標准C進行擴展)寫的,還有幾個用匯編語言(用的是GCC的"AT&T風格")寫的目標架構短段。因為要支持擴展的C語言,GCC在很長的時間里是唯一一個能正確編譯Linux的編譯器。
有許多其他的語言用在一些方面上,主要集中在內核構建過程中(這里指從源代碼創建可引導鏡像)。包括Perl、Python和多種腳本語言。有一些驅動可能是用C++、Fortran或其他語言寫的,但是這樣是強烈不建議的。
編譯器兼容性
GCC是Linux內核源代碼的預設編譯器。在2004年,Intel主張通過修改內核,以便Intel C++編譯器能正確編譯內核。在2009年,有通過修改內核2.6.22版而成功編譯的報告(並帶來平均8-9%性能增長)。
自從2010年,已經開始進行使用Clang建造Linux內核的努力,Clang是一個可作為替代的C語言編譯器;截止2014年4月12日,官方內核幾乎可以完全用Clang編譯。致力於這個目標的計劃叫做「LLVMLinux」,得名於Clang所基於的LLVM編譯器下部構造。
LLVMLinux不意圖復制Linux內核或LLVM,因此它是由最終提交給上游計劃的補丁構成的一個元計劃。使Linux內核可以用Clang編譯最大的好處是比GCC有更快的編譯速度,內核開發者可以得益於由此而來的更快的工作流程
⑶ Linux 該怎麼入門呢
入門的話找本不用太厚,你能看懂的書來學習,再厚你看不懂,掌握不了方法也是白搭。
我看過同事以前培訓教材,某某青鳥的linux書,裡面是關於Centos6系統的一些介紹,
基本上都是簡單易學,學習一些方法還是可以的。
但是要注意Centos7以後的命令語法,有部分改變了不少,甚至完全不太一樣,
建議從7開始學吧。
另外就是對著書不停地練習,不管是學習使用命令,還是修改配置文檔,過程中會遇到各種各樣的問題,
遇到問題解決問題,不管是翻書還是網上網路,直到把問題解決了,掌握的知識點要做好筆記,不斷
地積累,學習一段時間,你就會感覺即使用遇到新問題都有辦法解決。
linux種類有不少,Centos是跟redhand有點類似的,其它的還有ubuntu,debian,
國產的還有UOS,deepin等等,基本命令都差不多,也有些是自身系統特定的格式,
不過都差不多。看你只是學習,還是以後工作也要使用的,找一個適合自己的來入門。
⑷ linux版本的發行版和內核版是什麼意思
Linux內核是Linux操作系統創始人主持的網站www.kernel.org上發布的操作系統的最基本的那些東西。
Linux發行版則是前述那些東慧宏孝西的基礎上添加了一些工具軟體的絕橘基礎上構成的一套龐大復雜的操作系統。雖然內核都是一樣的,但添加部分各不相同,這就構成了不同的發行版本。
Linux本身指的是一個操作系統內核,只有內核是無法直接使用的。我們需要的,可以使用的操作系統是一個包含了內核和一批有用的程序的的一個集合體,這個就是Linux發行版。
其中,Ubuntu。RedHat就是Linux的不同的發行版。
(4)linux內核基礎擴展閱讀:
Linux系統的主要特性
1、基本思想
Linux的基本思想有兩點:第一,一切都是文件;第二,每個軟體都有確定的用途。其中第一條詳細來講就是系統中的所有都歸結為一個文件,包括命令、硬體和軟體設備、操作系統、進程前稿等等對於操作系統內核而言,都被視為擁有各自特性或類型的文件。至於說Linux是基於Unix的,很大程度上也是因為這兩者的基本思想十分相近。
Linux是一款免費的操作系統,用戶可以通過網路或其他途徑免費獲得,並可以任意修改其源代碼。這是其他的操作系統所做不到的。正是由於這一點,來自全世界的無數程序員參與了Linux的修改、編寫工作,程序員可以根據自己的興趣和靈感對其進行改變,這讓Linux吸收了無數程序員的精華,不斷壯大。
3、完全兼容POSIX1.0標准
這使得可以在Linux下通過相應的模擬器運行常見的DOS、Windows的程序。這為用戶從Windows轉到Linux奠定了基礎。許多用戶在考慮使用Linux時,就想到以前在Windows下常見的程序是否能正常運行,這一點就消除了他們的疑慮。
4、多用戶、多任務
Linux支持多用戶,各個用戶對於自己的文件設備有自己特殊的權利,保證了各用戶之間互不影響。多任務則是現在電腦最主要的一個特點,Linux可以使多個程序同時並獨立地運行。
5、良好的界面
Linux同時具有字元界面和圖形界面。在字元界面用戶可以通過鍵盤輸入相應的指令來進行操作。它同時也提供了類似Windows圖形界面的X-Window系統,用戶可以使用滑鼠對其進行操作。在X-Window環境中就和在Windows中相似,可以說是一個Linux版的Windows。
6、支持多種平台
Linux可以運行在多種硬體平台上,如具有x86、680x0、SPARC、Alpha等處理器的平台。此外Linux還是一種嵌入式操作系統,可以運行在掌上電腦、機頂盒或游戲機上。2001年1月份發布的Linux 2.4版內核已經能夠完全支持Intel64位晶元架構。同時Linux也支持多處理器技術。多個處理器同時工作,使系統性能大大提高。
⑸ linux內核主要由哪幾個部分組成
一個完整的Linux內核一般由5部分組成,它們分別是內存管理、進程管理、進程間通信、虛擬文件系統和網路介面。
1、內存管理
內存管理主要完成的是如何合理有效地管理整個系統的物理內存,同時快速響應內核各個子系統對內存分配的請求。
Linux內存管理支持虛擬內存,而多餘出的這部分內存就是通過磁碟申請得到的,平時系統只把當前運行的程序塊保留在內存中,其他程序塊則保留在磁碟中。在內存緊缺時,內存管理負責在磁碟和內存間交換程序塊。
2、進程管理
進程管理主要控制系統進程對CPU的訪問。當需要某個進程運行時,由進程調度器根據基於優先順序的調度演算法啟動新的進程。:Linux支持多任務運行,那麼如何在一個單CPU上支持多任務呢?這個工作就是由進程調度管理來實現的。
在系統運行時,每個進程都會分得一定的時間片,然後進程調度器根據時間片的不同,選擇每個進程依次運行,例如當某個進程的時間片用完後,調度器會選擇一個新的進程繼續運行。
由於切換的時間和頻率都非常的快,由此用戶感覺是多個程序在同時運行,而實際上,CPU在同一時間內只有一個進程在運行,這一切都是進程調度管理的結果。
3、進程間通信
進程間通信主要用於控制不同進程之間在用戶空間的同步、數據共享和交換。由於不用的用戶進程擁有不同的進程空間,因此進程間的通信要藉助於內核的中轉來實現。
一般情況下,當一個進程等待硬體操作完成時,會被掛起。當硬體操作完成,進程被恢復執行,而協調這個過程的就是進程間的通信機制。
4、虛擬文件系統
Linux內核譽衫鉛中的虛擬文件系統用一個通用的文件模型表示了各種不同的文件系統,這個文件模型屏蔽了很多具體文件系統的差異,使Linux內核支持很多不同的文件系統。
這個文件系統可以分為邏輯文件系統和設備驅動程序:邏輯文件系統指Linux所支持的文件系統,例如ext2、ext3和fat等;設備驅動程序指為每一種硬體控制器所編寫的設備驅動程序模塊。
5、網路介面
網路介面提供了對各種網路標準的實現和各種網路硬體的支持。網路介面一般分為網路協議慶好和網路驅動程序。網路協議部分負責實現每一種可能的網路傳輸協議。
網路設備驅動程序則主要負責與硬體設備進行通信,每一種可能的網路硬體設備都有相應的設備驅動程序。
(5)linux內核基礎擴展閱讀:
Linux 操作系統的誕生、發展和成長過程始終依賴著五個重要支柱:UNIX操作系統、MINIX操作系統、GNU計劃、POSIX標准和Internet 網路。
1981 年IBM公司推出微型計算機IBM PC。
1991年,GNU計劃已經開發出了許多工具軟體,最受期盼的GNU C編譯器已經出現,GNU的操作系統核心HURD一直處於實驗階段,沒有任何可用性,實質上也沒能開發出完整的GNU操作系統,但是GNU奠定了Linux用戶基礎和開發環境。
1991年初,林納斯·托瓦茲開始在一台386sx兼容微機上學習minix操作系統。1991年4月,林納斯·托瓦茲開始醞釀並著手編制自己的操作系統。
1991 年4 月13 日在comp.os.minix 上發布說自己已經成功地將bash 移植到了minix 上,而且已經愛不釋手、不能離開這個shell軟體了。
1993年,大約有100餘名程序員參與了Linux內核代碼編寫/修改工作,其中核心組由5人組成,此時Linux 0.99的代碼大約有十萬行,用戶大約有10萬左右。
1994年3月,Linux1.0發布,代碼量17萬行,當時是按照完全自由免費的協議發布,隨後正式採用GPL協議。
1995年1月,Bob Young創辦了RedHat(小紅帽),以GNU/Linux為核心,集成了400多個源代碼開放的程序模塊,搞出了一種冠以品牌的Linux,即RedHat Linux,稱為Linux"發行版",在市場上出售。這在經營模式上是一種創舉。
2001年1月,Linux 2.4發布,它進一步地提升了SMP系統的擴展性,同時它也集成了很多用於支持桌面系統的特性:USB,PC卡(PCMCIA)的支持,內置的即插即用,等等功能。
2003年12月,Linux 2.6版內核發布,相對於2.4版內核2.6在對系統的支持都有很大的變化。
2004年的第1月,SuSE嫁到了Novell,SCO繼續頂著罵名四處強行「塌棚化緣」, Asianux, MandrakeSoft也在五年中首次宣布季度贏利。3月,SGI宣布成功實現了Linux操作系統支持256個Itanium 2處理器。