操作系統(tǒng)隨筆-操作系統(tǒng)真象還原

復習操作系統(tǒng)真象還原,記錄一些知識點

實模式內存布局


image.png

如下圖所示: 編譯器給程序中各符號(變量名或函數(shù)名等)分配的地址,就是各符號相對于文件開頭的偏移量。


image.png

如下圖所示:關鍵字 section 并沒有對程序中的地址產生任何影響,即在默認情況下,有沒有 section 都一個樣, section 中數(shù)據(jù)的地址依然是相對于整個文件的順延,僅僅是在邏輯上讓開發(fā)人員梳理程序之用 。


image.png

如下圖所示:
vstart xxx 和 orgxxxx 這兩個關鍵字是同一功能,但很多同學都混淆其意義。它們并不是告訴編譯器程序加載到地址 xxxx處。vstart 和 org ,它們的功能是告訴編譯器:“嘿,老兄,你幫我把后面所有數(shù)據(jù)〈指令和變量 )的地址以 xxxx 為起始開始編吧”
用 vstart 的時機是:我預先知道我的程序將來被加載到某地址處。程序只有加載到非 0 地址時 vstart 才是有用的,程序默認起始地址是 0 。
mbr 用 vstart=Ox7c00 來修飾的原因,是因為開發(fā)人員知道 mbr 要被加載器( BIOS )加載到物理地址Ox7c00, mbr 中后續(xù)的物理地址都是 Ox7c00+。
只有開發(fā)人員知道以xxxx 為起始的原因是將來有某個加載器要把我的這個程序放到內存的 xxxx 地址,如果我程序中引用的所
有地址不是以口xx 為起始的,那就壞了,訪問錯的數(shù)據(jù)肯定出事。


image.png

關于匯編中vstart的作用:
https://blog.csdn.net/qq_39286701/article/details/118486106

實模式下的段寄存器:


image.png

實模式下的通用寄存器:


image.png

image.png

eflags寄存器:


image.png

CPU與IO通信:


image.png

從實模式進入保護模式:


image.png

image.png

段描述符表:


image.png

段界限計算方式:


image.png

全局描述符表:GDT
全局描述符表 GDT 相當于是描述符的數(shù)組,數(shù)組中的每個元素都是8 宇節(jié)的描述符。
GOT 中的第 0 個段描述符是不可用的,原因是定義在 GOT 中的段描述符是要用選擇子來訪問的,如果使用的選擇子忘記初始化,選擇子的值便會是 0,這便會訪問到第 0 個段描述符。
lgdt 的指令格式是: lgdt 48 位內存數(shù)據(jù)。
在保護模式下重新?lián)Q個 GDT 的原因是實模式下只能訪問低端 IMB 空間,所以 GDT 只能位于 IMB 之內。根據(jù)操作系統(tǒng)的實際情況,有可能需要把 GDT 放在其他的內存位置,所以在進入保護模式后,訪問的內存空間突破了 IMB,可以將 GDT 放在合適的位置后再重新加載進來。
如下圖, GDT共48位,這 48 位內存數(shù)據(jù)劃分為兩部分,其中前 16 位是 GDT 以宇節(jié)為單位的界限值,所以這 16 位相當于GDT 的字節(jié)大小減 1 。后 32 位是 GDT 的起始地址。由于 GDT 的大小是 16 位二進制,其表示的范圍是 2的 16 次方等于 65536 字節(jié)。每個描述符大小是 8 字節(jié),故, GDT 中最多可容納的描述符數(shù)量是 65536/8=8192個,即 GDT 中可容納 8192 個段或門。


image.png

選擇子:
段寄存器是 16 位,所以選擇子也是 16 位,在其低 2 位即第 O~ 1 位,用來存儲 RPL,即請求特權級,可以表示 0、 1 、 2、 3 四種特權級。
段寄存器是 16 位,所以選擇子也是 16 位,在其低 2 位即第 O~ 1 位,用來存儲 RPL,即請求特權級,可以表示 0、 1 、 2、 3 四種特權級。
段寄存器是 16 位,所以選擇子也是 16 位,在其低 2 位即第 O~ 1 位,用來存儲 RPL,即請求特權級,可以表示 0、 1 、 2、 3 四種特權級。


image.png

進入保護模式的步驟:
1 打開A20
2 加載gdt
3 將cr0的pe位置1

;----------------- 打開A20 ----------------
in al, 0x92
or al, 0000_0010B
out 0x92, al
;------------------ 加載GDT ----------------
lgdt [gdt_ptr]
;----------------- cr0第0位置1 ----------------
mov eax, cr0
or eax, 0x00000001
mov cr0, eax

