日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux系统编程】进程替换:exec 函数族

發(fā)布時間:2024/4/24 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux系统编程】进程替换:exec 函数族 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. exec函數(shù)族
    • 02. 參考示例
      • 2.1 execl函數(shù)示例
      • 2.2 execv函數(shù)示例
      • 2.3 execlp() 或 execvp()函數(shù)示例
      • 2.4 execle() 或 execve()函數(shù)示例
    • 03. 附錄

01. exec函數(shù)族

在 Windows 平臺下,我們可以通過雙擊運行可執(zhí)行程序,讓這個可執(zhí)行程序成為一個進程;而在 Linux 平臺,我們可以通過 ./ 運行,讓一個可執(zhí)行程序成為一個進程。

但是,如果我們本來就運行著一個程序(進程),我們?nèi)绾卧谶@個進程內(nèi)部啟動一個外部程序,由內(nèi)核將這個外部程序讀入內(nèi)存,使其執(zhí)行起來成為一個進程呢?這里我們通過 exec 函數(shù)族實現(xiàn)。

exec 函數(shù)族,顧名思義,就是一簇函數(shù),在 Linux 中,并不存在 exec() 函數(shù),exec 指的是一組函數(shù),一共有 6 個:

#include <unistd.h>extern char **environ;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 execvpe(const char *file, char *const argv[],char *const envp[]);

其中只有 execve() 是真正意義上的系統(tǒng)調(diào)用,其它都是在此基礎(chǔ)上經(jīng)過包裝的庫函數(shù)。

exec 函數(shù)族提供了六種在進程中啟動另一個程序的方法。exec 函數(shù)族的作用是根據(jù)指定的文件名或目錄名找到可執(zhí)行文件,并用它來取代調(diào)用進程的內(nèi)容,換句話說,就是在調(diào)用進程內(nèi)部執(zhí)行一個可執(zhí)行文件。

進程調(diào)用一種 exec 函數(shù)時,該進程完全由新程序替換,而新程序則從其 main 函數(shù)開始執(zhí)行。因為調(diào)用 exec 并不創(chuàng)建新進程,所以前后的進程 ID (當然還有父進程號、進程組號、當前工作目錄……)并未改變。exec 只是用另一個新程序替換了當前進程的正文、數(shù)據(jù)、堆和棧段(進程替換)。

exec 函數(shù)族的 6 個函數(shù)看起來似乎很復雜,但實際上無論是作用還是用法都非常相似,只有很微小的差別。

l(list):參數(shù)地址列表,以空指針結(jié)尾。

v(vector):存有各參數(shù)地址的指針數(shù)組的地址。

p(path):按 PATH 環(huán)境變量指定的目錄搜索可執(zhí)行文件。

e(environment):存有環(huán)境變量字符串地址的指針數(shù)組的地址。

exec 函數(shù)族裝入并運行可執(zhí)行程序 path/file,并將參數(shù) arg0 ( arg1, arg2, argv[], envp[] ) 傳遞給此程序。

exec 函數(shù)族與一般的函數(shù)不同,exec 函數(shù)族中的函數(shù)執(zhí)行成功后不會返回,而且,exec 函數(shù)族下面的代碼執(zhí)行不到。只有調(diào)用失敗了,它們才會返回 -1,失敗后從原程序的調(diào)用點接著往下執(zhí)行。

02. 參考示例

2.1 execl函數(shù)示例

#include <stdio.h> #include <unistd.h>int main(int argc, char *argv[]) {printf("before exec\n");/* /bin/ls:外部程序,這里是/bin目錄的 ls 可執(zhí)行程序,必須帶上路徑(相對或絕對)ls:沒有意義,如果需要給這個外部程序傳參,這里必須要寫上字符串,至于字符串內(nèi)容任意-a,-l,-h:給外部程序 ls 傳的參數(shù)NULL:這個必須寫上,代表給外部程序 ls 傳參結(jié)束*/execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);// 如果 execl() 執(zhí)行成功,下面執(zhí)行不到,因為當前進程已經(jīng)被執(zhí)行的 ls 替換了perror("execl");printf("after exec\n");return 0; }

執(zhí)行結(jié)果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out before exec總用量 23K drwxrwxrwx 1 root root 4.0K 11月 5 15:38 . drwxrwxrwx 1 root root 4.0K 11月 4 18:05 .. -rwxrwxrwx 1 root root 576 11月 5 15:38 1.c -rwxrwxrwx 1 root root 704 11月 5 13:42 1.c.bak drwxrwxrwx 1 root root 4.0K 11月 3 20:46 4sys -rwxrwxrwx 1 root root 8.2K 11月 5 15:38 a.out deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.2 execv函數(shù)示例

