1. 程式人生 > >Linux(高階程式設計)3————程序的控制

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的引數。

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,會在下一篇部落格中更新。