進入保護模式后, jmp SELECTOR_CODE:p_mode_start ,使用遠跳指令清空流水線, 同時更新段描述符緩沖寄存器。

在 Linux 2.6 內核中,是用 detect_memory 函數(shù)來獲取內存容量的。其函數(shù)在本質上是通過調用 BIOS 中斷 Ox15 實現(xiàn)的,分別
是 BIOS 中斷 Ox15 的 3 個子功能,子功能號要存放到寄存器 EAX 或 AX 中,如下。
? EAX=OxE820:遍歷主機上全部內存。
? AX=OxE801: 分別檢測低 1見面和 16孔但~4GB 的內存,最大支持 4GB 。
? AH=Ox88:最多檢測出 64MB 內存,實際內存超過此容量也按照 64MB 返回。

分頁機制的思想是:

通過映射,可以使連續(xù)的線性地址與任意物理內存地址相關聯(lián),邏輯上連續(xù)的線性地址其對應的物理地址可以不連續(xù) 。
分頁機制的作用有兩方面 。
? 將線性地址轉換成物理地址。
? 用大小相等的頁代替大小不等的段。

image.png

一級頁表缺點:
(1 )一級頁表中最多可容納 IM ( 1048576 )個頁表項,每個頁表項是 4 字節(jié),如果頁表項全滿的話,
便是 4畫面大小。
(2 )一級頁表中所有頁表項必須要提前建好,原因是操作系統(tǒng)要占用 4GB 虛擬地址空間的高 IGB,
用戶進程要占用低 3GB 。
(3 )每個進程都有自己的頁表,進程一多,光是頁表占用的空間就很可觀了。

二級頁表:
每個頁表中可容納 1024 個物理頁,故每個頁表可表示的內存容量是 1024叫阻=4陋。頁目錄中共有1024 個頁表,故所有頁表可表示的內存容量是 1024*仙但=4GB ,這己經達到了 32 位地址空間的最大容量。
二級頁表的轉換:
(1 )用虛擬地址的高 10 位乘以 4 ,作為頁目錄表內的偏移地址,加上頁目錄表的物理地址,所得的和,便是頁目錄項的物理地址。讀取該頁目錄項,從中獲取到頁表的物理地址。
(2 )用虛擬地址的中間 1 0 位乘以 4 ,作為頁表內的偏移地址,加上在第 1 步中得到的頁表物理地址,所得的和,便是頁表項的物理地址。讀取該頁表項,從中獲取到分配的物理頁地址。 -
(3 )虛擬地址的高 10 位和中間 10 位分別是 PDE 和 PIE 的索引值,所以它們需要乘以 4 。但低 12 位就不是索引值啦,其表示的范圍是 0~Ox筒,作為頁內偏移最合適,所以虛擬地址的低 12 位加上第 2 步
中得到的物理頁地址,所得的和便是最終轉換的物理地址。


image.png
image.png
啟用分頁機制,我們要按順序做好三件事 。

(1 )準備好頁目錄表及頁表。
(2 )將頁表地址寫入控制寄存器 cr3 。
(3 )寄存器 c呻的 PG 位置 1 。
控制寄存器 cr3 用于存儲頁表物理地址,所以 cr3 寄存器又稱為頁目錄基址寄存器( Page DirectorγBase 31 12 11 5 4 3 2 1 O
Register, PDBR ) 。

操作系統(tǒng)真象還原中的分頁布局如下:


image.png

用虛擬地址獲取頁表中各數(shù)據(jù)類型的方法
獲取頁目錄表物理地址:讓虛擬地址的高 20 位為 0xfffff,低 12 位為 0x000 ,即 0xfffff000,這也是頁目錄表中第 0 個頁目錄項自身的物理地址。
訪問頁目錄中的頁目錄項,即獲取頁表物理地址:要使虛擬地址為 0xfffffxxx,其中 xxx 是頁目錄項的索引乘以 4 的積 。

TLB ,即Translation Lookaside Buffer,俗稱快表。TLB 中的條目是虛擬地址的高 20 位到物理地址高 20 位的映射結果,實際上就是從虛擬頁框到物理頁框的映射。除此之外 TLB中還有一些屬性位,比如頁表項的 RW 屬性。
  TLB 對開發(fā)人員不可見,但依然有兩種方法可以間接更新 TLB ,一個是針對 TLB 中所有條目的方法一一重新加載 CR3 ,比如將 CR3 寄存器的數(shù)據(jù)讀出來后再寫入 CR3 ,這會使整個 TLB 失效。另一個方法是針對 TLB 中某個條目的更新。處理器提供了指令 invlpg (invalidate page ),它用于在 TLB 中刷新, 某個虛擬地址對應的條目,
