本文目錄
- 一、exec函數簇介紹
- 二、exec函數簇
一、exec函數簇介紹
exec 函數族的作用是根據指定的文件名找到可執行文件,并用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。
exec函數族的函數執行成功后不會返回,因為調用進程的實體,包括代碼段,數據段和堆棧等都已經被新的內容(也就是新的進程信息會替換原進程的“用戶區”的信息)取代,只留下進程ID等一些表面上的信息仍保持原樣(比如PID、PPID、進程組號等這些在內核區的PCB中的信息),頗有些神似“三十六計"中的“金蟬脫殼”。看上去還是舊的軀殼,卻已經注入了新的靈魂。只有調用失敗了,它們才會返回-1,從原程序的調用點接著往下執行。
二、exec函數簇
int execl(const char *path,const char *arg,.../* (char *) NULL */);
int execlp(const char *file,const char *arg,.../* (char *) NULL */);
int execle(const char *path,const char *arg,.../* (char *) NULL ,char * const envp[] */;int execv(const char *path,char *const argv[]);
int execvp(const char *file ,char *const argv[]);
int execvp(const char *file,char *const argv[], char *const envp[]);//前面幾個都是標準c庫的函數,下面這個是linux的函數,一般來說就最上面兩個用的最多。
int execve(const char *filename,char *const argv[],char *const envp[]);
l:list
參數地址列表,以空指針結尾。
v:vector
存有各參數地址的指針數組的地址。
p:path
按PATH環境變量指定的目錄搜索可執行文件。
e:environment
存有環境變量字符串地址的指針數組地址。
輸入man 3 exec
查看標準C庫的文檔解釋:
首先在某個文件夾下創建hello.c文件,代碼如下:
#include <stdio.h>int main() { printf("hello, world\n");return 0;
}
然后在同級文件夾下創建execl.c文件,然后通過gcc exec.c -o exec
進行編譯。
/*#include<unistd.h>int execl(const char *path, const char *arg, ...);參數:-path:需要指定的執行的文件路徑或者相對路徑的名稱比如a.out 或者/home/linux/a.out執行a.out的時候可以傳遞一些參數,所以后面都是可變參數-arg:是執行可執行文件需要的參數列表第一個參數一般沒有什么作用,為了方便,一般寫的是程序的名稱、從第二個參數開始往后,就是程序執行所需要的參數。參數最后需要以NULL結束(哨兵)。返回值:只有出錯的時候才會有返回值,返回-1,并且設置errno。如果調用成功,沒有返回值。為什么沒有返回值?因為用戶區的內容已經被替換了。
*/#include <unistd.h>
#include <stdio.h>
#include<sys/types.h>int main() {// 創建一個子進程,在子進程中執行exec函數族中的函數pid_t pid = fork();if(pid > 0) {// 父進程printf("我是父進程, pid : %d\n",getpid());sleep(1);}else if(pid == 0) {// 子進程execl("hello","hello",NULL);//也可以試著跑一下系統的shell命令,也就是ps aux查看進程的命令,ps是可執行文件,aux是參數。//execl("/bin/ps", "ps", "aux", NULL); }for(int i = 0; i < 3; i++) {printf("i = %d, pid = %d\n", i, getpid());}return 0;
}
運行./exec,會發現輸出了hello,world! 并且只有父進程在輸出for循環,子進程因為跳出實現另一個進程,不會再往下執行了。
下面的execlp
函數則是到環境變量(輸入env 即可查看環境變量,可以看到ps的環境變量是/usr/local/bin,所以下面的代碼是可以成功找到ps并且執行的。)中去找可執行文件,所以不需要路徑。
/* #include <unistd.h>int execlp(const char *file, const char *arg, ... );- 會到環境變量中查找指定的可執行文件,如果找到了就執行,找不到就執行不成功。- 參數:- file:需要執行的可執行文件的文件名a.outps- arg:是執行可執行文件所需要的參數列表第一個參數一般沒有什么作用,為了方便,一般寫的是執行的程序的名稱從第二個參數開始往后,就是程序執行所需要的的參數列表。參數最后需要以NULL結束(哨兵)- 返回值:只有當調用失敗,才會有返回值,返回-1,并且設置errno如果調用成功,沒有返回值。int execv(const char *path, char *const argv[]);argv是需要的參數的一個字符串數組char * argv[] = {"ps", "aux", NULL};execv("/bin/ps", argv);*/
#include <unistd.h>
#include <stdio.h>int main() {// 創建一個子進程,在子進程中執行exec函數族中的函數pid_t pid = fork();if(pid > 0) {// 父進程printf("i am parent process, pid : %d\n",getpid());sleep(1);}else if(pid == 0) {// 子進程execlp("ps", "ps", "aux", NULL);printf("i am child process, pid : %d\n", getpid());}for(int i = 0; i < 3; i++) {printf("i = %d, pid = %d\n", i, getpid());}return 0;
}