進程創建
fork()------復制,返回值,寫時復制
vfork()創建子進程—子進程與父進程共用同一塊虛擬地址空間,
為了防止調用棧混亂,因此阻塞父進程直到子進程調用exit()退出或者進行程序替換
vfork創建的子進程不能在main函數中return 0;退出,因為釋放資源后,父進程陷入混亂崩潰
fork和vfork的聯系
fork和vfork在內核都是調用clone實現進程的創建
fork函數
fork從已存在進程中創建一個新進程。新進程為子進程,而原進程為父進程。
- 進程調用fork,當控制轉移到內核中的fork代碼后,內核做以下的事情:
- 分配新的內存塊和內核數據結構給子進程
- 將父進程部分數據結構內容拷貝至子進程
- 添加子進程到系統進程列表當中
- fork返回,開始調度器調度
fork函數返回值
1. 子進程返回0
2. 父進程返回的是子進程的pid
fork常規用法
1. 一個父進程希望復制自己,使父子進程同時執行不同的代碼段。
2. 例如,父進程等待客戶端請求,生成子 進程來處理請求。 一個進程要執行一個不同的程序。例如子進程從fork返回后,調用exec函數
fork調用失敗的原因
1.系統中有太多的進程2.實際用戶的進程數超過了限制
進程中止
進程退出場景
1.代碼運行完畢
2.結果正確 代碼運行完畢
3.結果不正確 代碼異常終止
中止方式:
1.main函數中return;
2.exit(int statu) 庫函數 ,退出時刷新緩沖區
3. _exit(int statu) 系調用接口,退出時,不會刷新緩沖區,直接釋放資源
返回值只用了1個字節,0到255.
進程等待
等待子進程退出----避免僵尸子進程,獲取子進程返回值
pid_wait(int status)—阻塞等待任意一個子進程退出
阻塞:發起一個系統調用完成功能,當前如果不具備條件;等待直到完成功能后返回
非阻塞:當前如果不具備完成條件;則立即返回。
pid_waitpid(pid_t pid ,int *status,int options)pid: -1 :等待任意進程子進程 >0:等待指定子進程status 用于獲取子進程的退出碼;不關注置空即可options:0 阻塞等待子進程退出WNOHANG 將waitpid設置為非阻塞
返回值:>0:退出的子進程pid ==0:當前沒有子進程退出 <0;出錯
獲取子進程status
wait和waitpid,都有一個status參數,該參數是一個輸出型參數,由操作系統填充。
如果傳遞NULL,表示不關心子進程的退出狀態信息。
否則,操作系統會根據該參數,將子進程的退出信息反饋給父進程
獲取子進程返回值:statu格式
---低16位中的高8位存儲子進程返回值
---低16位中的低8位中的高1位存儲core dump標志; 低7位存儲異常信號值
核心轉儲:程序異常退出時,保存程序運行信息,便于調式。
獲取返回值
status&0x7f==0-----程序正常退出,沒有異常信號
(status>>8)&0xff-------取返回值
異常退出信號值為0------表示子進程正常退出;否則是異常退出,返回值沒有判斷意義
If((statu & 0x7f)==0){Printf(“child exit code : %d\n”,(statu >> 8) & 0xff);
}
程序替換
替換一個進程所正在運行的程序--------重新加載其他程序到內存,重新映射虛擬地址空間與內存的映射位置到新的程序地址上;(代碼段修改映射位置,數據段重新初始化)
進程重新從main函數開始調度運行
重新更新頁表信息,映射地址信息
更改程序計數器到main函數的起始位置,重新開始執行
替換函數
六種替換函數
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …);
int execle(const char *path, const char *arg, …,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[])
int execve(const char *path, char *const argv[], char *const envp[]);
這些函數原型看起來很容易混,但只要掌握了規律就很好記。
l(list) : 表示參數采用列表
v(vector) : 參數用數組
p(path) : 有p自動搜索環境變量PATH
e(env) : 表示自己維護環境變量
l和v的區別:傳參的區別
l是程序運行參數使用函數的實參平鋪的形式賦予 execl(ls ,ls ,-l -a ,NULL)
v是程序運行參數使用字符串指針數組賦予
argv[0]=ls argv[1]=-1 execl(ls , argv)
帶p和不帶p區別:
帶p:程序名稱可以不帶路徑,直接區PATH環境變量所制定的路徑下找程序Execlp(ls , …)
不帶p:程序名稱必須帶路徑
execl(/bin/ls)
帶e和不帶e的區別:
帶e: 給進程自定義環境變量 env[0]=”myenv=100”execle(ls , ……, NULL,env)
不帶e: 繼承原有默認的環境變量。
Execl(ls ,…);
hello ~~bite~~!!本來要被父子進程都打印一遍,一共打印兩遍,現在只被打印一遍,因為子進程被程序替換