1. 程式人生 > >2014025627 《嵌入式程序設計》第五周學習總結

2014025627 《嵌入式程序設計》第五周學習總結

utl char 程序 width 學習總結 user 成功 數據段 判斷

教材學習內容總結

fork()函數:

一個進程,包括代碼、數據和分配給進程的資源。fork()函數通過系統調用創建一個與原來進程幾乎完全相同的進程,也就是兩個進程可以做完全相同的事,但如果初始參數或者傳入的變量不同,兩個進程也可以做不同的事。 一個進程調用fork()函數後,系統先給新的進程分配資源,例如存儲數據和代碼的空間。然後把原來的進程的所有值都復制到新的新進程中,只有少數值與原來的進程的值不同。fork()函數從已存在的進程中創建一個新進程。父進程→子進程,子進程幾乎是父進程的復制,其所獨有的只有它的進程號、資源使用和計時器等。子進程繼承了父進程的整個地址空間,包括進程上下文、代碼段、進程堆棧等。

父子進程的一個重要區別是:fork()的返回值不同。父進程中返回子進程的進程號,子進程中返回0 出錯為-1

Exec族函數

說是exec系統調用,實際上在Linux中,並不存在一個exec()的函數形式,exec指的是一組函數,一共有6個,分別是:

#include <unistd.h>

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[]);

其中只有execve是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。exec函數族的作用是根據指定的文件名找到可執行文件,並用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。這裏的可執行文件既可以是二進制文件,也可以是任何

Linux下可執行的腳本文件。與一般情況不同,exec函數族的函數執行成功後不會返回,因為調用進程的實體,包括代碼段,數據段和堆棧等都已經被新的內容取代,只有調用失敗了,它們才會返回一個-1,從原程序的調用點接著往下執行。fork()函數用於創建一個子進程,該子進程幾乎復制了父進程的所有內容,exec函數族提供了一個在進程中執行另外一個程序的方法。在執行完之後,當前進程除了進程號之外,其他的內容都被替換了。 出錯時返回-1

註意一定要寫上錯誤判斷語句,常見的錯誤有: 找不到文件或者路徑,此時error被設置為ENOENT數組argvenvp忘記用NULL結束,此時error被設置為EFAUTL 沒有對應可執行文件的運行權限,此時error被設置為EACCES

execlp(),以文件名的方式來查找可執行文件,同時使用參數列表的方式。運行結果與在shell中輸入命令ps -ef是一樣的。 execl(),使用完整的文件目錄來查找對應的可執行文件。註意目錄必須以/開頭,否則將其視為文件名。if((execlp("/bin/ps","ps","-ef",NULL))<0) 這裏必須是ps程序的完整路徑,註意目錄必須以/開頭。

execle()函數將環境變量添加到新建的子進程中,這裏的env是查看當前進程環境變量的命令。命令參數列表,必須以NULL結尾 char *envp[]={"PATH=/tmp","USER=harry",NULL};if((execle("/usr/bin/env","env",NULL,envp))<0)需要指出env的完整路徑

execve()函數,通過構造指針函數數組的方式來傳遞函數,註意參數列表一定要以NULL作為結束標識符。

終止程序函數exit()和_exit()函數:

_exit()函數:直接使進程停止運行,清除其使用的內存空間,並銷毀其在內核中的各種數據結構;_exit()函數的作用是直接使進程停止運行,使文件讀寫的速度加快;而exit()函數先會“清理I/O緩沖”,若想要保證數據的完整性,最好使用exit()函數。

void _exit(int status); status用於傳遞進程結束的狀態,一般來說,0表示正常結束,其他數值表示非正常結束。 實際編程時,可以用wait()系統調用接收子進程的返回值,從而針對不同的情況進行不同的處理。

exit()函數則在這些基礎上作了一些包裝,在執行退出之前加了若幹道工序。

exit()函數與_exit()函數最大的區別就在於 exit()函數在調用 exit 系統調用之前要檢查文件的打開情況,把文件緩沖區中的內容寫回文件。

wait()函數和waitpid( )函數:

wait()函數用於使父進程(也就是調用wait()的進程)阻塞,直到一個子進程結束或者該進程接收到了一個指定的信號為止。如果父進程沒有子進程或者它的子進程已經結束,則wait()會立即返回-1. wait()會暫時停止目前進程的執行,直到有信號來到或子進程結束。如果在調用wait()時子進程已經結束,則wait()會立即返回子進程結束狀態值。子進程的結束狀態值會由參數status 返回,而子進程的進程識別碼也會一快返回

wait()函數的語法:

#include<sys/types.h>

#include<sys/wait.h>

pid_wait int *status;

status指向的整型對象用來保存子進程結束時的狀態; 若成功則返回回收的子進程的進程號,失敗則返回-1

waitpid()的作用與wait()一樣,但它並不一定等待第一個終止的子進程。waitpid()有若幹選項,可提供一個非阻塞版本的wait()功能。實際上,wait()只是 waitpid()函數的一個特例,在linux內部實現wait()函數時直接調用的就是waitpid()函數。waitpid()會暫時停止目前進程的執行,直到有信號來到或子進程結束。如果在調用 waitpid()時子進程已經結束,則 waitpid()會立即返回子進程結束狀態值。 子進程的結束狀態值會由參數 status 返回,而子進程的進程識別碼也會一起返回。

waitpid()函數的語法:

#include<sys/types.h>

#include<sys/wait.h>

pid_waitpid( pid_t pid , int *status, int options );

參數說明:pid

pid>0,回收進程ID等於pid的子進程

pid=-1,回收任何一個子進程,此時和wait()相同

options

WNOHANG 若指定的子進程沒有結束,則waitpid()不阻塞而立即返回,此時返回值為0

WUNTRACED 為了實現某一個操作,由pid指定的任一子進程已被暫停,且其狀態自暫停以來沒有報告過,則返回其狀態。

返回值:已經結束的子進程的進程號(>0;

2014025627 《嵌入式程序設計》第五周學習總結