新聞中心
ARM架構(gòu)是現(xiàn)代計算機系統(tǒng)中使用最廣泛的處理器架構(gòu)之一,而Linux內(nèi)核則是當今最著名和流行的操作系統(tǒng)內(nèi)核之一。ARM Linux內(nèi)核是基于ARM處理器架構(gòu)的Linux內(nèi)核。在這篇文章中,我們將。

成都創(chuàng)新互聯(lián)主要從事網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)張家川回族自治,十年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220
ARM Linux內(nèi)核初始化流程包括以下幾個主要步驟:引導程序、內(nèi)存管理、設(shè)備驅(qū)動程序和根文件系統(tǒng)初始化。下面詳細介紹每個步驟。
引導程序
在系統(tǒng)上電或重啟時,處理器不能立即開始執(zhí)行操作系統(tǒng)內(nèi)核的代碼。相反,它必須先運行一個引導程序,該程序?qū)⒔庸芴幚砥鞑⒇撠熂虞d并運行操作系統(tǒng)內(nèi)核。在ARM Linux中,引導程序稱為引導加載程序(Boot Loader)。
引導加載程序有許多不同的實現(xiàn),例如U-Boot和RedBoot等。當引導加載程序被激活時,它將首先進行硬件初始化,并在合適的地址空間內(nèi)使用內(nèi)存,以便能夠?qū)⒉僮飨到y(tǒng)內(nèi)核加載到處理器中。其中的一個任務(wù)是將內(nèi)核映像從存儲設(shè)備復制到內(nèi)存中,并將處理器的控制權(quán)交給操作系統(tǒng)內(nèi)核。
內(nèi)存管理
一旦引導程序?qū)⒉僮飨到y(tǒng)內(nèi)核加載到處理器的內(nèi)存空間中,內(nèi)核就會接管處理器的控制權(quán)。此時,內(nèi)核將開始處理第二階段:內(nèi)存管理。在這個階段,內(nèi)核將掃描系統(tǒng)內(nèi)存,確認可以使用的內(nèi)存區(qū)域并進行內(nèi)存分配。
內(nèi)存管理也包括特殊區(qū)域的設(shè)置,例如中斷向量表和頁表等。此外,內(nèi)核必須在此階段完成虛擬內(nèi)存到物理內(nèi)存的映射,以便進程的虛擬地址可以正確映射到物理地址。這個過程通常是使用MMU(內(nèi)存管理單元)和虛擬內(nèi)存機制完成的。
設(shè)備驅(qū)動程序
設(shè)備驅(qū)動程序是操作系統(tǒng)內(nèi)核中的一個非常重要的功能模塊。在ARM Linux內(nèi)核初始化階段,設(shè)備驅(qū)動程序?qū)蕚浜糜布O(shè)備的可用性,包括CPU、內(nèi)存、存儲、網(wǎng)絡(luò)、各種傳感器和其他I/O設(shè)備。
ARM Linux內(nèi)核提供了一個稱為設(shè)備樹的機制。它可以描述硬件屬性和連接關(guān)系,并使內(nèi)核能夠自動加載正確的設(shè)備驅(qū)動程序。這種機制對于支持多種不同的硬件配置和平臺的ARM Linux系統(tǒng)非常有用。
根文件系統(tǒng)初始化
在設(shè)備驅(qū)動程序完成初始化之后,內(nèi)核在啟動進程之前會執(zhí)行另一個非常重要的任務(wù),即根文件系統(tǒng)初始化。根文件系統(tǒng)是操作系統(tǒng)內(nèi)核運行的根路徑,其中包含操作系統(tǒng)所需的所有文件、目錄和配置。
ARM Linux內(nèi)核可以將根文件系統(tǒng)作為掛載點,提供從閃存、其他文件系統(tǒng)或網(wǎng)絡(luò)卡等設(shè)備中加載文件的設(shè)備數(shù)據(jù)。根文件系統(tǒng)初始化過程確保所有必需的文件、目錄和配置都可用,并確保它們是正確掛載的。
綜上所述,ARM Linux內(nèi)核初始化的流程是引導程序、內(nèi)存管理、設(shè)備驅(qū)動程序和根文件系統(tǒng)初始化。操作系統(tǒng)內(nèi)核的初始化過程非常復雜,包括許多步驟和子過程。
對于ARM Linux系統(tǒng)的開發(fā)人員來說,了解ARM Linux內(nèi)核初始化流程的細節(jié)和原理至關(guān)重要。只有在完全理解操作系統(tǒng)內(nèi)核的初始化過程時,才能更好地管理和控制ARM Linux系統(tǒng)的行為和性能,從而確保其始終保持更佳工作狀態(tài)。
相關(guān)問題拓展閱讀:
- linux內(nèi)核同步問題
linux內(nèi)核同步問題
Linux內(nèi)核設(shè)計與實現(xiàn) 十、內(nèi)核同步方法
手把手教Linux驅(qū)動5-自旋鎖、信號量、互斥體概述
==
基礎(chǔ)概念:
==
并發(fā)
:多個執(zhí)行單元同時進行或多個執(zhí)行單元微觀串行執(zhí)行,宏謹拿觀并行執(zhí)行
競態(tài)
:并發(fā)的執(zhí)行單元對共享資源(硬件資源和軟件上的全局變量)的訪問而導致的竟態(tài)狀態(tài)。
臨界資源
:多個進程訪問的資源
臨界區(qū)
:多個進程訪問的代碼段
==
并發(fā)場合:
==
1、單CPU之間進程間的并發(fā)
:時間片輪轉(zhuǎn),調(diào)度進程。 A進程訪問打印機,時間片用完,OS調(diào)度B進程訪問打印機。
2、單cpu上進程和中斷之間并發(fā)
:CPU必須停止當前進程的執(zhí)行中斷;
3、多cpu之間
4、單CPU上中斷之間的并發(fā)
==
使用偏向:
==
==信號量用于進程之間的同步,進程在信號量保護的臨界區(qū)代碼里面是可以睡眠的(需要進行進程調(diào)度),這是與自旋鎖更大的區(qū)別。==
信號量又稱為信號燈,它是用來協(xié)調(diào)不同進程間的數(shù)據(jù)對象的,而最主要的應(yīng)用是共享內(nèi)存方式的進程間通信。本質(zhì)上,信號量是一個計數(shù)器,它用來記錄對某個資源(如共享內(nèi)存)的存取狀況。它負責協(xié)調(diào)各個進程,以保證他們能夠正確、合理的使用公共資源。它和spin lock更大的不同之處就是:無法獲取信號量的進程可以睡眠祥李搭,因此會導致系統(tǒng)調(diào)度。
1、==用于進程與進程之間的同步==
2、==允許多個進程進入臨界區(qū)代碼執(zhí)行,臨界區(qū)代碼允許睡眠;==
3、信號量本質(zhì)是==基于調(diào)度器的==,在UP和P下沒有區(qū)別;進程獲取不到信號量將陷入休眠,并讓出CPU;
4、不支持進程和中斷之間的同步
5、==進程調(diào)度也是會消耗系統(tǒng)資源的,如果一個int型共享變量就需要使用信號量,將極大的浪費系統(tǒng)資源==
6、信號量可以用于多個線程,用于資源的計數(shù)(有多種狀態(tài))
==信號量加鎖以及解鎖過程:==
sema_init(&sp->dead_sem, 0); /
初始化
/
down(&sema);
臨界區(qū)代碼
up(&sema);
==信號量定義:==
==信號量初始化:==
==dowm函數(shù)實現(xiàn)擾高:==
==up函數(shù)實現(xiàn):==
信號量一般可以用來標記可用資源的個數(shù)。
舉2個生活中的例子:
==dowm函數(shù)實現(xiàn)原理解析:==
(1)down
判斷sem->count是否 > 0,大于0則說明系統(tǒng)資源夠用,分配一個給該進程,否則進入__down(sem);
(2)__down
調(diào)用__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前已經(jīng)加鎖了,先把解鎖,調(diào)用schedule_timeout(timeout),當waiter.up=1后跳出for循環(huán);退出函數(shù)之前再加鎖;
Linux內(nèi)核ARM構(gòu)架中原子變量的底層實現(xiàn)研究
rk3288 原子操作和原子位操作
原子變量適用于只共享一個int型變量;
1、原子操作是指不被打斷的操作,即它是最小的執(zhí)行單位。
2、最簡單的原子操作就是一條條的匯編指令(不包括一些偽指令,偽指令會被匯編器解釋成多條匯編指令)
==常見函數(shù):==
==以atomic_inc為例介紹實現(xiàn)過程==
在Linux內(nèi)核文件archarmincludeaatomic.h中。 執(zhí)行atomic_read、atomic_set這些操作都只需要一條匯編指令,所以它們本身就是不可打斷的。 需要特別研究的是atomic_inc、atomic_dec這類讀出、修改、寫回的函數(shù)。
所以atomic_add的原型是下面這個宏:
atomic_add等效于:
result(%0) tmp(%1) (v->counter)(%2) (&v->counter)(%3) i(%4)
注意:根據(jù)內(nèi)聯(lián)匯編的語法,result、tmp、&v->counter對應(yīng)的數(shù)據(jù)都放在了寄存器中操作。如果出現(xiàn)上下文切換,切換機制會做寄存器上下文保護。
(1)ldrex %0,
意思是將&v->counter指向的數(shù)據(jù)放入result中,并且(分別在Local monitor和Global monitor中)設(shè)置獨占標志。
(2)add %0, %0, %4
result = result + i
(3)strex %1, %0,
意思是將result保存到&v->counter指向的內(nèi)存中,
此時 Exclusive monitors會發(fā)揮作用,將保存是否成功的標志放入tmp中。
(4) teq %1, #0
測試strex是否成功(tmp == 0 ??)
(5)bne 1b
如果發(fā)現(xiàn)strex失敗,從(1)再次執(zhí)行。
Spinlock 是內(nèi)核中提供的一種比較常見的鎖機制,==自旋鎖是“原地等待”的方式解決資源沖突的==,即,一個線程獲取了一個自旋鎖后,另外一個線程期望獲取該自旋鎖,獲取不到,只能夠原地“打轉(zhuǎn)”(忙等待)。由于自旋鎖的這個忙等待的特性,注定了它使用場景上的限制 —— 自旋鎖不應(yīng)該被長時間的持有(消耗 CPU 資源),一般應(yīng)用在==中斷上下文==。
1、spinlock是一種死等機制
2、信號量可以允許多個執(zhí)行單元進入,spinlock不行,一次只能允許一個執(zhí)行單元獲取鎖,并且進入臨界區(qū),其他執(zhí)行單元都是在門口不斷的死等
3、由于不休眠,因此spinlock可以應(yīng)用在中斷上下文中;
4、由于spinlock死等的特性,因此臨界區(qū)執(zhí)行代碼盡可能的短;
==spinlock加鎖以及解鎖過程:==
spin_lock(&devices_lock);
臨界區(qū)代碼
spin_unlock(&devices_lock);
==spinlock初始化==
==進程和進程之間同步==
==本地軟中斷之間同步==
==本地硬中斷之間同步==
==本地硬中斷之間同步并且保存本地中斷狀態(tài)==
==嘗試獲取鎖==
==
arch_spinlock_t結(jié)構(gòu)體定義如下:
==
==
arch_spin_lock的實現(xiàn)如下:
==
lockval(%0) newval(%1) tmp(%2) &lock->slock(%3) 1 slock的值賦值給lockval;并且(分別在Local monitor和Global monitor中)設(shè)置獨占標志。
(2)add %1, %0, %4
newval =lockval +(1slock指向的內(nèi)存中,
此時 Exclusive monitors會發(fā)揮作用,將保存是否成功的標志放入tmp中。
(4) teq %2, #0
測試strex是否成功
(5)bne 1b
如果發(fā)現(xiàn)strex失敗,從(1)再次執(zhí)行。
通過上面的分析,可知關(guān)鍵在于strex的操作是否成功的判斷上。而這個就歸功于ARM的Exclusive monitors和ldrex/strex指令的機制。
(6)while (lockval.tickets.next != lockval.tickets.owner)
如何lockval.tickets的next和owner是否相等。相同則跳出while循環(huán),否則在循環(huán)內(nèi)等待判斷;
*
(7)wfe()和p_mb() 最終調(diào)用#define barrier()
a
volatile
(“”: : :”memory”) *
阻止編譯器重排,保證編譯程序時在優(yōu)化屏障之前的指令不會在優(yōu)化屏障之后執(zhí)行。
==
arch_spin_unlock的實現(xiàn)如下:
==
退出鎖時:tickets.owner++
==
出現(xiàn)死鎖的情況:
==
1、擁有自旋鎖的進程A在內(nèi)核態(tài)阻塞了,內(nèi)核調(diào)度B進程,碰巧B進程也要獲得自旋鎖,此時B只能自旋轉(zhuǎn)。 而此時搶占已經(jīng)關(guān)閉,(單核)不會調(diào)度A進程了,B永遠自旋,產(chǎn)生死鎖。
2、進程A擁有自旋鎖,中斷到來,CPU執(zhí)行中斷函數(shù),中斷處理函數(shù),中斷處理函數(shù)需要獲得自旋鎖,訪問共享資源,此時無法獲得鎖,只能自旋,產(chǎn)生死鎖。
==
如何避免死鎖:
==
1、如果中斷處理函數(shù)中也要獲得自旋鎖,那么驅(qū)動程序需要在擁有自旋鎖時禁止中斷;
2、自旋鎖必須在可能的最短時間內(nèi)擁有
3、避免某個獲得鎖的函數(shù)調(diào)用其他同樣試圖獲取這個鎖的函數(shù),否則代碼就會死鎖;不論是信號量還是自旋鎖,都不允許鎖擁有者第二次獲得這個鎖,如果試圖這么做,系統(tǒng)將掛起;
4、鎖的順序規(guī)則(a) 按同樣的順序獲得鎖;b) 如果必須獲得一個局部鎖和一個屬于內(nèi)核更中心位置的鎖,則應(yīng)該首先獲取自己的局部鎖 ;c) 如果我們擁有信號量和自旋鎖的組合,則必須首先獲得信號量;在擁有自旋鎖時調(diào)用down(可導致休眠)是個嚴重的錯誤的;)
==
rw(read/write)spinlock:
==
加鎖邏輯:
1、假設(shè)臨界區(qū)內(nèi)沒有任何的thread,這個時候任何的讀線程和寫線程都可以鍵入
2、假設(shè)臨界區(qū)內(nèi)有一個讀線程,這時候信賴的read線程可以任意進入,但是寫線程不能進入;
3、假設(shè)臨界區(qū)有一個寫線程,這時候任何的讀、寫線程都不可以進入;
4、假設(shè)臨界區(qū)內(nèi)有一個或者多個讀線程,寫線程不可以進入臨界區(qū),但是寫線程也無法阻止后續(xù)的讀線程繼續(xù)進去,要等到臨界區(qū)所有的讀線程都結(jié)束了,才可以進入,可見:==rw(read/write)spinlock更加有利于讀線程;==
==
seqlock(順序鎖):
==
加鎖邏輯:
1、假設(shè)臨界區(qū)內(nèi)沒有任何的thread,這個時候任何的讀線程和寫線程都可以鍵入
2、假設(shè)臨界區(qū)內(nèi)沒有寫線程的情況下,read線程可以任意進入;
3、假設(shè)臨界區(qū)有一個寫線程,這時候任何的讀、寫線程都不可以進入;
4、假設(shè)臨界區(qū)內(nèi)只有read線程的情況下,寫線程可以理解執(zhí)行,不會等待,可見:==seqlock(順序鎖)更加有利于寫線程;==
讀寫速度
:
CPU > 一級緩存 > 二級緩存 > 內(nèi)存
,因此某一個CPU0的lock修改了,其他的CPU的lock就會失效;那么其他CPU就會依次去L1 L2和主存中讀取lock值,一旦其他CPU去讀取了主存,就存在系統(tǒng)性能降低的風險;
mutex用于互斥操作。
互斥體只能用于一個線程,資源只有兩種狀態(tài)(占用或者空閑)
1、mutex的語義相對于信號量要簡單輕便一些,在鎖爭用激烈的測試場景下,mutex比信號量執(zhí)行速度更快,可擴展
性更好,
2、另外mutex數(shù)據(jù)結(jié)構(gòu)的定義比信號量小;、
3、同一時刻只有一個線程可以持有mutex
4、不允許遞歸地加鎖和解鎖
5、當進程持有mutex時,進程不可以退出。
? mutex必須使用官方API來初始化。
? mutex可以睡眠,所以不允許在中斷處理程序或者中斷下半部中使用,例如tasklet、定時器等
==常見操作:==
struct mutex mutex_1;
mutex_init(&mutex_1);
mutex_lock(&mutex_1)
臨界區(qū)代碼;
mutex_unlock(&mutex_1)
==常見函數(shù):==
=
創(chuàng)新互聯(lián)服務(wù)器托管擁有成都T3+級標準機房資源,具備完善的安防設(shè)施、三線及BGP網(wǎng)絡(luò)接入帶寬達10T,機柜接入千兆交換機,能夠有效保證服務(wù)器托管業(yè)務(wù)安全、可靠、穩(wěn)定、高效運行;創(chuàng)新互聯(lián)專注于成都服務(wù)器托管租用十余年,得到成都等地區(qū)行業(yè)客戶的一致認可。
分享名稱:深入剖析ARMLinux內(nèi)核初始化流程(armlinux內(nèi)核初始化)
鏈接地址:http://www.dlmjj.cn/article/djeioes.html


咨詢
建站咨詢
