exec函數可以把當前進程替換為一個新進程,新進程由path或file指定,可以使用exec函數將程式的執行從一個程式切換到另一個程式,新的程式啟動後,原來的程式就不再運行。
#include <unistd.h>
char **environ;
int execl(const char *path, const char *arg0, ..., (char *)0);
int execlp(const char *file, const char *arg0, ..., (char *)0);
int execle(const char *path, const char *arg0, ..., (char *)0, 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[]);
這些函數分為兩大類,execl,execlp和execle的參數個數是可變的,參數以一個null 指標結束。
execv和execvp的第二個參數是字串數組,兩者在新程式啟動時都會把在argv數組中給定的參數傳遞給main函數。
上面的5個函數通常都是由execve函數實現。
以字母p結尾的函數通過搜尋PATH環境變數來尋找新程式的可執行檔的路徑,如果可執行檔不在PATH定義的路徑中,則需要把包括目錄在內的使用絕對路徑的檔案名稱作為參數傳遞給函數。
函數execle和execve可以通過參數envp傳遞字串數組作為新程式的環境變數。
下面是一個樣本程式:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Running ls with execl/n");
execl("/bin/ls", "ls", "-l", NULL);
printf("done./n");
exit(0);
}
儲存為pexec.c
編譯:gcc -o pexec pexec.c
然後運行:./pexec
在筆者電腦上得到如下結果:
Running ps with execl
總計 36
-rwxr-xr-x 1 deng deng 8371 2010-08-13 21:06 pexec
-rw-r--r-- 1 deng deng 177 2010-08-13 20:11 pexec.c
-rw-r--r-- 1 deng deng 170 2010-08-13 07:54 pexec.c~
-rwxr-xr-x 1 deng deng 8374 2010-08-13 07:35 system1
-rw-r--r-- 1 deng deng 143 2010-08-13 07:35 system1.c
以上是正常的ls命令的輸出結果,但字串done卻根本沒出現,說明當前程式已經被execl函數替換掉了。
另一個樣本:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Running ps with execlp/n");
execlp("ps","ps","ax",NULL);
printf("done./n");
exit(0);
}
該樣本程式用於列印當前的進程,儲存為pexecp.c
編譯:gcc -o pexecp pexecp.c
運行:./pexecp
筆者電腦啟動並執行結果如下:
Running ps with execlp
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
2 ? S< 0:00 [kthreadd]
3 ? S< 0:00 [migration/0]
4 ? S< 0:00 [ksoftirqd/0]
5 ? S< 0:00 [watchdog/0]
6 ? S< 0:00 [migration/1]
7 ? S< 0:00 [ksoftirqd/1]
8 ? S< 0:00 [watchdog/1]
9 ? S< 0:00 [events/0]
10 ? S< 0:00 [events/1]
11 ? S< 0:00 [cpuset]
12 ? S< 0:00 [khelper]
………………中間還有很多,在此省略
4698 ? Sl 2:48 /usr/lib/firefox-3.6.8/plugin-container /usr/lib/flas
4787 ? S 0:01 gedit /home/deng/workspace/linux_test/chapter11/pexec
4975 ? S 0:00 /usr/lib/gvfs/gvfsd-computer --spawner :1.9 /org/gtk/
4997 ? Rl 0:00 gnome-terminal
4998 ? S 0:00 gnome-pty-helper
4999 pts/0 Ss 0:00 bash
5106 pts/0 R+ 0:00 ps ax
在這裡可以看到我們在程式裡面用execlp()函數啟動的進程ps ax,它相當於shell下的命令ps ax,效果相同
但這裡我們依然沒有看到最後一句done沒有被列印出來
一般情況下,exec函數是不會返回的,除非發生了錯誤。出現錯誤時,exec函數會返回-1,並且會設定錯誤變數errno.