子程序複製了父程序的什麼

2022-05-03 03:09:07 字數 1891 閱讀 9704

如果你對**段、資料段、棧、堆存放哪些資料還不是很清楚,請先看我寫和linux 記憶體管理。

#include#include

#include

#include

main()

else

}

輸出:這裡就涉及到實體地址和邏輯位址(或稱虛擬位址)的概念。

靜態重定向--在程式裝入主存時已經完成了邏輯位址到實體地址和變換,在程式執行期間不會再發生改變。

動態重定向--程式執行期間完成,其實現依賴於硬體位址變換機構,如基址暫存器。

使用者程式看不見真正的實體地址。使用者只生成邏輯位址,且認為程序的位址空間為0到max。實體地址範圍從r+0到r+max,r為基位址,位址對映-將程式位址空間中使用的邏輯位址變換成記憶體中的實體地址的過程。由記憶體管理單元(mmu)來完成。

fork()會產生乙個和父程序完全相同的子程序,但子程序在此後多會exec系統呼叫,出於效率考慮,linux中引入了「寫時複製「技術,也就是只有程序空間的各段的內容要發生變化時,才會將父程序的內容複製乙份給子程序。在fork之後exec之前兩個程序用的是相同的物理空間(記憶體區),子程序的**段、資料段、堆疊都是指向父程序的物理空間,也就是說,兩者的虛擬空間不同,但其對應的物理空間是同乙個。當父子程序中有更改相應段的行為發生時,再為子程序相應的段分配物理空間,如果不是因為exec,核心會給子程序的資料段、堆疊段分配相應的物理空間(至此兩者有各自的程序空間,互不影響),而**段繼續共享父程序的物理空間(兩者的**完全相同)。而如果是因為exec,由於兩者執行的**不同,子程序的**段也會分配單獨的物理空間。

fork之後核心會

通過將子程序放在佇列的前面,以讓子程序先執行,以免父程序執行導致寫時複製,而後子程序執行exec系統呼叫,因無意義的複製而造成效率的下降。

fork時子程序獲得

父程序資料空間、堆和棧的複製,所以變數的位址(當然是虛擬位址)也是一樣的。

每個程序都有自己的虛擬位址空間,不同程序的相同的虛擬位址顯然可以對應不同的實體地址。因此位址相同(虛擬位址)而值不同沒什麼奇怪。

具體過程是這樣的:

fork子程序完全複製父程序的棧空間,也複製了頁表,但沒有複製物理頁面,所以這時虛擬位址相同,實體地址也相同,但是會把父子共享的頁面標記為「唯讀」(類似mmap的private的方式),如果父子程序一直對這個頁面是同乙個頁面,知道其中任何乙個程序要對共享的頁面「寫操作」,這時核心會複製乙個物理頁面給這個程序使用,同時修改頁表。而把原來的唯讀頁面標記為「可寫」,留給另外乙個程序使用。

這就是所謂的「寫時複製」。正因為fork採用了這種寫時複製的機制,所以fork出來子程序之後,父子程序哪個先排程呢?核心一般會先排程子程序,因為很多情況下子程序是要馬上執行exec,會清空棧、堆。。這些和父程序共享的空間,載入新的**段。。。,這就避免了「寫時複製」拷貝共享頁面的機會。如果父程序先排程很可能寫共享頁面,會產生「寫時複製」的無用功。所以,一般是子程序先排程滴。

#include #include 

int main(void

)

輸出onetwo

onetwo

首先要清楚stdin和stdout都是行緩衝,stderr是無緩衝。"one"存放在父程序的行緩衝裡,子程序複製了父進行程的行緩衝,所以子程序也會列印輸出"one"。

#include #include 

int main(void

)

輸出onetwo

two

想消除行緩衝所帶來的困擾,方法如下

1、輸出資料後加換行符

2、使用fflush之類的函式強制重新整理

3、使用setbuf,setvbuf函式設定緩衝區大小

4、使用非緩衝的的流,如stderr.

子程序複製了父程序的什麼

這裡涉及到實體地址和邏輯位址 或稱虛擬位址 的概念 從邏輯位址到實體地址的對映稱為位址重定向 cpu產生的邏輯位址被分為 使用者只生成邏輯位址,且認為程序的位址空間為0到max。實體地址範圍從r 0到r max,r為基位址 每個程序都有自己的虛擬位址空間,不同程序的相同的虛擬位址顯然可以對應不同的實...

子程序退出,父程序為什麼要等待?

在模擬實現之前,我們首先要理解什麼是阻塞狀態?作業系統將不滿足某種條件的程序從執行佇列中拿出,將其狀態設定為其他狀態並放入等待佇列中,在此等待佇列中的程序的都處於阻塞狀態。1 殭屍程序,造成記憶體洩漏 2 父程序得管理子程序,所以父程序派給子程序的任務完成的如何,我們都需要知道,如,子程序執行完成,...

父程序與子程序管道

int main else return 0 先在父程序中建立管道,然後建立子程序,子程序複製了父程序管道檔案的檔案描述符,所以父程序和子程序各具有2個管道描述符,當在子程序中關閉讀端,這時關閉的是子程序中管道檔案的讀端,而父程序的讀端沒有關閉,這時子程序往寫段寫資料的時候,因管道讀端未完全關閉,所...