什麼是進程?進程是一個運行中的程序實體,擁有獨立的堆棧、內存空間和邏輯控制流。函數
這是標準的進程概念。讓咱們經過操做系統的fork
函數看看這個抽象的概念是怎麼在進程的實現中體現出來的。操作系統
建立一個進程,須要進程體、進程表和數據空間。指針
進程體在C代碼中對應一個函數,編譯成二進制代碼後就是一組指令。code
進程表用來記錄進程的進程ID、進程名稱、寄存器快照空間。簡單說,當中斷髮生時,會保存此刻CPU的狀態,而後記錄到進程表中。進程
進程表的做用就是用來存儲進程快照。內存
進程堆棧的做用是什麼?存儲進程中函數的參數,存儲進程運行過程當中的局部數據。字符串
數據空間呢?先看一段簡單的代碼。編譯
char *f(int a, int b); int main(int argc, char **argv) { f(5, 6); return 0; } char *f(int a, int b) { int c = a + b; char *str = "Hello, World!"; return str; }
char *str
指向的內存中的數據STR存儲在進程的數據空間中。爲何STR不是存儲在進程的堆棧中呢?class
函數f的返回值是STR的內存地址。執行這段代碼,咱們會發現:調用函數f能正確得到STR。變量
試想一下,假如STR存儲在進程的堆棧中,當f執行結束後,堆棧中的數據會被清空,咱們調用函數f是不能正確得到STR的。
STR存儲在進程的數據空間中,存儲在進程堆棧中的只是存儲STR的內存空間的內存地址。
進程A調用fork新建進程B,A是B的父進程,B是A的子進程。
fork執行結束後,若是能成功建立B進程,B進程的數據空間、堆棧和進程表和A進程的這些要素徹底相同。
B進程畢竟是不一樣於A進程的獨立進程,因此:
猜猜看,子進程的堆棧是在進程表中仍是在數據空間中?
回答是:在進程的數據空間中。
在前面,咱們雖然把堆棧和數據空間分開說,那是爲了強調兩個要素在保存數據時的差別。堆棧中的數據隨時變化,例如,進程中的一個函數執行結束,堆棧中的數據就會發生變化。
進程的數據空間呢?我覺得,當進程結束執行的時候,進程的數據空間中的數據纔會消失。這是個人猜想,暫時不知道怎麼去驗證。
認爲堆棧保存在數據空間中的依據是什麼?由於寄存器ss
中的選擇子指向的描述符描述的那段內存空間就是數據空間。
進程的ds、es、ss
的選擇子相同,指向相同的數據空間。
每一個進程都有一個LDT。LDT存儲在進程的進程表中。
在進程的進程表中,有一個LDT選擇子。根據LDT選擇子,能從GDT中找到指向LDT的描述符。
有點繞。連起來再說一次:經過進程表中的LDT選擇子,從GDT中找到指向LDT的描述符,根據描述符找到LDT,LDT也在進程表中。