execv() 和 execl() 的用法基本是一樣的,無非將列表傳參,改為用指針數(shù)組。

#include <stdio.h> #include <unistd.h>int main(int argc, char *argv[]) {// execv() 和 execl() 的用法基本是一樣的,無非將列表傳參,改為用指針數(shù)組// execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);/* 指針數(shù)組ls:沒有意義,如果需要給這個外部程序傳參,這里必須要寫上字符串,至于字符串內(nèi)容任意-a,-l,-h:給外部程序 ls 傳的參數(shù)NULL:這個必須寫上,代表給外部程序 ls 傳參結(jié)束*/char *arg[]={"ls", "-a", "-l", "-h", NULL};// /bin/ls:外部程序,這里是/bin目錄的 ls 可執(zhí)行程序,必須帶上路徑(相對或絕對)// arg: 上面定義的指針數(shù)組地址execv("/bin/ls", arg);perror("execv");return 0; }

測試結(jié)果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out 總用量 23K drwxrwxrwx 1 root root 4.0K 11月 5 15:40 . drwxrwxrwx 1 root root 4.0K 11月 4 18:05 .. -rwxrwxrwx 1 root root 643 11月 5 15:40 1.c -rwxrwxrwx 1 root root 576 11月 5 15:38 1.c.bak drwxrwxrwx 1 root root 4.0K 11月 3 20:46 4sys -rwxrwxrwx 1 root root 8.2K 11月 5 15:40 a.out deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.3 execlp() 或 execvp()函數(shù)示例

execlp() 和 execl() 的區(qū)別在于,execlp() 指定的可執(zhí)行程序可以不帶路徑名,如果不帶路徑名的話,會在環(huán)境變量 PATH指定的目錄里尋找這個可執(zhí)行程序,而 execl() 指定的可執(zhí)行程序,必須帶上路徑名。

#include <stdio.h> #include <unistd.h>int main(int argc, char *argv[]) {// 第一個參數(shù) "ls",沒有帶路徑名,在環(huán)境變量 PATH 里尋找這個可執(zhí)行程序// 其它參數(shù)用法和 execl() 一樣execlp("ls", "ls", "-a", "-l", "-h", NULL);/*char *arg[]={"ls", "-a", "-l", "-h", NULL};execvp("ls", arg);*/perror("execlp");return 0; }

執(zhí)行結(jié)果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out 總用量 22K drwxrwxrwx 1 root root 4.0K 115 15:42 . drwxrwxrwx 1 root root 4.0K 114 18:05 .. -rwxrwxrwx 1 root root 354 115 15:42 1.c -rwxrwxrwx 1 root root 643 115 15:40 1.c.bak drwxrwxrwx 1 root root 4.0K 113 20:46 4sys -rwxrwxrwx 1 root root 8.2K 115 15:42 a.out deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.4 execle() 或 execve()函數(shù)示例

execle() 和 execve() 改變的是 exec 啟動的程序的環(huán)境變量(只會改變進程的環(huán)境變量,不會影響系統(tǒng)的環(huán)境變量),其他四個函數(shù)啟動的程序則使用默認系統(tǒng)環(huán)境變量。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> // getenv()int main(int argc, char *argv[]) {// getenv() 獲取指定環(huán)境變量的值printf("before exec:USER=%s, HOME=%s\n", getenv("USER"), getenv("HOME"));// 指針數(shù)據(jù)char *env[]={"USER=TEST", "HOME=/tmp", NULL};/* ./test:外部程序,當前路徑的 test 程序,通過 gcc test.c -o test 編譯test:這里沒有意義NULL:給 test 程序傳參結(jié)束env:改變 test 程序的環(huán)境變量,正確來說,讓 test 程序只保留 env 的環(huán)境變量*/execle("./test", "test", NULL, env);/*char *arg[]={"test", NULL}; execve("./test", arg, env); */perror("execle");return 0; }

外部程序,test.c 示例代碼:

#include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(int argc, char *argv[]) {printf("\nin the test fun, after exec: \n");printf("USER=%s\n", getenv("USER"));printf("HOME=%s\n", getenv("HOME"));return 0; }

03. 附錄

3.1 參考博客:【Linux系統(tǒng)編程】進程替換:exec 函數(shù)族

總結(jié)

以上是生活随笔為你收集整理的【Linux系统编程】进程替换:exec 函数族的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。