image.png

操作系統(tǒng)真象還原的硬盤分配:
MBR 寫在了硬盤的第 0 扇區(qū),第 1 扇區(qū)是空著的,原因是個人喜好,其實不空著也行,不過硬盤那么大,何必搞得那么擁擠呢。 因此 loader 寫在硬盤的第 2 扇區(qū),由于 loader.bin 目前的大小是 1342 字節(jié),占用 3 個扇區(qū),所以第 2~4 扇區(qū)不能再用啦,從第 5 扇區(qū)起我們可以自由使用。但此時我的強迫癥又發(fā)作啦,我這里并沒有接著第 5 扇區(qū)寫,而是選的第 9 扇區(qū)(要是起始為 1 的話算是第 10 個扇區(qū)〉, 內核是從第9個扇區(qū)開始寫的
dd if=$(BUILD_DIR)/kernel.bin
of=/usr/bochs/hd60M.img
bs=512 count=200 seek=9 conv=notrunc
至于為什么把 count 設成這么大,原因是這樣的:每次寫完內核后,咱們要往磁盤中同步內核文件,這樣才能驗證內核的正確性。按理說,咱們現(xiàn)在的內核文件不足 4 扇區(qū),count=4 最合適。不過,內核發(fā)展越來越大時,每次都要根據(jù)實際內核文件大小去改寫 count 參數(shù),這樣就難免會有忘記修改的情況。之前我就深受其苦, 內核文件變大了,而 count 忘記調整,造成寫入硬盤中的內核文件不完整,所以到后來,程序運行不受控制,以至于調試的時候都調暈啦,看著 CPU 中跑的指令我完全蒙圈了,根本不是自己寫的?;腥淮笪蛑螅揖透纱嘁徊降轿?,因為我們將來的內核大小不會超過 100kb,所以直接把 count 改為 200 塊扇區(qū)。另外請大家不用擔心, dd命令會自己判斷寫入的數(shù)據(jù)量,如果參數(shù) if指定的文件體積小于 count*bs,只按實際文件大小寫入。

image.png
image.png

操作系統(tǒng)真象還原的程序布局:


image.png

調用約定:


image.png
image.png

匯編風格:


image.png

第八章加入內存管理后,程序內存變化:
0xc009e000 是主線程的 PCB,占據(jù)一頁
內核預計在 70KB 左右,裝載到 0x9ff00 以下是綽綽有余的,所以,主線程的棧頂?shù)刂?0x9ff00是我們在低端 lMB 中所用到的最高地址 。
32MB 物理內存需要 1024 字節(jié)的位圖,也就是僅占四分之一頁,打算支持 4 頁內存的位圖,即最大可管理 512MB 的物理內存故再減去 4 頁,即 0xc009e000 - 0x4000 = 0xc009a000。故我們的位圖地址為 0xc009a000 。
頁目錄大小為 1 頁框,第 0 和第 768 個頁目錄項指向同一個頁表,它們共享這 1 頁框空間,第 769~ 1022 個頁目錄項共指向 254 個頁表,故頁表總大小等于 256個PG_SIZE,共計 0x200000 字節(jié),2M。注意,最后一個頁目錄項(第 1023 個 pde )指向頁目錄表,因此不重復計算空間。因此,1M內存外的2M空間是頁目錄表以及內核的頁表。

分頁中將32位虛擬地址映射成物理地址的三個步驟:

  1. 首先處理高 IO 位的 pde 索引,從而處理器得到頁表物理地址。
  2. 其次處理中間 IO 位的 pte 索引,進而處理器得到普通物理頁的物理地址 。
  3. 最后是把低 12 位作為普通物理頁的頁內偏移地址,此偏移地址加上物理頁的物理地址,得到的地址之和便是最終的物理地址,處理器到此物理地址上進行讀寫操作。

第八章內存管理memory.c中幾個重要的函數(shù):
其中以下兩個函數(shù)最難理解:
uint32_t* pte_ptr(uint32_t vaddr) /* 得到虛擬地址vaddr對應的pte指針/
uint32_t
pde_ptr(uint32_t vaddr) /* 得到虛擬地址vaddr對應的pde的指針 */

image.png

