一、linuxexec函數族
在Linux系統開發中,exec()函數族用於將當前進程的代碼替換為新的代碼,並且將原有進程的執行上下文傳遞給新的代碼。
exec()函數族中一共包含六個函數:
#include <unistd.h> int execl(const char *pathname, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *pathname, const char *arg, ..., char * const envp[]); int execv(const char *pathname, char *const argv[]); int execvp(const char *file, char *const argv[]); int execve(const char *filename, char *const argv[], char *const envp[]);
這些函數實現的功能類似,但參數不同且各自具有特殊的用途。下面分別進行詳細的介紹。
二、linux exec命令
除了exec()函數族外,Linux還提供了與之對應的命令:execl、execlp、execle、execv、execvp、execve。用戶可以直接在終端上使用這些命令來替換進程代碼。
Linux exec命令的語法格式如下:
execl(pathname, arg0, arg1, ..., argn, (char *)0); execlp(file, arg0, arg1, ..., argn, (char *)0); execle(pathname, arg0, arg1, ..., argn, envp, (char *)0); execv(pathname, argv); execvp(file, argv); execve(filename, argv, envp);
其中,pathname和file表示要執行的程序路徑;arg0到argn表示程序的命令行參數;envp表示程序的環境變數,是一個字元串數組。
需要注意的是,參數列表中必須以NULL結尾,否則會出現未知錯誤。
三、linux文件描述符
進程在Linux中與外部環境進行通信,都是通過文件描述符進行的。每個進程都有自己的一組文件描述符,其值是非負整數。
文件描述符可以是以下三種類型之一:
- 標準輸入 STDIN_FILENO (值為0)
- 標準輸出 STDOUT_FILENO (值為1)
- 標準錯誤 STDERR_FILENO (值為2)
除了標準輸入、輸出、錯誤之外,每個進程還有其他的文件描述符。這些描述符可以表示打開的文件、管道、網路套接字等資源。
四、與linuxexec相關的系統調用
1. pipe()
pipe()系統調用用於創建父子進程共享的管道。管道實際上是一組文件描述符,它們連接兩個進程的輸出和輸入。
#include <unistd.h> int pipe(int fd[2]);
參數fd是一個二元數組,調用成功後fd[0]表示管道的讀端文件描述符,fd[1]表示管道的寫端文件描述符。需要注意的是,fd[0]和fd[1]不能交換順序。
2. fork()
fork()系統調用用於創建一個新進程,新進程與原始進程相同,但具有不同的PID、內存空間和其他狀態。
#include <unistd.h> pid_t fork(void);
調用fork()後,將會返回兩次,一次在父進程中,一次在子進程中。父進程將返回子進程的PID,子進程將返回0。
3. dup2()
dup2()系統調用用於複製文件描述符,並將其賦值給指定的文件描述符。
#include <unistd.h> int dup2(int oldfd, int newfd);
參數oldfd是要複製的文件描述符,newfd是將要賦予複製後的文件描述符。
4. wait()
wait()系統調用用於等待任意子進程退出,並返回該子進程的PID和退出狀態。
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status);
如果沒有任何子進程退出,則當前進程將被掛起,直到有子進程退出。
五、完整代碼示例
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char **argv) { int fd[2], status; pid_t pid; if (pipe(fd) == -1) { perror("pipe()"); return -1; } pid = fork(); if (pid == -1) { perror("fork()"); return -1; } else if (pid == 0) { close(fd[0]); dup2(fd[1], STDOUT_FILENO); execlp("ls", "ls", "/", (char *)0); close(fd[1]); exit(0); } close(fd[1]); dup2(fd[0], STDIN_FILENO); execlp("grep", "grep", "bin", (char *)0); close(fd[0]); wait(&status); return 0; }
代碼說明:
以上代碼實現了將ls命令的結果通過管道傳遞給grep命令進行過濾的功能。具體實現步驟如下:
- 創建一個管道,用於將ls的輸出傳遞給grep。
- 調用fork()創建一個子進程。
- 在子進程中,將標準輸出重定向到管道的寫端,調用execlp()執行ls命令。
- 在父進程中,將標準輸入重定向到管道的讀端,調用execlp()執行grep命令。
- 調用wait()等待子進程退出。
原創文章,作者:LDKV,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/149860.html