Linux 子进程创建

2019-03-22 language c/cpp

进程执行

Linux 上将进程创建和新进程加载分开,分别通过 fork()execNN() 执行,其中后者包含了一组可用的函数,包括了 execlexeclpexecleexecvexecvp

创建了一个进程后,再将子进程替换成新的进程,其声明如下:

#include <unistd.h>

extern char **environ;

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[]);

其中,path 表示要启动程序的名称包括路径名;arg 表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且 arg 必须以 NULL 结束。

注意,上述 exec 系列函数底层都是通过 execve() 系统调用实现。注意,如果需要通过 LD_PRELOAD 捕获进程调用,那么仍然需要其它执行的实现。

#include <unistd.h>

int execve(const char *filename, char *const argv[], char *const envp[]);

其中各个函数的区别如下。

1. 带 l 的 exec 函数

包括了 execl、execlp、execle,表示后边的参数以可变参数的形式给出,且都以一个空指针结束。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    printf("entering main process---\n");
    execl("/bin/ls","ls","-l",NULL);
    printf("exiting main process ----\n");
    return 0;
}

利用 execl 将当前进程 main 替换掉,所有最后那条打印语句不会输出。

2. 带 p 的 exec 函数

也就是 execlp、execvp,表示第一个参数 path 不用输入完整路径,只有给出命令名即可,它会在环境变量 PATH 当中查找命令。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    printf("entering main process---\n");
    execlp("ls","ls","-l",NULL);
    printf("exiting main process ----\n");
    return 0;
}

3. 不带 l 的 exec 函数

包括了 execv、execvp 表示命令所需的参数以 char *arg[] 形式给出,且 arg 最后一个元素必须是 NULL 。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    printf("entering main process---\n");
    char *argv[] = {"ls","-l",NULL};
    execvp("ls", argv);
    printf("exiting main process ----\n");
    return 0;
}

4. 带 e 的 exec 函数

包括了 execle ,可以将环境变量传递给需要替换的进程,再上述的声明中,有一个指针数组的变量 extern char **environ;,每个指针指向的字符串为 KV 结构。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    char *const envp[] = {"AA=11", "BB=22", NULL};
    printf("entering main process---\n");
    execle("/bin/bash", "bash", "-c", "echo $AA", NULL, envp);
    printf("exiting main process ----\n");
    return 0;
}