Linux进程编程(8)exce族函数的使用

Linux进程编程(8)exce族函数的使用


前言

exec 系列函数用于在当前进程上下文中加载并执行一个新的程序。换句话说,exec 会替换当前进程的代码、数据段和堆栈等信息为新程序的相应部分,然后执行新程序。这个过程中,进程的 PID 不会改变,但是几乎所有其他的内容都会被新程序替换。


一、exce族函数是什么?

exec 系列函数有多个变体,如 execl(), execp(), execle(), execv(), execvp()execve() 等。这些变体主要是在传递命令行参数和环境变量方面有所不同。

常见的 exec 函数:

  1. execl(const char *path, const char *arg0, ..., const char *argN, NULL)
    使用逗号分隔的参数列表,并且以 NULL 终止。

  2. execv(const char *path, char *const argv[])
    使用字符串数组来传递参数。

  3. execle(const char *path, const char *arg0, ..., const char *argN, NULL, char *const envp[])
    execl 类似,但允许传递一个环境变量数组。

  4. execve(const char *path, char *const argv[], char *const envp[])
    允许传递一个参数数组和一个环境变量数组。

  5. execpexecvp
    这两个函数会在系统 PATH 环境变量所指定的目录中查找可执行文件。

二、实现代码

示例:

1.下面的代码使用 execl() 在子进程中执行 ls -l 命令:

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

int main() {
    pid_t pid = fork();  // 创建子进程

    // fork 失败
    if (pid < 0) {
        perror("fork failed");
        return 1;
    }

    // 子进程
    if (pid == 0) {
        // 使用 execl 执行 ls -l 命令
        // 注意:这里的第二个和第三个参数是命令的名字和参数,最后一个参数必须是 NULL
        execl("/bin/ls", "ls", "-l", NULL);

        // 如果 execl 调用失败,则会执行以下 perror
        perror("execl failed");
        return 1;
    }

    // 父进程
    // 父进程可以继续执行其他任务,或等待子进程完成
    return 0;
}

2.使用 execvp() 执行 ls -l


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

int main() {
    pid_t pid = fork();  // 创建子进程

    // fork 失败
    if (pid < 0) {
        perror("fork failed");
        return 1;
    }

    // 子进程
    if (pid == 0) {
        // 参数列表,第一个是命令,最后一个必须是 NULL
        char *args[] = {"ls", "-l", NULL};
        
        // 使用 execvp 执行 ls -l 命令
        // 这里使用的是 PATH 环境变量中的 ls 命令
        execvp("ls", args);

        // 如果 execvp 调用失败,则会执行以下 perror
        perror("execvp failed");
        return 1;
    }

    // 父进程
    // 父进程可以继续执行其他任务,或等待子进程完成
    return 0;
}

3.使用 execle() 执行 env 命令

execle() 允许你传递一个新的环境变量数组给新程序。下面的代码在子进程中执行 env 命令,这个命令会打印出环境变量。

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

int main() {
    pid_t pid = fork(); // 创建子进程

    if (pid < 0) {
        perror("fork failed");
        return 1;
    }

    if (pid == 0) {
        // 新的环境变量列表
        char *newenv[] = {"MY_VAR=hello", NULL};

        // 使用 execle 执行 env 命令
        execle("/usr/bin/env", "env", NULL, newenv);

        // 如果 execle 调用失败,则会执行以下 perror
        perror("execle failed");
        return 1;
    }

    // 父进程可以继续执行其他任务,或等待子进程完成
    return 0;
}

4.使用 execv() 执行 ls -l

这个例子与使用 execvp() 类似,但它不会搜索 PATH 环境变量来查找 ls 命令。

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

int main() {
    pid_t pid = fork();  // 创建子进程

    if (pid < 0) {
        perror("fork failed");
        return 1;
    }

    if (pid == 0) {
        // 参数列表,第一个是命令,最后一个必须是 NULL
        char *args[] = {"ls", "-l", NULL};

        // 使用 execv 执行 ls -l 命令
        execv("/bin/ls", args);

        // 如果 execv 调用失败,则会执行以下 perror
        perror("execv failed");
        return 1;
    }

    // 父进程可以继续执行其他任务,或等待子进程完成
    return 0;
}

总结

这些示例覆盖了 exec 系列函数中的主要变体,每种变体都有其特定用途和优势。例如,execl 和 execle 允许你直接在函数调用中指定参数,而 execv 和 execvp 允许你通过数组传递参数,这在参数数量未知时非常有用。而 execle 和 execve 允许你指定新程序的环境变量。希望这些示例和注释能够帮助你理解这些函数的不同用途。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值