第九章 線程
總結一下: 上調度器的都是線程,能動的都是線程(哈哈哈哈)。

線程是一套機制,此機制可以為一般的代碼塊創(chuàng)造它所依賴的上下文環(huán)境,從而讓代碼塊具有獨立性,因此在原理上線程能使一段函數(shù)成為調度單元(或稱為執(zhí)行流),使函數(shù)能被調度器“認可”,從而能夠被專門調度到處理器上執(zhí)行。

進程擁有整個地址空間,其中包括各種資源,而進程中的所有線程共享同一個地址空間,原因很簡單,因為這個地址空間中有線程運行所需要的資源。
由于各個進程都擁有自己的虛擬地址空間,正常情況下它們彼此無法訪問到對方的內部,因為進程之間的安全性是由操作系統(tǒng)的分頁機制來保證的,只要操作系統(tǒng)不要把相同的物理頁分配給多個進程就行了。

強調下,只有線程才具備能動性,它才是處理器的執(zhí)行單元,因此它是調度器眼中的調度單位。進程只是個資源整合體,它將進程中所有線程運行時用到資源收集在一起,供進程中的所有線程使用,真正上處理器上運行的其實都叫線程,進程中的線程才是一個個的執(zhí)行實體、執(zhí)行流,因此,經調度器送上處理器執(zhí)行的程序都是錢程。


進程的六個提問:
1) 加載一個任務到處理器上運行,    任務由哪兒來???
2) 找到了任務, 資源從哪兒獲得???
3) 任務變成了進程運行了,該運行多久呢???
4) 當前任務換下處理器后,當前進程使用的資源存放在哪兒呢???
5) 進程被換下的原因是什么?還能再把它換上處理器運行嗎???
6) 進程獨享地址空間,它的地址空間在哪兒???

一個簡單的PCB結構:
image.png

PCB 中包含“進程狀態(tài)飛,它解決了上面第 5 個問題,
“時間片”解決上面第 3 個問題,
“頁表”解決了上面第 6 個問題,它代表進程的地址空間
“寄存器映像”是用來解決上面第 4 個問題的
其實第 4 個問題解決了,第 2 個問題也就一同搞定了,再從 PCB 中把寄存器映像加載到寄存器中就行了。
目前只剩下第 1 個問題沒有解決了,其實,要解決此問題,就是要單獨維護一個進程表,將所有的 PCB結構加載到此表中,由調度器直接在進程表中找相應進程的 PCB ,從而獲取到對應進程的信息,將其寄存器映像加載到處理器后,新進程就開始運行了。

進程使用的戰(zhàn)也屬于 PCB 的一部分,不過此棋是進程所使用的 0 特權級下內核戰(zhàn)(并不是 3 特權級下的用戶棧) 。我們在 PCB 中還要維護一個“核指針 ” 成員,它記錄0級棧棧頂?shù)奈恢?,借此找到進程或線程的“寄存器映像”。

實現(xiàn)線程的兩種方式——用戶/內核


image.png

講個題外話,真理在代碼中,多debug?。。。? 抓重點?。?! 梳理代碼邏輯!?。?!

核心是要理解ret指令:


image.png

匯編語言CALL和RET指令:調用一個過程
http://c.biancheng.net/view/3537.html

程序=算法+數(shù)據(jù)結構。 我感覺先定義數(shù)據(jù)結構,程序圍繞著數(shù)據(jù)結構來寫。

存儲數(shù)據(jù)只是鏈表的部分功能,它最主要的功能是“鏈”。
下面兩個宏,很重要?。。?/p>

image.png

其實我們從開機到創(chuàng)建第一個線程前,程序都有個執(zhí)行流,這個執(zhí)行流帶我們從 BIOS 到 mbr 到 loader 到 kernel ,其實它就是我們所說的主線程 。 為此我們還在 loader 中把 esp 置為 Oxc009f000,這是有意為之的設計,意圖是把 Oxc009e000 作為主線程的 PCB.

image.png
image.png

完整的程序=用戶代碼+內核代碼

image.png

結合thread.h中PCB的結構體對照著看,內核級線程的切換真有意思:


image.png
image.png

第十章 輸入輸出系統(tǒng)

公共資源:可以是公共內存、公共文件、公共硬件等,總之是被所有任務共享的一套資源。
臨界區(qū): 各任務中訪問公共資源的指令代碼組成的區(qū)域就稱為臨界區(qū)。 #即臨界區(qū)是指令
競爭條件: 多個任務以非互斥的方式同時進入臨界區(qū)

