先來看看exec函數: shell
exec函數族 函數
fork建立子進程後執行的是和父進程相同的程序(但有可能執行不一樣的代碼分支),子進程每每要調用一種exec函數以執行另外一個程序。當進程調用一種exec函數時,該進程的用戶空間代碼和數據徹底被新程序替換,重新程序的啓動例程開始執行。調用exec並不建立新進程,因此調用exec先後該進程的id並未改變。 google
將當前進程的.text、.data替換爲所要加載的程序的.text、.data,而後讓進程重新的.text第一條指令開始執行,但進程ID不變,換核不換殼。 spa
其實有六種以exec開頭的函數,統稱exec函數: orm
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[]); it
int execv(const char *path, char *const argv[]); io
int execvp(const char *file, char *const argv[]); form
int execve(const char *path, char *const argv[], char *const envp[]);
execlp函數
加載一個進程,藉助PATH環境變量
int execlp(const char *file, const char *arg, ...); 成功:無返回;失敗:-1
參數1:要加載的程序的名字。該函數須要配合PATH環境變量來使用,當PATH中全部目錄搜索後沒有參數1則出錯返回。
該函數一般用來調用系統程序。如:ls、date、cp、cat等命令。
如你所見,exec函數實際上時一族函數:有6個。解決標題的問題這幾個均可以用,可是我使用execlp函數。
先來看看它的用法:
它的原型:int execlp(const char *file, const char *arg, …);
這是一個變參函數。第一個參數是可執行文件的名稱,能夠不用指定文件目錄,他會自動在當前的環境變量中查找,適用於使用系統可執行文件來建立一個進程這樣的場合。相信知道exec函數的人應該知道它是用來幹嗎的吧?若是不知道,請自行www.baidu.com或www.google.com。一個示例:execlp("ls", "ls", "-l", "-f", NULL); 使用程序名在PATH中搜索。用NULL做爲哨兵
因此,咱們能夠利用它在使程序執行自己的過程當中執行其餘可執行文件。查看當前進程的命令:ps aux 而後要將它輸入到文件中去,怎麼辦呢?重定向! ps aux > out.txt 可是咱們能直接在程序中這麼寫麼?答案是不能。爲何?由於>是轉義字符。(別嫌我囉嗦,大部分人基礎都不咋地,我也是。基礎好的話也不會來寫這個來增強記憶了。)因此,咱們實際上要這樣作:execlp("ps","ps","aux","\>","o_ret",NULL); o_ret是一個自定義文件描述符。
懂了嗎?可是,我要說可是!這不行!爲何?來,咱們來看看,execlp("ps","ps","aux","\>","o_ret",NULL);若是咱們是在shell環境中執行這個函數所作的事,那咱們是這樣執行的:ps aux > o_ret 請問,請問,o_ret是什麼?shell環境知道麼?他不知道!因此,命令執行失敗。
那麼怎麼辦?沒事,有辦法,知道dup2函數麼?(不能讀成dup2(er),應該是dup(to))他將一個文件描述符複製給另外一個文件描述符。你們應該知道一句話,在Linux中,一切皆文件。那麼標準輸入輸出流,標準錯誤流是否是文件?是,而且他們三一直佔用這文件描述符的前三。我不是說他們的使用頻率,我是說他們的地位,咱們用戶自定義的文件描述符最牛逼也就只能排在3號位置,前面的0,1,2是他們的天下。
若是,若是咱們用dup2函數將o_ret複製給stdout,會發生什麼?是的,原先默認輸出到屏幕上的東西都會輸出到o_ret指向的文件中去。咱們還用去重定向麼?不用,還要去使用轉義字符麼?不用。
說了這麼些,若是認真看,應該是會有一些明悟的。接下來上代碼:
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int o_ret, e_ret, c_ret;
o_ret = open("process_information.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);//建立文件,若存在,截斷;權限644
if (-1 == o_ret)
{
perror("file ");
exit(1);
}
dup2(o_ret, STDOUT_FILENO);
e_ret = execlp("ps", "ps", "aux", nullptr);
//第一個ps是讓函數去找這個可執行文件,第二個ps是argv[0]參數,這裏我是這麼理解的,函數找到ps文件後,開闢一個shell空間,而後使用後面的參數來執行。
//可參考:https://baike.baidu.com/item/execlp
if (-1 == e_ret)
{
perror("execlp() ");
//exit(1); 執行到這兒了,若是退出,打開的文件怎麼辦?
}
c_ret = close(o_ret);
if (-1 == c_ret)
{
puts("close file failure");
}
printf("c_ret = %d\n", c_ret);
printf("hello from processInformation_printf_file!\n");
return 0;
}