进程体替换(exec函数族)与调用命令行(system)

一、进程体替换(exec函数族)

  使用函数fork()创建新的子进程后,子进程往往需要调用函数exec()以执行另一个程序。当进程调用函数exec()时,该进程执行的程序完全替换为新程序,而新程序则从其函数main()开始执行。

  与 fork 或 vfork 函数不同,exec 函数不是创建调用进程的子进程,而是创建一个新的进程取代调用进程自身。新进程会用自己的全部地址空间,覆盖调用进程的地址空间,但进程的 PID 保持不变。exec 只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆段和栈段

  exec函数族的作用:根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

#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[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int fexecve(int fd, char *const argv[], char *const envp[]);
// 7 个函数返回值:若出错,返回 -1;若成功,不返回

1、execl函数

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
若出错,返回 -1, 若成功,不返回

  execl()其中后缀 “l” 代表 list 也就是参数列表的意思,第一参数 path 字符指针所指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]… 最后一个参数须用空指针NULL作结束

#include <unistd.h>
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    cout << "hello\n";
    // 去磁盘中加载另外一段程序,替换掉当前的正文段、数据段等。
    // 11 22 是传给./test(可执行程序)的参数。
    execl("test", "./test", "11", "22", NULL);  
    cout << "world\n";
    return 0;
}

2、execlp函数

#include <unistd.h>
int execlp(const char *file, const char *arg, ...);
若出错,返回 -1, 若成功,不返回

  execlp()会从 PATH 环境变量所指的目录中查找符合参数 file 的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。

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

int main()
{
    pid_t pid;
    pid = fork();
    if (pid == 0) // 子进程启动火狐,打开一个网址
    {
     	// NULL表示参数结束
        execlp("/usr/bin/firefox", "firefox", "www.baidu.com", NULL);
    }
    else if (pid > 0)
    {
        while (1)
        {
            printf("I am parent\n");
            sleep(1);
        }
    }
    else
    {
        perror("fork");
        exit(1);
    }
    return 0;
}

  当指定 file 作为参数时,如果 file 中包含 /,则就将其视为路径名。否则就按 PATH 环境变量,在它所指定的各目录中搜索可执行文件。这也就是 execlp 和 execl 的区别了。

二、调用命令行(system)

#include <stdlib.h>
int system(const char *command);

1、函数功能与参数解析

  linux系统中可以使用函数system()函数调用shell命令。
  system()函数执行 command 参数表示的命令行,并返回命令进程的终止状态。若 command 参数是一个空指针 (NULL),则仅当命令处理程序可用时,system 返回非 0 值,这一特征可以确定在一个给定的操作系统上是否支持 system 函数。在 UNIX 中,system 总是可用的。

2、函数详解

  因为 system 在其实现中调用了 fork、exec 和 waitpid,因此有 3 种返回值。

  • fork 失败或者 waitpid 返回除 EINTR 之外的出错,则 system 返回 -1,并且设置 errno以指示错误类型。
  • 如果 exec 失败(表示不能执行 shell),则其返回值如同 shell 执行了 exit (127) 一样。
  • 如果所有 3 个函数(fork、exec 和 waitpid)都成功,那么 system 的返回值是 shell 的终止状态,其格式已在 waitpid 中说明。
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    int status;
    // 若 command 参数是一个空指针 (NULL),
    // 则仅当命令处理程序可用时,system 返回非 0 值。
    if ((status = system(NULL)) == -1)
        perror("system"), exit(1);
    // 通过 if (!status) 判断系统是否支持 system 函数。
    if (!status)
        printf("shell 不可用\n");
    else
    {
        // 如果成功,那么 system 的返回值是 shell 的终止状态
        // 如果将shell命令错误则,终止状态为 exit(127)
        if ((status = system("ls -l")) == -1) 
            perror("system"), exit(1);
        // WEXITSTATUS (status) 得到 exit或_exit 参数、return返回值。
        printf("WEXITSTATUS (status) = %d\n", WEXITSTATUS(status));
    }
    return 0;
}

3、system与exec的区别

  使用 system 函数而不直接使用 fork+exec 的好处是,syetem函数针对各种错误和信号都做了必要的处理,而且 system 是标准库函数,可跨平台使用。

【与exec的区别】:

1. system()和exec()都可以执行进程外的命令,system是在原进程上开辟了一个新的进程,但是exec是用新进程(命令)覆盖了原有的进程

2. system()和exec()都有能产生返回值,system的返回值并不影响原有进程,但是exec的返回值影响了原进程

参考:https://blog.csdn.net/qq_29350001/article/details/70837744

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: LabVIEW是一款用于进行数据采集、控制与分析的图形化编程环境。LabVIEW允许用户通过拖拽与连接图形化符号进行程序设计,以方便地实现各种功能。 对于调用命令行管理员,LabVIEW提供了相应的功能以提高用户的灵活性和便利性。用户可以通过LabVIEW调用命令行管理员,以执行需要管理员权限的操作,比如安装软件、修改系统文件等。下面是一些常见的操作步骤: 1. 打开LabVIEW编程环境,创建一个新的VI(Virtual Instrument)。 2. 在Block Diagram中,通过搜索功能找到"调用命令行"(Call Command Line)的函数模块,并将其拖拽到Block Diagram上。 3. 点击函数模块,可以看到相应的函数配置面板,在这里可以设置命令行参数。 4. 在函数配置面板上,设置命令行参数,如要执行的命令、需要管理员权限等。 5. 将命令行输出连接到适当的输出控件上,以便在界面上显示命令行的输出结果。 6. 运行VI,就可以触发命令行并执行相应的操作了。 LabVIEW的这种调用命令行管理员的功能,既方便又灵活,提供了更多操作系统级别的控制与处理能力。同时,用户还可以通过结合其他LabVIEW的功能,如图表控件、数据存储等,进一步进行数据的分析和展示。总的来说,LabVIEW的调用命令行管理员功能可以为用户提供更多的操作与控制能力,并提高编程的便利性和效率。 ### 回答2: 在LabVIEW中调用命令行管理员权限可以通过以下步骤实现: 1. 首先,打开LabVIEW,创建一个新的VI(虚拟仪器)。 2. 在Block Diagram(块图)中,使用搜索栏搜索并找到“System Exec(系统执行)”节点。 3. 将“System Exec”节点拖放至Block Diagram中。 4. 在“System Exec”节点上,右键单击并选择“Open VI(打开VI)”。 5. 在“Open VI”对话框中,选择命令行可执行文件的路径。在这个路径后面添加以下内容以获取管理员权限: "cmd.exe /k <你的命令>" 例如,要运行ipconfig命令,管理员权限,路径应该为: "cmd.exe /k ipconfig" 6. 单击“Open”按钮以保存更改并返回到主窗口。 7. 连接“System Exec”节点的输出终端至您希望将结果存储的变量或显示器。 8. 单击“Run(运行)”按钮以执行命令行命令,并在结果上查看管理员权限。 9. 如果需要更多的命令行操作,可以通过创建适当的命令字符串并将其传递给“System Exec”节点来实现。 通过以上步骤,您就可以在LabVIEW中调用命令行管理员权限,并执行您所需的命令。请注意在执行任何管理员命令之前确保您具有适当的管理员权限。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~青萍之末~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值