用戶態和內核態的區別
內核態:在內核態下,CPU可以執行所有的指令和訪問所有的硬件資源。
用戶態:在用戶態下,CPU只能執行部分指令集,無法直接訪問硬件資源。
內核態的底層操作主要包括:內存管理、進程管理、設備驅動程序控制、系統調用等。
分為內核態和用戶態的原因:
安全性:通過對權限的劃分,用戶程序無法直接訪問硬件資源,從而避免了惡意程序對系統資源的破壞。
穩定性:用戶態程序出現問題時,不會影響到整個系統,避免了程序故障導致系統崩潰的風險。
隔離性:內核態和用戶態的劃分使操作系統內核與用戶程序之間有了明確的邊界,有利于系統的模塊化和維護。
內核態和用戶態的劃分有助于保證操作系統的安全性、穩定性和易維護性。
線程和進程的區別是什么?
本質區別:進程是操作系統資源分配的基本單位,而線程是任務調度和執行的基本單位。
開銷方面:每個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有很大的開銷;線程可以看做輕量級的進程,同一類線程共享代碼和數據空間,每個線程都有自己獨立的運行棧和程序計數器(PC),線程之間切換開銷小。
穩定性:進程中某個線程如果崩潰了,可能會導致整個進程都崩潰。而進程中的子進程崩潰,并不會影響其他進程。
內存分配:系統在運行的時候會為每個進程分配不同的內存空間;而對線程而言,除了CPU外,系統不會為線程分配內存(線程所有使用的資源來自其所屬進程的資源),進程組之間只能共享資源。
包含關系:沒有線程的進程可以看作是單線程的,如果一個進程內有多個線程,則執行過程不是一條線的,而是多條線。
進程、線程、協程的區別是什么?
類型 | 定義 | 資源特點 | 通信方式 | 上下文切換開銷 | 優缺點 |
---|---|---|---|---|---|
進程 | 操作系統中進行資源分配和調度的基本單位 | 擁有獨立內存空間和系統資源,有獨立的堆和棧 | 通過管道、消息隊列、信號量等特定機制 | 較大,需保存和恢復整個進程狀態 | 穩定性和安全性相對較高,但上下文切換開銷大 |
線程 | 進程內的執行單元,CPU調度和分派的基本單位 | 共享進程的內存空間,包括堆和全局變量 | 可直接讀寫共享內存 | 較小,只需保存和恢復線程上下文 | 通信高效,上下文切換開銷小,但存在數據競爭和線程安全問題 |
協程 | 用戶態的輕量級線程 | 擁有自己的寄存器上下文和棧,與其他協程共享堆內存 | 可直接讀寫共享內存 | 非常小,只需保存和恢復協程上下文,無需內核級切換 | 處理大量并發任務效率高,但需程序員顯式調度管理,編程模型復雜 |
為什么進程崩潰不會對其他進程產生很大影響?
隔離性:每個進程都有自己獨立的內存空間,當一個進程崩潰時,其內存空間會被操作系統回收,不會影響其他進程的內存空間。
獨立性:每個進程都是獨立運行的,它們之間不會共享資源。
資源:虛擬內存、文件句柄、信號量等
進程之下為什么還要設計進程?
線程之間可以并發運行且可以共享相同的地址空間,可以解決多進程資源共享和創建開銷大等問題。
多線程比單線程的優勢,劣勢
優勢:提高程序的運行速率,可以充分利用多核處理器的資源,同時處理多個任務,加快程序的執行速度。
劣勢:存在多線程數據競爭訪問的問題,需要通過鎖機制來保證線程安全,增加了加鎖的開銷,并且還會有死鎖的風險。多線程會消耗更多資源,因為每個線程都需要占用一定內存和處理時間。
線程是不是越多越好,大多會有什么問題?
切換開銷:線程的創建和切換會消耗資源。如果創建太多線程,會占用大量的系統資源,導致系統資源負載過高,某個線程崩潰后,可能會導致進程崩潰。
死鎖問題:過多的線程相互競爭可能會導致死鎖問題。競爭是指多個線程同時訪問和修改共享資源,如果沒有合適的同步機制,可能會導致數據不一致或錯誤的結果。而死鎖則是多個線程相互等待對方釋放資源,導致程序無法繼續運行。
進程切換和線程切換的區別?
進程切換:包括整個進程的地址空間、全局變量、文件描述符等。
線程切換:線程切換只涉及到線程的堆棧、寄存器和程序計數器等,不涉及進程級別資源。
線程切換為什么比進程切換快,節省了什么資源?
??線程共享同一進程的地址空間和資源,線程切換時只需要切換堆棧和程序計數器等少量信息,而不需要切換地址空間,避免了進程切換時需要切換內存映射表等大量資源的開銷,從而節省了時間和系統資源。
線程切換詳細過程時怎么樣的?上下文保存在哪里?
步驟:
- 上下文保存:保存當前線程的上下文信息。包括寄存器狀態、程序計數器、堆棧指針等,用于保存線程的執行狀態。
- 切換到調度器:調度器負責選擇下一個要執行的線程,并根據調度算法做出決策。
- 上下文恢復:調度器選擇了下一個要執行的線程后,它會從該線程保存的上下文信息中恢復線程的執行狀態。
- 切換到新進程:調度器將執行權切換到新進程,使其開始執行。
上下文信息的保存通常由操作系統負責管理,具體保存在哪里取決于操作系統的實現方式。一般情況下,上下文信息會保存在線程的控制塊(Thread Control Block,TCB)中。
TCB是操作系統用于管理線程的數據結構,包含了線程的狀態、寄存器的值、堆棧信息等。當發生線程切換時,操作系統會通過切換TCB來保存和恢復線程的上下文信息。
進程的狀態,如何切換?
- NULL -> 創建狀態:一個新進程被創建時的第一個狀態;
- 創建狀態 -> 就緒狀態:當進程被創建完成并初始化后,一切就緒準備運行時,變為就緒狀態,這個過程是很快的;
- 就緒態 -> 運行狀態:處于就緒狀態的進程被操作系統的進程調度器選中后,就分配給CPU正式運行該進程;
- 運行狀態 -> 結束狀態:當進程已經運行完成或出錯時,會被操作系統作結束狀態處理;
- 運行狀態 -> 就緒狀態:處于運行狀態的進程在運行過程中,由于分配給它的運行時間片用完,操作系統會把該進程變為就緒態,接著從就緒態選中另外一個進程運行;
- 運行狀態 -> 阻塞狀態:當進程請求某個事件且必須等待時,例如請求I/O事件;
- 阻塞狀態 -> 就緒狀態:當進程要等待的事件完成時,它從阻塞狀態變到就緒狀態;
進程間通訊有哪些方式?
通信方式 | 特點 | 適用場景 |
---|---|---|
管道 | 分為匿名管道和命名管道,匿名管道無名字,存于內存,數據無格式、大小受限、單向通信,用于父子進程;命名管道需在文件系統創建設備文件,突破親緣關系限制 | 適合簡單、對通信速度要求不高,且數據量不大的同主機進程間通信 |
消息隊列 | 數據以自定義消息體形式存于內核消息鏈表,解決管道數據無格式問題,但讀寫需在用戶態與內核態拷貝數據 | 適合同主機進程間,對數據格式有要求,通信速度要求相對不極致的場景 |
共享內存 | 直接分配共享空間,進程可直接訪問,速度快,但多進程競爭易致數據錯亂 | 對通信速度要求極高,同主機進程間需頻繁大量數據交互的場景 |
信號量 | 本質是計數器,通過P、V原子操作實現進程互斥與同步,保護共享資源 | 多進程共享資源訪問控制場景 |
信號 | 異步通信機制,用于應用進程和內核交互,通知系統事件,部分信號進程無法捕捉忽略 | 用于通知進程系統事件,如進程結束、停止等控制場景 |
socket | 可用于不同主機或本地主機進程通信,基于TCP、UDP協議或本地進程通信方式 | 不同主機間或本地有網絡通信需求的進程間通信 |
管道有幾種方式?
匿名管道:是一種在父子進程或者兄弟進程之間進行通信的機制,只能用于具有親緣關系的進程間通信,通常通過pipe系統創建。
命名管道:是一種允許無關的進程間進行通信的機制,基于文件系統,可以在不相關的進程之間進行通信。
信號和信號量有什么區別?
信號:一種處理異步事件的方式。信號是比較復雜的通信方式,用于通知接收進程有某種事件發生,除了用于進程外,還可以發送信號給進程本身。
信號量:進程間通信處理同步互斥的機制。是在多線程環境下使用的一種設施,它負責協調各個線程,以保證它們能夠正確、合理地使用公共資源。
公共內存是怎么實現的?
公共內存的機制:不同進程拿出一塊虛擬地址空間來,映射到相同的物理內存中。減少了進程通信來回拷貝問題,提高了通信速率。
線程間通訊有什么方式?
名稱 | 原理及特性 |
---|---|
互斥鎖(Mutex) | 本質是鎖,訪問共享資源前加鎖,完成后釋放。加鎖后其他線程嘗試加鎖會阻塞,直至當前線程釋放。釋放時有多個阻塞線程,第一個變為運行態可加鎖,其余等待 |
條件變量(Condition Variables) | 多線程實現“等待 - 喚醒”邏輯常用方法,利用線程間共享全局變量同步,與互斥鎖結合。線程改變條件狀態前,先鎖互斥量,pthread_cond_wait 操作將自己放等待列表并解鎖互斥量(原子操作),返回時重鎖 |
自旋鎖(Spinlock) | 通過 CPU 的 CAS 函數(Compare And Swap),在用戶態完成加解鎖,不主動產生線程上下文切換。加鎖先查看鎖狀態,空閑則設置為當前線程持有;競爭時加鎖失敗線程“忙等待”。CAS 函數將兩步合為原子指令,“忙等待”可用 while 循環或 CPU 的 PAUSE 指令實現 |
信號量(Semaphores) | 可命名或無名,用于控制資源訪問次數,對應整型變量(sem)。有 P、V 兩個原子操作函數:P 操作將 sem 減 1,小于 0 則進程/線程阻塞;V 操作將 sem 加 1,小于等于 0 則喚醒等待進程/線程 |
讀寫鎖(Read-Write Locks) | 由讀鎖和寫鎖構成,讀資源用讀鎖加鎖,寫資源用寫鎖加鎖。寫鎖未被持有時,多個線程可并發持讀鎖;寫鎖被持有時,讀、寫線程獲取鎖均會阻塞。適用于讀多寫少場景 |
除了互斥鎖你還知道什么鎖?分別應用于什么場景?
讀寫鎖:允許多個線程同時讀取共享資源,但只允許一個線程進行寫操作。適用于讀操作頻繁、寫操作較少的場景,可以提高并發性能。
自旋鎖:是一種忙著等待鎖,線程在獲取鎖時不會進入阻塞狀態,而是循環忙等待直到獲取到鎖。適用于臨界區很小且鎖的持有時間很短的場景,避免線程頻繁切換帶來的開銷。
條件變量:條件變量用于線程間的同步和通信。它通常與互斥鎖一起使用,線程可以通過條件變量等待某個條件滿足,當條件滿足時,其他線程可以通過條件變量發送信號通知等待線程。
信號量:是一種計數器,用于控制對共享資源的訪問。它可以用于限制同時訪問資源的線程數量,或者用于線程間的同步。
進程調度算法有哪些?
先來先服務
每次從就緒隊列選擇最先進入隊列的進程,然后一致運行,直到進程退出或被阻塞,才會繼續從隊列中選擇第一個進程接著運行。(利于長作業,不利于短作業)。
最短作業優先
優先選擇運行時間最短的進程來運行,有利于提高系統的吞吐量。
不利于長作業:長作業可能不斷往后推。
高響應優先
每次進行進程調度時,先計算響應比優先級,然后把響應比優先級最高的進程投入運行。
該算法同時兼顧了短作業和長作業:等待時間相同時,要求的服務時間越短,響應比就越高,兼顧了短作業;要求的服務時間相同時,等待時間越長,響應比越高,兼顧了長作業。
時間片輪調度算法:
最古老、最簡單、最公平的且使用最廣的算法。
每個進程被分配一個時間段,成為時間片,即允許該進程在該時間段中運行。
- 如果時間片用完,進程還在運行,那么將會把此進程從CPU釋放出來,并把CPU分配另外一個進程。
- 如果該進程在時間片結束前阻塞或結束,則CPU立即進行切換。
- 如果時間片設的太短會導致過多的進程上下文切換,降低了CPU效率。
- 如果舍得太長又可能引起對短作業進程的響應時間變長。
最高優先級
從就緒隊列中選擇最高優先級的進程進行運行。(低優先級的進程可能永遠不會運行)
-
靜態優先級:創建進程時就已經確定了優先級。
-
動態優先級:根據進程的動態變化調整優先級。隨著時間的推移增加等待進程的優先級。
-
非搶占式:當就緒隊列中出現優先級高的進程,運行完當前進程,再選擇優先級高的進程。
-
搶占式:當就緒隊列中出現優先級高的進程,當前進程掛起,調度優先級高的進程運行。
多級反饋隊列調度算法
-
多級:表示有多個隊列,每個隊列優先級從高到低,同時優先級越高時間片越短。
-
反饋:表示如果有新的進程加入優先級高的隊列時,立刻停止當前正在運行的進程,轉而去運行優先級高的隊列。
工作原理: -
設置多個隊列,賦值每個隊列不同的優先級,每個隊列優先級從高到低,同時優先級越高時間片越短。
-
新的進程會被放入到第一級隊列的末尾,按先來先服務的原則排隊等待被調度,如果在第一級隊列規定的時間片沒運行完成,則將其轉入到第二級隊列的末尾,依次類推,直到完成。
-
當較高優先級的隊列為空,才調度較低優先級的隊列中的進程運行。如果進程運行時,有新進程進入較高優先級的隊列,則停止當前運行的進程并將其移入到原隊列末尾,接著讓優先級高的進程運行。
對于短作業可能可以在第一級隊列很快就被處理完。
對于長作業,如果在第一級隊列處理不完,可以移入下次隊列等待被執行,雖然等待時間變長了,但是運行時間也會更長了,所以該算法很好的兼顧了長短作業,同時有較好的響應時間。
為什么并發執行線程要加鎖?
- 為了保護共享數據,防止出現”競爭條件“。
- ”競爭條件:多個線程同時訪問和操作同一塊數據時,最終結果依賴于線程的執行順序,這可能導致數據的不一致性。
- 通過加鎖,可以保證在任何時刻只有一個線程能夠訪問共享數據,從而避免“競爭條件”,確保數據的一致性和完整性。
自旋鎖是什么?應用在哪些場景?
自旋鎖加鎖失敗后,線程會忙等待,直到它拿到鎖。
自旋鎖是通過CPU提供的CAS函數,在用戶態完成加鎖和解鎖,不會主動產生線程上下文交換。
步驟:
- 查看鎖的狀態,如果鎖是空閑的,執行下一步。
- 將鎖設置為當前線程持有。
CAS函數把這兩個步驟合并成了一條硬件級指令,形成原子指令。
在單核CPU上,需要搶占式的調度器(即不斷通過時鐘中斷一個線程,運行其他線程)。否則,自旋鎖在單個CPU上無法使用,因為一個自旋的線程永遠不會放棄CPU。
- 當加鎖失敗時,互斥鎖用線程切換來應對,自旋鎖則用忙等待來應對。
- 如果確定被鎖住的代碼執行時間很短,就不應該用互斥鎖,應該使用自旋鎖。
死鎖發生條件是什么?
- 互斥條件:多個線程不能同時使用同一個資源。
- 持有并等待條件:線程A已經持有了資源1,又想申請資源2,而資源2已經被線程B持有了,所以線程A就會處于等待狀態,但是線程A在等待資源2的同時并不會釋放自己已經持有的資源1。
- 不可剝奪條件:當線程已經持有了資源,在自己使用完之前不能被其他線程獲取。
- 環路等待條件:在死鎖發生的時候,兩個線程獲取資源的順序構成了環形鏈。
如何避免死鎖?
避免死鎖問題就只需要破環其中一個條件就可以,最常見的并且可行的就是使用資源有序分配法,來破壞環路等待條件。
線程總是以相同的順序申請自己想要的資源。
樂觀鎖和悲觀鎖有什么區別?
樂觀鎖:
- 基本思想:樂觀鎖假設多個事務之間很少發生沖突,因此在讀取數據時不會加鎖,而是在更新數據時檢查數據的版本(如使用版本號或時間戳),如果版本匹配則執行更新操作,否則認為發生了沖突。
- 使用場景:樂觀鎖適用于讀多寫少的場景,可以減少鎖的競爭,提高并發性能。例如,數據庫中的樂觀鎖機制可以用于并發更新同一行數據的情況。
悲觀鎖:
- 基本思想:悲觀鎖假設多個事務之間會頻繁發生沖突,因此在讀寫數據時會加鎖,防止其他事務對數據進行修改,直到當前事務完成操作后才釋放鎖。
- 適用場景:悲觀鎖適用于寫多的場景,通過加鎖保證數據的一致性。例如,數據庫中的行級鎖機制可以用于處理并發更新同一行數據的情況。
樂觀鎖適用于讀多寫少的場景,通過版本控制來處理沖突;而悲觀鎖適用于寫多的場景,通過加鎖來避免沖突。
講一下銀行家算法
銀行家算法的業務邏輯:
- 不負荷執行:一個進程的最大需求量不超過系統擁有的總資源數,才會接納執行。
- 可分期:一個進程可以分期請求資源,但總請求數不可超過最大需求量。
- 推遲分配:當系統現有資源數小于進程需求時,對進程的需求可以延遲分配,但總讓進程在有限時間內獲取資源。
舉例:
假設系統中有三類互斥資源R1、R2、R3,可用資源數分別為9,8,5,在指定時刻有P1,P2,P3,P4,P5這五個進程,這三個互斥資源的最大需求量和已分配資源數如下表:
進程 | 最大需求量(分別為R1 R2 R3) | 已分配資源數(分別為R1 R2 R3) |
---|---|---|
P1 | 6 5 2 | 1 2 1 |
P2 | 2 2 1 | 2 1 1 |
P3 | 8 1 1 | 2 1 0 |
P4 | 1 2 1 | 1 2 0 |
P5 | 3 4 4 | 1 1 3 |
第一步:分析
資源R1的剩余可用資源數 = 9 - 1 - 2 - 2 - 1 - 1 = 2。
資源R2的剩余可用資源數 = 8 - 2 - 1 - 1 - 2 - 1 = 1。
資源R3的剩余可用資源數 = 5 - 1 - 1 - 0 - 0 - 3 = 0。
系統剩余可用資源數分別時2,1,0
計算出各個進程需要的資源數如下表:
進程 | 最大需求量 | 已分配資源數 | 首次分配需要的資源數 |
---|---|---|---|
P1 | 6 5 2 | 1 2 1 | 5 3 1 |
P2 | 2 2 1 | 2 1 1 | 0 1 0 |
P3 | 8 1 1 | 2 1 0 | 6 0 1 |
P4 | 1 2 1 | 1 2 0 | 0 0 1 |
P5 | 3 4 4 | 1 1 3 | 2 3 1 |
根據銀行家算法不負荷原則(一個進程的最大需求量不超過系統擁有的總資源數,才會被接納執行),優先給進程P2執行。
第二步:執行P2
執行完成P2后,操作系統剩余可用資源數為4,2,1。
進程 | 最大需求量 | 已分配資源數 | 第二次分配需要的資源數 |
---|---|---|---|
P1 | 6 5 2 | 1 2 1 | 5 3 1 |
P2 | 完成 | 完成 | 完成 |
P3 | 8 1 1 | 2 1 0 | 6 0 1 |
P4 | 1 2 1 | 1 2 0 | 0 0 1 |
P5 | 3 4 4 | 1 1 3 | 2 3 1 |
第三步:執行P4
執行完成P4后,操作系統剩余可用資源數為5,4,1。
進程 | 最大需求量 | 已分配資源數 | 第三次分配需要的資源數 |
---|---|---|---|
P1 | 6 5 2 | 1 2 1 | 5 3 1 |
P2 | 完成 | 完成 | 完成 |
P3 | 8 1 1 | 2 1 0 | 6 0 1 |
P4 | 完成 | 完成 | 完成 |
P5 | 3 4 4 | 1 1 3 | 2 3 1 |
第四步:執行P5
執行完成P5后,操作系統剩余資源可用資源數為 6,5,4
進程 | 最大需求量 | 已分配資源數 | 第三次分配需要的資源數 |
---|---|---|---|
P1 | 6 5 2 | 1 2 1 | 5 3 1 |
P2 | 完成 | 完成 | 完成 |
P3 | 8 1 1 | 2 1 0 | 6 0 1 |
P4 | 完成 | 完成 | 完成 |
P5 | 完成 | 完成 | 完成 |
第五步:執行P1
執行完成P1后,操作系統剩余資源可用資源數為7,7,5
進程 | 最大需求量 | 已分配資源數 | 第三次分配需要的資源數 |
---|---|---|---|
P1 | 完成 | 完成 | 完成 |
P2 | 完成 | 完成 | 完成 |
P3 | 8 1 1 | 2 1 0 | 6 0 1 |
P4 | 完成 | 完成 | 完成 |
P5 | 完成 | 完成 | 完成 |
第六步:執行P3
執行完成P3后,操作系統剩余資源可用資源數為9,8,5
進程 | 最大需求量 | 已分配資源數 | 第三次分配需要的資源數 |
---|---|---|---|
P1 | 完成 | 完成 | 完成 |
P2 | 完成 | 完成 | 完成 |
P3 | 完成 | 完成 | 完成 |
P4 | 完成 | 完成 | 完成 |
P5 | 完成 | 完成 | 完成 |
總結:
銀行家算法的核心思想:在分配給進程資源前,首先判斷這個進程的安全性。如果系統當前資源能滿足其執行,則嘗試分配,如果不滿足則讓該進程等待。
通過不斷檢查剩余可用資源是否滿足某個進程的最大需求,如果可以則加入安全序列,并把該進程當前持有的資源回收;不斷重復這個進程,看最后能否實現讓所有進程都加入安全序列。
介紹一下操作系統內存管理
操作系統設計了虛擬內存,每個進程都有自己的獨立的虛擬內存。
虛擬內存帶來的好處:
- 第一,虛擬內存可以使進程對運行內存超過物理內存大小。對于沒有被經常訪問的內存,可以把它換到物理內存之外,比如硬盤上的swap區域。
- 第二,每個進程的虛擬內存空間是相互獨立的(每個進程都有自己的頁表)。解決了多進程之間地址沖突的問題。
- 第三,頁表里的頁表項中除了物理地址之外,還有一些標記屬性的bit,比如控制一個頁的讀寫權限,標記該頁是否存在等。在內存訪問方面,操作系統提供了更好的安全性。
分頁是把整個虛擬和物理內存空間切成一段段固定尺寸的大小。
- 頁表是存儲在內存里的,內存管理單元(MMU)將虛擬內存轉換成物理內存。
- 當進程訪問的虛擬地址在頁表中查不到時,系統會產生一個缺頁異常,進入系統內核空間分配物理內存、更新進程頁表,最后再返回用戶空間,恢復進程的運行。
什么是虛擬內存和物理內存?
- 虛擬內存:操作系統提供給每個運行中程序的一種地址空間,每個程序在運行時認為自己擁有的內存空間就是虛擬內存,其大小可以遠遠大于物理內存的大小。虛擬內存通過將程序的地址空間劃分成若干個固定大小的頁或段,并將這些頁或者段映射到物理內存中的不同位置,從而使得程序在運行時可以更高效地利用物理內存。
- 物理內存:物理內存是計算機實際存在地內存,是計算機中地實際硬件部件。
講一下頁表
分頁是把整個虛擬和物理內存空間切成一段段固定尺寸的大小。這樣一個連續并且尺寸固定的內存空間就叫做頁。
- 頁與頁之間是緊密排列的,所以不會有外部碎片。
- 內存分頁機制會有內部內存碎片。(內存分頁機制分配內存的最小單位是一頁,即使程序不足一頁大小,最少只能分配一個頁)
虛擬地址分為兩部分,頁號和頁內偏移。頁號作為頁表的索引,頁表包含物理頁每頁所在物理內存的基地址。這個基地址與頁內偏移的組合就形成了物理內存地址。
內存地址轉換步驟:
- 把虛擬內存地址,切分成頁號和偏移量
- 根據頁號,從頁表里面,查詢對應的物理頁號。
- 直接拿物理頁號,加上前面的偏移量,就得到了物理內存地址。
講一下段表?
虛擬地址可以通過段表與物理地址進行映射,分段機制會把程序的虛擬地址分為4個段,每個段在段表中有一個項,在這一項找到段的基地址,再加上偏移量,于是就能找到物理內存中的地址。
虛擬地址是怎么轉化到物理地址的?
當程序訪問一個虛擬地址時,MMU會將虛擬地址分解為頁號和頁內偏移量。然后,MMU會查找頁表,根據頁號找到對應的頁表項。頁表項中包含了物理頁的地址或頁框號。最后,MMU將物理頁的地址與頁內偏移量組合,得到對應的物理地址。
程序的內存布局是怎么樣的?
- 代碼段:二進制可執行代碼。
- 數據段:已初始化的靜態常量和全局常量。
- BSS段:未初始化的靜態變量和全局變量。
- 堆段:動態分配的內存,從低地址開始向上增長。
- 文件映射段:動態庫、共享內存。
- 棧段:局部變量和函數調用的上下文等。棧的大小是固定的,一般是8MB。
- 保留區:代碼段下面的內存空間,防止程序因為出現BUG,導致讀或寫了一些小內存地址的數據,而使得程序跑飛。
堆和棧的區別?
- 分配方式:堆是動態分配內存,有程序員手動申請和釋放內存,通常用于存儲動態數據結構和對象。棧是靜態分配內存,由編譯器自動分配和釋放內存,用于存儲函數的局部變量和函數調用信息。
- 內存管理:堆需要程序員手動管理內存的分配和釋放,如果管理不當可能會導致內存泄漏或內存溢出。棧由編譯器自動管理內存,遵循后進先出的原則,變量的生命周期由其作用域決定,函數調用時分配內存,函數返回時釋放內存。
- 大小和速度:堆通常比棧大,內存空間大,動態分配和釋放內存需要時間開銷。棧大小有限,通常比較小,內存分配和釋放速度較快,因為是編譯器自動管理。
fork會復制哪些東西?
- fork階段會復制父進程的頁表信息(虛擬內存)。
- fork之后,如果發生了寫時復制,就會復制物理內存。