Linux(高階程式設計)3————程序的控制
程序控制都包含那些內容?
1.程序建立
2.程序終止
3.程序等待
4.程序替換
1.程序建立:
在前面程序概念中關於程序建立已有所瞭解,下面更詳細的分析進城建立。
-
fork()函式
返回值型別:pid_t
1.返回值:
1.子程序中返回0;
2.父程序中返回子程序的pid;
3.失敗返回-1 ;
(失敗原因:1.子程序數目達到上限;2.記憶體不夠)
2.fork的特點:
1.子程序以父程序為模板拷貝父程序。(寫時拷貝)
2.子程序把父程序的PCB複製,稍加修改(pid/ppid)
3.記憶體指標上下文基本相同。
4.父子程序執行同一份程式碼。
5.子程序從fork之後開始執行,父子程序執行順序取決與作業系統的排程。
畫圖理解fork()之後父子程序執行的過程:
fork()的寫時拷貝技術:
通常情況下父子程序程式碼共享,當有一方向試圖寫入時,便以寫時拷貝的方式雙方各執一份副本。- vfork()函式
Linux前期的程序建立函式,缺點比較多,在程序概念中以講過,這裡就不在解釋。
2.程序終止:
- 程序退出的3個場景:
1.程式碼執行完畢,結果正確。
2.程式碼執行完畢,結果錯誤。
3.程式碼異常終止。 - 程序常見退出方式:
1.從main函式返回。
2.呼叫exit()函式。
3._exit()。
同為程序終止函式exit()和_exit的區別:
1.exit()函式呼叫通過at_exit()和on_exit()函式定義的清理函式(回撥函式)。
2.exit()函式關閉所有開啟的流,所有的緩衝資料均被寫入。
3.呼叫_exit();- A: exit()退出、_exit()退出 例項:
- B:return退出
return是一種常見的退出程序方式。執行return n等同於執行exit(n),因為main函式會將return返回值當作為exit的引數。
- A: exit()退出、_exit()退出 例項:
3.程序等待:
-
程序等待的必要:
1.之前介紹過殭屍程序,如果子程序退出,父程序對子程序退出置之不理的話,就會造成記憶體洩露。
2.一旦成為殭屍程序的話,就會變的刀槍不入,kil -9都沒辦法,因為不可能殺死一個已經死了的程序。
3.父程序如果不等待子程序的話,就不會獲知父程序派給子程序的任務完成的情況。結果是否正確,是否正常退出。
4.父程序通過程序等待獲取子程序退出資訊,釋放子程序資源。 -
程序等待的方式:
1.wait方法:
返回值:pid_t;成功:返回子程序pid;失敗:返回-1;
引數:輸出型引數,獲取子程序退出狀態,不關心則可設為NULL。
特點:阻塞型等待。
wait阻塞例項:
2.waitpid方法:
返回值:pid_t型別;成功:返回收集到子程序pid;如果設定WNOHANG,waitpid發現沒有已退出的子程序可收集,則返回0;
失敗:返回-1;
pid:pid = -1,等待任意一個子程序,與wait等效;pid>0,等待ID與pid相等的子程序。
status:儲存程序退出狀態。
options:WNOHANG,若pid指定的子程序沒有結束,直接返回0,不予以等待。若子程序結束,則返回子程序pid。
出錯原因: 不存在子程序。
4.程序替換:
- 程序 替換會用到exec族函式:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<wait.h>
#include<fcntl.h>
//exec族函式使用樣例
int main(void)
{
char* const argv[] = {"ps","-ef",NULL};
char* const envp[] = {"PATH=/bin:/usr/bin","TIME=console",NULL};
//1.execl 檔案路徑l,在檔案路徑中找,可以是相對路徑,也可以是絕對路徑
//execl("/bin/ps","ps","-ef",NULL);
//2.execlp 檔名p,在當前路徑中找,帶環境變數,無需寫全路徑
//execlp("ps","ps","-ef",NULL);
//3.execle 帶e的,需要自己組裝環境變數
//execle("/bin/ps","ps","-ef",NULL,envp);
//4.execv,帶v的,命令以陣列方式傳參
//execv("/bin/ps",argv);
//5.execvp,帶v帶p
//execvp("ps",argv);
//6.execve,帶v帶e
//execve("/bin/ps",argv,envp);
exit(0);
}
學習了程序控制,我們可以根據bash的原理自己寫一個小專案,自己的shell,會在下一篇部落格中更新。