Linux——程式建立、程式終止、程式等待、程式程式替換
一、程式建立
建立一個程式就是建立一個pcb,pcb在Linux下是一個task_struct結構體,放在核心中,只能通過呼叫介面實現建立
1.pid_t fork(void);
通過複製父程式建立一個子程式(複製了父程式pcb中的資料)
程式碼共享,資料獨有
2.pid_t vfork(void);
也是建立一個子程式,但是父程式使用vfork建立後,vfork的呼叫並不會立即返回(通常說會阻塞父程式),而是讓子程式先執行,直到子程式退出或執行程式替換之後父程式才能執行(vfork建立的子程式若程式替換,排程執行新的程式,就會給自己開闢新的空間,與新的程式建立對映關係)
資料共用
vfork建立的子程式特殊的地方:父子程式共用一個虛擬地址空間(父程式的虛擬地址空間)
在程式執行中每呼叫一個函式就會有一次函式壓棧——函式呼叫棧
父子程式使用了同一個棧,若父子程式同時執行會造成呼叫棧混亂,因此讓子程式先執行,直到子程式退出或程式替換後有了自己的地址空間
注意:vfork建立的子程式不能在main函式中使用return退出,因為子程式使用return退出釋放了所有資源,父程式執行的時候資源是錯誤的
3.寫時拷貝技術
子程式建立出來後,與父程式對映關係訪問同一塊物裡記憶體(但虛擬地址空間及頁表這些資訊都是程式獨有),當物裡記憶體中資料即將發生改變時,重新為子程式開闢實體記憶體,拷貝資料過去
4.程式擁有獨立性——各有各的虛擬地址空間,對映各自資料儲存
程式之間沒有交叉關係,不會受到其他程式執行影響,就是為了保證程式的穩定執行
5.返回值
子程式中返回0;父程式中返回子程式的pid;出錯返回-1
二、程式終止
1.程式常見退出方法
(1)main函式中的return
普通函式中的return只能退出函式,不能退出程式
(2)void exit (int status);
在任意位置呼叫程式的任意位置退出一個程式
(3)void _exit (int status);
在任意位置呼叫程式的任意位置退出一個程式
問:exit和_exit的區別是什麼?
答:exit是庫函式,退出時會重新整理緩衝區,將緩衝區的資料寫入檔案;
_exit是系統呼叫介面,退出程式時直接釋放資源,不會重新整理緩衝區
2.程式退出場景
正常退出:程式執行到return或exit的地方退出
異常退出:程式執行到中途崩潰了
不管子程式正常退出或者異常退出,只要是退出了,沒有被父程式等待處理,就都會成為殭屍程式
三、程式等待
父程式等待子程式退出,為了獲取退出子程式的返回值,釋放退出子程式的所有資源,避免產生殭屍程式
殭屍程式產生的原因:子程式先於父程式退出,為了儲存退出返回值而無法完全釋放資源產生的
程式等待的方法
1.int wait (int* status); [status:輸出型引數——用於獲取退出子程式的返回值]
處理退出的子程式,如果呼叫這個介面沒有子程式已經退出,則會使父程式阻塞等待,直到有子程式退出
阻塞:為了完成一個功能我們發起一個呼叫,但是若當前不具備完成功能的條件,則呼叫等待
非阻塞:為了完成一個功能我們發起一個呼叫,但若當前不具備完成功能的條件,則呼叫立即報錯返回
返回值:成功返回處理的退出子程式的pid,失敗(比如沒有子程式)返回-1
2.int waitpid (int pid, int *status, int options);
返回值:成功返回退出子程式的pid,沒有子程式退出返回0,失敗(比如沒有子程式)返回-1
wait與waitpid的區別:
(1)wait等待的是任意一個子程式的退出(wait是一個父程式假設有很多子程式,任意一個退出,都會處理後呼叫返回);waitpid可以等待指定的子程式,也可以等待任意一個子程式,通過第一個引數確定(第一個引數pid == -1表示等待任意)
(2)wait是一個阻塞介面(wait如果沒有子程式退出,則會一直等待);waitpid可以預設阻塞,也可以設定為非阻塞,通過第三個引數確定(option == 0表示預設阻塞,option == WNOHANG表示非阻塞),非阻塞操作通常需要迴圈處理
3.獲取子程式status
一個程式退出場景有兩種:正常退出、異常退出
一個程式只有正常退出的時候返回值才有意義;若程式是異常退出,則返回值沒有意義
因此在獲取返回值之前,應先通過低七位判斷程式是否是正常退出(正常退出則異常訊號值為0;否則大於0)
判斷一個程式是否正常退出:取出低七位;status & 0x7f == 0 正常退出
如何取出返回值(低16位中的高8位):(status >> 8)& 0xff ——因為返回值只用了一個字元,因此程式的返回值
WIFEXITED() / WEXITSTATUS
系統呼叫介面出錯後,如何獲取錯誤原因?
#include<errno.h>
#include<string.h>
char *strerror(errno); 根據錯誤編號獲取文字資訊——錯誤都是上一次系統呼叫介面使用錯誤的原因
perror(char *msg);直接列印上一次系統呼叫介面使用錯誤的原因
core dump——核心轉儲
指的是程式異常退出時,將退出前的程式執行資訊儲存下來(預設是關閉的)
四、程式程式替換
重新載入另一個程式到記憶體中,然後將現有的一個pcb的記憶體指標所指向的記憶體空間指向這個新的程式(更新頁表對映資訊),則這個現有的pcb就跑去排程這個新的程式了。
程式替換,給一個程式替換一個新的要排程執行的程式,並且因為這個程式排程的程式已經被替換,因此當執行完畢新的程式後會退出;原先的程式在程式替換以後的程式碼都不會被執行到(替換後相當於已經沒有當前的程式碼了,只有新的程式)
如何替換:exec函式族
#include<unistd.h>
int execl(const char *path, const char *arg, ...);//path—帶路徑的程式檔名稱;arg/...表示程式的執行引數,逐個賦予,最終以NULL結尾
int execlp(const char *file, const char *arg, ...);//PATH環境變數指定了一些路徑,execlp會去PATH環境變數指定的路徑下查詢程式檔案
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const arg);
int execvp(const char *file, char *const arg);
int execve(const char *file, char *const arg, char *const envp[]);
i 和 v的區別:程式執行引數的賦予方式不同
有沒有p的區別:新的程式檔案的名稱是否需要帶路徑
有沒有e的區別:是否自定義環境變數
相關文章
- Linux系統程式設計之程式控制(程式建立、終止、等待及替換)Linux程式設計
- 程式等待和程式替換
- 程式控制:程式的建立、終止、阻塞、喚醒和切換
- Windows 程式的建立和終止Windows
- Linux Shell程式設計(28)——程式替換Linux程式設計
- Linux 下使用 killall 命令終止程式Linux
- 終止指定埠的程式
- shell替換程式裡的程式碼
- linux下查詢程式及終止程式操作的相關命令Linux
- shell替換程式碼
- 【Linux】程式終止方式--exit的呼叫過程!!!Linux
- Linux系統程式設計之程式替換:exec 函式族Linux程式設計函式
- Linux之ps查詢程式用kill終止命令Linux
- Linux Shell程式設計(24)——命令替換Linux程式設計
- 終止程式的工具 kill 、killall、pkill、xkill
- Linux 下使用 killall 命令終止程式的 8 大用法Linux
- linux下啟動和終止JAVA程式shell指令碼LinuxJava指令碼
- Linux Shell程式設計(6)——變數替換Linux程式設計變數
- subprocess.Popen 如何提前終止程式執行
- Linux下可以替換執行中的程式麼?Linux
- Linux程式管理、程式建立、執行緒實現、殭屍程式Linux執行緒
- 併發程式設計——如何終止執行緒程式設計執行緒
- APUE 7-3 終止處理程式例項
- 如何在OS X中建立郵箱地址的替換程式碼
- 子程式等待父程式退出及fork使用
- Linux 下用ps查詢程式並用kill終止命令詳解Linux
- jQuery的each終止或跳過示例程式碼jQuery
- 終止imp/exp和expdp/impdp程式執行的方法
- PHP實現守護程式的啟動和終止操作PHP
- python 小程式,替換檔案中的字串Python字串
- replace()方法替換字串內容程式碼例項字串
- 如何將Windows的桌面替換成自己的程式Windows
- java建立程式Java
- linux系統程式設計之程式(一):程式與程式Linux程式設計
- 程式的建立和程式的狀態
- qt程式建立及模板程式碼分析QT
- linux系統程式設計之程式(八):守護程式詳解及建立,daemon()使用Linux程式設計
- 用Python程式如何捕獲Ctrl+C終止訊號?Python