多線程訪問公共資源時出問題的原因是產生了競爭條件,也就是多個任務同時出現(xiàn)在自己的臨界區(qū) 。

信號量是種同步機制

image.png

第十一章 用戶進程

文檔是應用程序的應用,應用程序是編譯器的應用,編譯器又是操作系統(tǒng)的應用 。 那操作系統(tǒng)是誰的應用?當然是硬件的應用啦。

TSS 是 Task State Segment 的縮寫,即任務狀態(tài)段

正是由于好奇心特別大,所以才會想了解操作系統(tǒng)的原理?!? 這句話,我是贊同的。

為什么 GDT 中第 0 個段描述符不可用? 是擔心選擇子未初始化

image.png

TSS 中的字段基本上全是寄存器名稱,這些寄存器就是任務運行中的最新狀態(tài)。


image.png

我們使用 TSS 唯一的理由是為 0 特權級的任務提供棧。

用戶進程進入內核態(tài)后,除了擁有單獨的地址空間外,其他方面和內核線程是一樣的。

image.png
image.png

有個疑問:
下面這句代碼,我能理解它是對的,但我感覺最開始初始化用戶進程的時候,self_kstack一開始肯定是在固定的位置的。。。。


image.png

第十二章 進一步完善內核
“系統(tǒng)調用”準確地來說應該被稱為“操作系統(tǒng)功能調用”
Linux 系統(tǒng)調用是用中斷門來實現(xiàn)的,通過軟中斷指令 int 來主動發(fā)起中斷信號。
Linux 只占用一個中斷向量號,即 Ox80
Linux 在寄存器 eax中寫入子功能號

完善堆內存管理:
arena 是個內存?zhèn)}庫,并不直接對外提供內存分配,只有內存塊描述符才對外提供內存塊,內存塊描述符將同類 arena 中的空閑內存塊匯聚到一起,作為某一規(guī)格內存塊的分配入口。

image.png

核心是下面三個函數(shù):
sys_malloc 申請內存的函數(shù) 多看看,有意思,厲害
mfree_page 釋放內存的函數(shù)
sys_free 釋放內存的函數(shù)
整個memory.c文件,多看看,挺有意思的。比,寫if, else有意思多了?。。。。。。。。。。?/p>

第十三章 編寫硬盤驅動程序
文件系統(tǒng)是運行在操作系統(tǒng)中的軟件模塊,是操作系統(tǒng)提供的一套管理磁盤文件讀寫的方法和數(shù)據(jù)組織、存儲形式,因此,文件系統(tǒng)=數(shù)據(jù)結構+算法,哈哈,所以它是程序。

磁盤容量:


image.png

分區(qū),邏輯分區(qū);
老實說,沒太看懂里面的概念,不過看看這張圖,大致了解了。。。。


image.png

硬件是實實在在的東西,要想在軟件中管理它們,只能從邏輯上抓住這些硬件的特性,將它們抽象成一些數(shù)
據(jù)結構,然后這些數(shù)據(jù)結構便代表了硬件,用這些數(shù)據(jù)結構來組織硬件的信息及狀態(tài),在邏輯上硬件就是這數(shù)據(jù)
結構。

硬盤驅動程序 獲取硬盤信息 掃描分區(qū)表 =>有一種軟件與硬件的交互的美感, 有種抽象控制硬件的感覺?。。⌒枰嗫纯?沒太看懂?。。。?/p>

最重要的是:
intr_hd_handler 硬盤中斷處理程序
ide_read 從硬盤讀取sec_cnt個扇區(qū)到buf
partition_scan 掃描硬盤hd中地址為ext_lba的扇區(qū)中的所有分區(qū)
硬盤工作完成后,會調用intr_hd_handler 中斷函數(shù),才會繼續(xù)向下走。。。。

/* ata通道結構 */
struct ide_channel {
char name[8]; // 本ata通道名稱, 如ata0,也被叫做ide0. 可以參考bochs配置文件中關于硬盤的配置。
uint16_t port_base; // 本通道的起始端口號
uint8_t irq_no; // 本通道所用的中斷號
struct lock lock;
bool expecting_intr; // 向硬盤發(fā)完命令后等待來自硬盤的中斷
struct semaphore disk_done; // 硬盤處理完成.線程用這個信號量來阻塞自己,由硬盤完成后產生的中斷將線程喚醒
struct disk devices[2]; // 一個通道上連接兩個硬盤,一主一從
};

這個結構中為什么要一個lock, 加上一個 信號量disk_done, 這個沒搞懂?????

