Linux系統程式設計之程式替換:exec 函式族
在
Windows 平臺下,我們可以透過雙擊執行可執行程式,讓這個可執行程式成為一個程式;而在 Linux 平臺,我們可以透過 ./ 執行,讓一個可執行程式成為一個程式。
但是,如果我們本來就執行著一個程式(程式),我們如何在這個程式內部啟動一個外部程式,由核心將這個外部程式讀入記憶體,使其執行起來成為一個程式呢?這裡我們透過 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 函式族提供了六種在程式中啟動另一個程式的方法。exec 函式族的作用是根據指定的檔名或目錄名找到可執行檔案,並用它來取代呼叫程式的內容,換句話說,就是在呼叫程式內部執行一個可執行檔案。
程式呼叫一種 exec 函式時,該程式完全由新程式替換,而新程式則從其 main 函式開始執行。因為呼叫 exec 並不建立新程式,所以前後的程式 ID (當然還有父程式號、程式組號、當前工作目錄……)並未改變。exec 只是用另一個新程式替換了當前程式的正文、資料、堆和棧段(程式替換)。
exec 函式族的 6 個函式看起來似乎很複雜,但實際上無論是作用還是用法都非常相似,只有很微小的差別。
l(list):引數地址列表,以空指標結尾。
v(vector):存有各引數地址的指標陣列的地址。
p(path):按 PATH 環境變數指定的目錄搜尋可執行檔案。
e(environment):存有環境變數字串地址的指標陣列的地址。
exec 函式族裝入並執行可執行程式 path/file,並將引數 arg0( arg1, arg2, argv[], envp[] ) 傳遞給此程式。
exec 函式族與一般的函式不同,exec 函式族中的函式執行成功後不會返回,而且,exec 函式族下面的程式碼執行不到。只有呼叫失敗了,它們才會返回 -1,失敗後從原程式的呼叫點接著往下執行。
excel程式碼
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("before exec\n\n");
/* /bin/ls:外部程式,這裡是/bin目錄的 ls 可執行程式,必須帶上路徑(相對或絕對)
ls:沒有意義,如果需要給這個外部程式傳參,這裡必須要寫上字串,至於字串內容任意
-a,-l,-h:給外部程式 ls 傳的引數
NULL:這個必須寫上,代表給外部程式 ls 傳參結束
*/
execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);
// 如果 execl() 執行成功,下面執行不到,因為當前程式已經被執行的 ls 替換了
perror("execl");
printf("after exec\n\n");
return 0;
}
執行結果:
execv()示例程式碼:
execv() 和 execl() 的用法基本是一樣的,無非將列表傳參,改為用指標陣列。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
// execv() 和 execl() 的用法基本是一樣的,無非將列表傳參,改為用指標陣列
// execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);
/* 指標陣列
ls:沒有意義,如果需要給這個外部程式傳參,這裡必須要寫上字串,至於字串內容任意
-a,-l,-h:給外部程式 ls 傳的引數
NULL:這個必須寫上,代表給外部程式 ls 傳參結束
*/
char *arg[]={"ls", "-a", "-l", "-h", NULL};
// /bin/ls:外部程式,這裡是/bin目錄的 ls 可執行程式,必須帶上路徑(相對或絕對)
// arg: 上面定義的指標陣列地址
execv("/bin/ls", arg);
perror("execv");
return 0;
}
execlp() 或 execvp() 示例程式碼:
execlp() 和 execl() 的區別在於,execlp() 指定的可執行程式可以不帶路徑名,如果不帶路徑名的話,會在環境變數 PATH指定的目錄裡尋找這個可執行程式,而 execl() 指定的可執行程式,必須帶上路徑名。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
// 第一個引數 "ls",沒有帶路徑名,在環境變數 PATH 裡尋找這個可執行程式
// 其它引數用法和 execl() 一樣
execlp("ls", "ls", "-a", "-l", "-h", NULL);
/*
char *arg[]={"ls", "-a", "-l", "-h", NULL};
execvp("ls", arg);
*/
perror("execlp");
return 0;
}
execle() 或 execve() 示例程式碼:
execle() 和 execve() 改變的是 exec 啟動的程式的環境變數(只會改變程式的環境變數,不會影響系統的環境變數),其他四個函式啟動的程式則使用預設系統環境變數。
execle()示例程式碼:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // getenv()
int main(int argc, char *argv[])
{
// getenv() 獲取指定環境變數的值
printf("before exec:USER=%s, HOME=%s\n", getenv("USER"), getenv("HOME"));
// 指標資料
char *env[]={"USER=EDU", "HOME=/tmp", NULL};
/* ./edu:外部程式,當前路徑的 edu 程式,透過 gcc edu.c -o edu 編譯
edu:這裡沒有意義
NULL:給 edu 程式傳參結束
env:改變 edu 程式的環境變數,正確來說,讓 edu 程式只保留 env 的環境變數
*/
execle("./edu", "edu", NULL, env);
/*
char *arg[]={"edu", NULL};
execve("./edu", arg, env);
*/
perror("execle");
return 0;
}
外部程式,edu.c 示例程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("\nin the edu fun, after exec: \n");
printf("USER=%s\n", getenv("USER"));
printf("HOME=%s\n", getenv("HOME"));
return 0;
}
執行結果:
最後:
關注回覆“物聯網”即可獲取物聯網全套影片教程
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914734/viewspace-2656127/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux系統程式設計之程式控制(程式建立、終止、等待及替換)Linux程式設計
- Linux系統程式設計之程式介紹Linux程式設計
- Linux系統程式設計——特殊程式之孤兒程式Linux程式設計
- Linux系統程式設計之匿名管道Linux程式設計
- linux系統時間程式設計(9) 計算程式片段執行時間clock函式Linux程式設計函式
- Linux系統程式設計之檔案IOLinux程式設計
- Linux作業系統之Shell程式設計Linux作業系統程式設計
- PHP exec system passthru系統函式PHP函式
- 【Perl程式設計-6】正規表示式--替換+轉化程式設計
- Linux——程式建立、程式終止、程式等待、程式程式替換Linux
- 函式程式設計函式程式設計
- Linux系統程式設計之程式間通訊方式:管道(二)Linux程式設計
- Linux系統程式設計之程式間通訊方式:管道(一)Linux程式設計
- 【Linux網路程式設計】Socket Api函式Linux程式設計API函式
- 物聯網教程Linux系統程式設計——特殊程式之殭屍程式Linux程式設計
- 物聯網教程Linux系統程式設計——特殊程式之守護程式Linux程式設計
- 分散式系統程式設計分散式程式設計
- 【Linux】Linux系統程式設計入門Linux程式設計
- 設計原則之【裡式替換原則】
- JavaScript函數語言程式設計之pointfree與宣告式程式設計JavaScript函數程式設計
- Linux系統程式設計—共享記憶體之mmapLinux程式設計記憶體
- Linux系統程式設計之程式間通訊方式:命名管道(二)Linux程式設計
- Linux系統程式設計之程式間通訊方式:命名管道(一)Linux程式設計
- Linux系統程式設計基礎Linux程式設計
- Linux系統程式設計入門Linux程式設計
- Linux系統程式設計—有名管道Linux程式設計
- 好程式設計師Python培訓分享函數語言程式設計之匿名函式程式設計師Python函數函式
- linux系統時間程式設計(6) 日曆時間tm轉字串strftime函式Linux程式設計字串函式
- 【Linux系統程式設計】Linux訊號列表Linux程式設計
- Linux系統程式設計【4】——檔案系統Linux程式設計
- 物聯網學習教程—Linux系統程式設計之程式介紹Linux程式設計
- Linux系統程式設計之程式間通訊方式:訊息佇列Linux程式設計佇列
- python程式設計之slice與indices函式用法Python程式設計函式
- 使用反應式程式設計替換Java自動資源管理 - Arvind程式設計Java
- Linux系統程式設計—訊號捕捉Linux程式設計
- Linux系統程式設計-檔案IOLinux程式設計
- Linux系統程式設計:訊號捕捉Linux程式設計
- Linux系統程式設計:mmap使用技巧Linux程式設計