linux子进程¶
Linux的exec(3)是一系列函数。之前总是稀里糊涂地用,这次搞清楚了。
#include <unistd.h>
extern char **environ;
int execl(const char *pathname, const char *arg, ...
/*, (char *) NULL */);
int execlp(const char *file, const char *arg, ...
/*, (char *) NULL */);
int execle(const char *pathname, const char *arg, ...
/*, (char *) NULL, char *const envp[] */);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
规律¶
这6个函数可以分为两组'execl组'和'execv组'。 后缀p表示从$PATH中查找程序, 后缀e表示最后一个参数是数组,里面是环境变量。
验证¶
这里通过c语言和python调用命令cat hello.txt
, 验证每个函数。
#include <unistd.h>
int main(){
int pid=-1;
pid=fork();
if(pid == 0)
execl("/usr/bin/cat", "cat", "hello-execl.txt", NULL);
pid=fork();
if(pid == 0)
execlp("cat", "cat", "hello-execlp.txt", NULL);
pid=fork();
if(pid == 0)
execle("/usr/bin/cat", "cat", "hello-execle.txt", NULL, (char*[]){NULL});
pid=fork();
if(pid == 0)
execv("/usr/bin/cat", (char*[]){"cat", "hello-execv.txt", NULL});
pid=fork();
if(pid == 0)
execvp("cat", (char*[]){"cat", "hello-execvp.txt", NULL});
pid=fork();
if(pid == 0)
execve("/usr/bin/cat", (char*[]){"cat", "hello-execve.txt", NULL}, (char*[]){NULL});
}
grep -n 10 "target" file
命令, 调用方法是
execlp("grep", "grep", "-n", "10", "target", "file", NULL);
使用环境变量,要用sh来拓展ENV1符号
execle("/usr/bin/sh", "sh","-c" ,"echo $ENV1", NULL, (char*[]){"ENV1=HELLO", NULL});
python 的os库的方法更全,且不需要带NULL
>>> [method for method in dir(os) if method.startswith("exec")]
['execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe']
实现cat hello.txt
import os
os.execlp("cat", "cat", "hello.txt")
使用环境变量, 同样要用sh来拓展ENV1符号
import os
env = os.environ.copy()
env["ENV1"]="hello"
os.execlpe("sh", "sh", "-c", "echo $ENV1", env)
实用替代方法¶
exec族的函数都会替换当前进程的堆栈,所以需要用fork生成新的进程。更方便的方法是在c中用system, python中用subprocess