進程(三)----(進程創建、進程終止、進程等待、進程替換)

進程控制

1、進程創建

pid_t fork(void);- - - - -創建一個進程(父子進程數據獨有,代碼共享)

在這裏插入圖片描述
寫時拷貝技術(提高進程創建效率):子進程複製了父進程,一開始與父進程指向同一塊物理內存;因此看起來父子進程完全相同;但是進程之間具有獨立性,意味着當這塊物理內存中數據即將發生改變時會重新給子進程開闢物理內存,將數據拷貝過來,因爲子進程應該有自己的數據。按理說每個進程都應該有自己獨立的內存空間,但若創建子進程時直接開闢空間拷貝技術,會比較緩慢,並且拷貝過來的數據子進程從來都不用。
代碼共享"因爲代碼段是隻讀的。
**子進程創建pcb的時候,也會創建頁表,虛擬地址空間,然後從父進程pcb中拷貝這些數據過來。

  • vfork創建的子進程,父子進程可以同時運行
  • pid_t vfork(void):創建一個子進程,並且阻塞父進程,直到子進程exit退出或者程序替換之後,父進程纔會進行
  • vfork創建子進程效率比較高,因爲vfork創建子進程後父子進程會共用同一個虛擬空間。
  • 在這裏插入圖片描述
  • 早期使用vfork是因爲它創建子進程效率高,但是fork實現了寫時拷貝之後,創建效率也變高了,並且使用起來更加靈活,因此vfork現在已經很少使用了。

創建子進程優點:讓子進程調度另一個程序運行。(有一個任務,父進程可以幹,但是怕有風險,萬一數據處理出錯崩潰了,因此創建一個子進程,讓子進程去幹)

進程創建的流程:在內核中調用clone接口創建pcb,從父進程pcb拷貝數據進來,寫時拷貝技術。

進程終止(退出一個進程)

  • main函數return 退出進程時會退出緩衝區
  • void exit(int status);- - - - - 庫函數- - - - - 退出調用進程,將status作爲返回值返回給父進程
  • void _exit(int status);- - - - - 系統調用接口- - - - -退出調用進程,將status返回給父進程

庫函數和函數調用接口的關係?(庫函數封裝了系統調用接口,系統調用接口不太好用)

  • exit/return退出時都會刷新緩衝區,_exit退出時直接釋放資源,不刷新緩衝區
  • return只會在main函數中的時候纔會退出進程,而exit是在任意位置調用都會推出調用進程

以上幾種進程退出方式都屬於進程的正常退出,但是會根據返回值向父進程表示爲什麼退出。
在進程退出時也可能異常退出,(如:程序中出現分母爲零情況)- - - - -程序崩潰- - - - -程序並沒有運行完畢,突然因爲某種錯誤退出了

進程等待(父進程等待子進程的退出,獲取子進程的返回值,避免產生殭屍進程)

pid_t wait(int *status);- - - - -阻塞等待任意一個子進程退出,獲取子進程的返回值到status指向的空間中,並且釋放子進程資源,返回退出的子進程pid。
阻塞:爲了完成某個功能發起一個調用,若目前不具備完成功能的條件,則調用不返回一直等待;
非阻塞:爲了完成某個功能發起一個調用,若當前不具備完成功能的條件,則立即報錯返回;非阻塞操作通常需要循環操作。

*pid_t waitpid(pid_t pid,int status,int options);
pid:若== -1,則表示等待任意一個子進程退出;若 > 0,則表示等待指定的子進程退出。
status:輸出型參數,傳入一個 int 空間的首地址,獲取退出的子進程返回值。
options:選項參數,0- - - 表示默認阻塞等待;WNOHANG- - -表示將waitpid設置爲非阻塞,沒有子進程已經退出的話就立即報錯返回。
返回值:若等待到了子進程退出則返回子進程的pid;若有子進程,但是沒有退出則返回0;出錯返回 -1.

  • 非阻塞操作相較於阻塞操作,對CPU利用更加充分,因爲不在一直等待,但必須循環進行操作
  • wait和waitpid並不是只處理剛退出的程序,而是對已經退出的進程進行處理(不管什麼時候退出的)

int status == status這個變量有四個字節的空間,向函數傳入地址
int *status 定義了一個指針變量,有8個字節空間,存放的是另一塊空間的地址
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章