lock的作用: 操作硬盤之前先將硬盤所在的通道上鎖,從而保證一次只操作同一通道上的一塊硬盤。
信號量的作用是: 在硬盤工作過程中讓出CPU,通過信號量阻塞自己

第十四章 文件系統(tǒng)
inode 是文件索引結構組織形式的具體體現(xiàn),必須為每個文件者睜獨配備一個劃羊的元信息數(shù)據(jù)結構,因此在UINX 文件系統(tǒng)中,一個文件必須對應一個 inode,磁盤中有多少文件就有多少 inode。

image.png
image.png

在 Linux 中,目錄和文件都用 inode 來表示,因此目錄也是文件,只是目錄是包含文件的文件 。
文件名應該存儲在和目錄相關的地方
在磁盤上的文件系統(tǒng)中 (注意啦,我說的是磁盤上),沒有一種專門稱為目錄的數(shù)據(jù)結構,磁盤上有的只是 inode,

image.png

有了目錄項后,通過文件名找文件實體數(shù)據(jù)塊的流程是 。
( l )在目錄中找到文件名所在的目錄項 。
(2 )從目錄項中獲取 inode 編號 。
(3 )用 inode 編號作為 inode 數(shù)組的索引下標,找到 inode
(4 )從該 inode 中獲取數(shù)據(jù)塊的地址,讀取數(shù)據(jù)塊 。

創(chuàng)建文件的本質是創(chuàng)建了文件的文件控制塊,即目錄項和 inode

image.png

我們需要在某個固定地方去獲取文件系統(tǒng)元信息的配置,這個地方就是超級塊,超級塊是保存文件系統(tǒng)元信息的元信息。

image.png
image.png

由于 inode 是從硬盤上保存的 , 文件被打開時, 肯定是先要從硬盤上載入其 inode,但硬盤比較慢, 為了避免下次再打開該文件時還要從硬盤上重復載入 inode,應該在該文件第一次被打開時就將其 inode加入到 內存緩存中,每次打開一個文件時,先在此緩沖中查找相關的 inode , 如果有就直接使用, 否則再從硬盤上讀取 inode,然后再加入此緩存

image.png

掛載分區(qū)的實質是把該分區(qū)文件系統(tǒng)的元信息從硬盤上讀出來加載到內存中,這樣硬盤資源的變化都用內存中元信息來跟蹤。如果有寫操作,及時將內存中的元信息同步寫入到硬盤以持久化

文件描述符所描述的對象是文件的操作。
每次打開一個文件就會產生一個文件結構
文件描述符確實只是個整數(shù),準確地說,它是 PCB 中文件描述符數(shù)組元素的下標


image.png
image.png
image.png
image.png

有三個標準的文件描述符, 0 是標準輸入, 1 是標準輸出, 2 是標準錯誤

磁盤是一種低速設備,因此文件系統(tǒng)的設計原則是盡量減少硬盤操作。

inode 隊列中的所有 inode 應該被所有任務共享,包括內核線程和進程

第十五章 系統(tǒng)交互

fork復制進程資源,然后執(zhí)行


image.png
image.png

孤兒進程和僵尸進程
當父進程提前退出時,它所有的子進程還在運行,沒有一個執(zhí)行了 exit,因為它們的生命周期尚未結束,還在運行中,個個都擁有“全尸”(進程體),這些進程就稱為孤兒進程。
如果父進程在派生出子進程后井沒有調用 wait 等待接收子進程的返回值,這時某個子進程調用 exit 退出了,自然沒人來接收返回值了(父進程未退出,因此子進程不能過繼給 init, init 也不能幫子進程做善后收尸,只有父進程才有權限為子進程收尸),因此其 pcb 所占的空間不能釋放,沒人為其“收尸飛自然就成了“僵尸”。

image.png

管道是個環(huán)形緩沖區(qū)

管道有兩端,→端用于從管道中讀入數(shù)據(jù),另一端用于往管道中寫入數(shù)據(jù)。這兩端使用文件描述符的方式來讀取,故進程創(chuàng)建管道實際上是內核為其返回了用于讀取管道緩沖區(qū)的文件描述符, 一個描述符用于讀,另一個描述符用于寫。

image.png

管道的用法: 進程在創(chuàng)建管道之后馬上調用 fork,克隆出一個子進程,子進程完全繼承了父進程的一切,也就是說和父進程一模一樣,因此也繼承了管道的描述符,這為父子進程通信提供了保證。

image.png
image.png
image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容