進程切換(上下文切換):
- 定義:暫停當前運行進程,從運行狀態變成其他狀態,調度另一個進程從就緒狀態變成運行狀態
- 要求:切換前,保存進程上下文;切換后,恢復進程上下文;快速切換
- 進程存儲的生命周期的信息:寄存器(PC,SP,...);CPU狀態;內存地址空間
進程控制塊PCB:內核的進程狀態記錄
- 內核為每個進程維護了對應的進程控制塊PCB
- 內核將相同狀態的進程的PCB放置在同一隊列
進程控制塊結構:
- 進程標識信息
- 進程狀態信息
- 進程占用的資源(存儲資源、內核堆棧等)
- 保護現場用的內容
- 當前進程在哪個隊列
其中內存地址空間結構中會包含:有哪些內存塊及地址空間,第一級頁表起始地址,置換相關結構
進程創建:
- Windows進程創建API:CreateProcess
- Unix進程創建系統調用:fork/exec。fork()把一個進程復制成兩個進程,父子進程有各自的PID;接下來的exec()用新程序來重寫當前進程,PID不改變。
空閑進程創建
當用戶代碼執行完之后,系統將在空閑進程中執行。
第一個內核線程的創建:
fork()的開銷:
- 對子進程分配內存
- 復制父進程的內存和CPU寄存器到子進程里
- 開銷昂貴
99%調用fork是為了接下來調用exec,考慮到fork()操作中內存復制是沒有作用的,子進程可能會關閉打開的文件和連接,因此考慮將其合并到一個調用中,于是出現了vfork()。
vfork():
- 創建進程時,不再創建一個同樣的內存映像,而是當調用exec()時才開始復制,而要被覆蓋或者關閉的資源不再進行復制
- 一些時候稱為輕量級fork()
- 子進程應該幾乎立刻調用exec()
- 現在使用Copy on Write(COW)技術
進程加載exec
- exec調用成功時:是相同的進程,運行了不同的程序
- exec()允許一個進程加載一個不同段程序,并在MAIN執行,(_start)
- 允許一個進程指定參數的數量argc和字符串參數數字argv
- 允許進程指定不同的控制流,OS中可指定不同的應用程序,即調用成功=相同進程,運行的是不同的程序!
- Code(代碼段)stack(堆棧)heap(堆)等完全重寫
進程等待與退出:
父進程等待子進程:
1. wait()系統調用用于父進程等待子進程的結束
- 子進程結束時通過exit()向父進程返回一個值
- 父進程通過wait()接受并處理返回值
2. wait()系統調用的功能
- 有子進程存活時,父進程進入等待狀態,等待子進程的返回結果。當某子進程調用exit()時,喚醒父進程,將exit()返回值作為父進程中wait的返回值
- 有子進程調用exit()而父進程還未調用wait()處理時,子進程被稱為僵尸進程。如果此時父進程調用wait()則直接處理并返回
- 無子進程或無子進程存活時,wait()也是立刻返回
3. exit()用于進程的有序終止
- 進程結束執行時調用exit(),完成進程資源回收。
4.?exit()系統調用的功能
- 將調用參數作為進程的結果返回
- 關閉所有打開的文件等占用資源
- 釋放內存
- 釋放大部分進程相關的內核數據結構
- 檢查是否父進程是存活的:如果父進程存活,保留結果的值直到父進程用wait()處理,進入僵尸狀態;如果父進程不存活,則子進程為孤兒進程,直接釋放所有數據結果,進程結束
- 清理所有等待的僵尸進程
其他進程控制系統調用
- 優先級控制:nice()指定進程的初始優先級;unix系統中進程優先級會隨執行時間而衰落
- 進程調試支持:ptrace()允許一哥進程控制另一個進程的執行;設置斷點和查看寄存器
- 定時:sleep()可以讓進程在定時器的等待隊列中等待指定。
為什么要讓父進程等?而不是直接結束?
當進程執行完畢退出后,幾乎所有資源都回收到OS中。但有個資源很難回收,就是PCB,PCB是代表進程存在的唯一標識,OS要依據PCB執行回收。這個功能由父進程完成。
?