fork()函數
程序是一個程式的一次執行的過程。它和程式是有本質差別的,程式是靜态的,它是一些儲存在磁盤上的指令的有序集合,沒有任何執行的概念;而程序是一個動态的概念,它是程式執行的過程,包括了動态建立、排程和消亡的整個過程。它是程式執行和資源管理的最小機關。
在Linux中從已存在的程序中建立一個新的程序唯一方法是使用fork()(或vfork(),下一篇筆記将介紹它們的差別),原來存在的程序為父程序,新建立的程序為子程序,fork()函數執行一次傳回兩個值,子程序傳回0,父程序傳回子程序的PID,出錯傳回-1;使用fork()建立的子程序就是父程序的一個複制品,子程序繼承了整個程序的位址空間,包括程序上下文、程序堆棧、記憶體資訊、打開的檔案描述符、信号控制設定、程序優先級、程序組号、目前工作目錄、根目錄、資源限制、控制終端等,而子程序所獨有的隻有它的程序号、資源使用和計時器等。下面是《Linux_C一站式學習》中的例子:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
char *message;
int n;
pid = fork();
if (pid < ) {
perror("fork failed");
exit();
}
if (pid == ) {
message = "This is the child\n";
n = ;
} else {
message = "This is the parent\n";
n = ;
}
for(; n > ; n--) {
printf(message);
sleep();
}
return ;
}
執行結果是
This is the child
This is the parent
This is the child
This is the parent
This is the child
This is the parent
This is the child
This is the chil
This is the child
程式的運作過程是

詳細說明看《Linux_C一站式學習》。
exec函數族
exec函數主要用于在程序中啟動另一個程式執行的方法,exec函數族是6個以exec字母開頭的函數,這6個函數執行成功不傳回,隻有出錯時傳回-1,它們就是:
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 *
下面對這些函數參數進行說明:
(1)通過對比這些函數,發現隻有函數名的第五和第六位的字母不一樣,首先看不帶字母“p”的函數,第一個參數必須是可執行程式的絕對路徑或相對路徑,而不能是檔案名,這個路徑就是PATH環境變量的值;
(2)帶有字母“l ”(表示list )的exec函數要求将新程式的每個指令行參數都當作一個參數傳給它,指令行參數的個數是可變的,是以函數原型中有… ,… 中的最後一個可變參數應該是NULL,起sentinel的作用;
(3)帶有字母“v”(表示vector )的函數,則應該先構造一個指向各參數的指針數組,然後将該數組的首位址當作參數傳給它,數組中的最後一個指針也應該是NULL,就像main函數的argv參數或者環境變量表一樣;
(4)以“e” (表示environment )結尾的exec函數,可以把一份新的環境變量表傳給它,其他exec函數仍使用目前的環境變量表執行新程式。
(5)下面是《嵌入式Linux應用程式開發詳解(完整版_第1-12章)》兩個應用執行個體
/*execlp.c*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
if(fork()==){
/*調用execlp函數,這裡相當于調用了“ps -ef”指令*/
if(execlp("ps","ps","-ef",NULL)<)
perror("execlp error!");
}
}
/*execl.c*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
if(fork()==){
/*調用execl函數,注意這裡要給出ps程式所在的完整路徑*/
if(execl("/bin/ps","ps","-ef",NULL)<)
perror("execl error!");
}
}
exit()/_exit()
exit()和_exit()都是用來無條件中止程序,但它們是有差別的
從圖檔可以看出在調用exit()比exit()時多做了些清理、儲存工作,最後執行exit()中止程序執行;而_exit()則是直接執行exit()中止程序執行。下面是《嵌入式Linux應用程式開發詳解(完整版第1-12章)》兩個應用執行個體
/*exit.c*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Using exit...\n");
printf("This is the content in buffer");
exit();
}
/*exit.c*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Using exit...\n");
printf("This is the content in buffer");
_exit();
}
wait()/waitpid()
wait()和waitpid()的作用是阻塞調用wait()和waitpid()函數的程序,直到一個子程序結束或者該程序接到了一個指定的信号為止,如果該父程序沒有子程序或者他的子程序已經結束,則wait()就會立即傳回。