当前位置: 首页 > news >正文

linux的exec和system函数介绍及选择

在应用程序中有时候需要调用第三方的应用,这是常见的需求。此时可以使用linux下的exec命令或system命令达到目的。但是这两个该选择哪个呢?有什么区别?下面总结介绍下。

exec和system介绍

在Linux中,`exec`命令用于在当前进程中执行一个新的程序。它会取代当前进程的内容,并用新的程序来替换它。`exec`命令接受两个参数,第一个参数是要执行的程序的路径,第二个参数是一个字符串数组,用于传递给新程序的命令行参数。

`system`命令也用于在当前进程中执行一个新的程序,但它是通过调用shell来实现的。`system`命令接受一个字符串参数,该字符串包含要执行的命令。它会创建一个新的shell进程,并在该进程中执行指定的命令。

`exec`和`system`的主要区别在于它们的实现方式和用途。`exec`直接在当前进程中执行一个新程序,而`system`通过调用shell来执行命令。因此,`exec`更加高效,因为它避免了创建新的进程和shell的开销。另外,`exec`通常用于在当前进程中执行其他可执行程序,而`system`则更适用于执行shell命令和脚本。exec是一系列函数接口的总称,其实分为多个函数接口版本。

exec族函数:

       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 execvpe(const char *file, char *const argv[],char *const envp[]);

如何选择

在Linux中,exec和system是两个不同的命令,用于执行外部程序。

exec是一个系统调用,它可以用来执行一个新的程序,并替换当前进程的内容。它需要提供一个可执行文件的路径以及命令行参数,然后它会将当前进程替换为指定的程序。execvp命令是一个低级别的命令,它可以更好地控制执行的过程,但是它不会创建新的进程。

system是一个库函数,它可以用来执行一个命令。它接收一个字符串参数,该参数是要执行的命令,然后它会创建一个新的进程来执行该命令。system命令是一个高级别的命令,它更简单易用,但是它的控制能力较弱。 

选择使用exec还是system取决于你的需求。如果你需要更细粒度的控制可以使用exec。例如如果你需要替换当前进程的内容,或者需要在子进程中执行一些特定的操作,那么exec可能更适合。另一方面,如果你只是简单地执行一个命令,并希望获得执行结果,那么system可能更方便。

void set_gpio64_low(void)
{	system("echo 64 > /sys/class/gpio/export");system("echo out > /sys/class/gpio/gpio64/direction");system("echo 0 > /sys/class/gpio/gpio64/value");
}

`exec`命令的基本用法

#include <unistd.h>int execvp(const char *file, char *const argv[]);

要执行一个shell脚本,可以将shell解释器的路径作为第一个参数,将脚本文件的路径作为第二个参数,并将其他参数作为字符串数组传递。

下面是一个示例,演示如何使用`execvp`命令执行一个shell脚本:

#include <unistd.h>
#include <stdio.h>int main() {char *const argv[] = {"./script.sh", NULL};execvp("/bin/sh", argv);printf("execvp failed\n");return 0;
}

在上面的示例中,`./script.sh`是要执行的shell脚本的路径。`/bin/sh`是shell解释器的路径。`NULL`表示参数数组的结束。

请注意,`execvp`命令执行成功后,当前进程将被替换为新的程序,因此后续代码不会被执行。如果`execvp`命令执行失败,它将返回-1,并且可以使用`perror`函数打印错误信息。

确保在执行`execvp`命令之前,脚本文件具有执行权限。可以使用`chmod`命令为脚本文件添加执行权限。

`execvp`命令执行成功后的当前进程将被替换为新的程序,后续代码不会被执行。如果想要在`execvp`命令执行后继续执行代码,可以使用`fork`函数创建一个子进程,在子进程中调用`execvp`命令,而父进程则可以继续执行后续代码。

下面是一个示例代码:

#include <stdio.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid == 0) {// 子进程中执行新的程序char *args[] = {"ls", "-l", NULL};execvp("ls", args);} else if (pid > 0) {// 父进程中继续执行后续代码printf("This is the parent process.\n");// 可以添加其他代码} else {// fork失败printf("Fork failed.\n");return 1;}return 0;
}

在上述代码中,子进程中调用了`execvp`命令来执行`ls -l`命令,而父进程则继续执行后续代码。

如果你想在应用程序中满足条件时调用其他应用程序,可以考虑使用fork和execvp的组合。使用fork创建一个子进程,在子进程中使用execvp执行其他应用程序,这样可以避免替换当前进程,同时在父进程中可以继续执行后续代码。

system与execl的区别

system会新起一个子进程来调用要执行的命令。而exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。

int system(const char * cmdstring){pid_t pid;int status;if(cmdstring == NULL){return (1);}if((pid = fork())<0){status = -1;}else if(pid == 0){execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);//底层就是execlexit(127); //子进程正常执行则不会执行此语句}else{while(waitpid(pid, &status, 0) < 0){if(errno != EINTER){status = -1;break;}}}return status;
}

正确处理 execvp 函数调用错误方案和相应的输出消息

需要注意的是,exec 系列函数只有在发生错误时才会返回,所以要实现错误检查例程,并根据需要处理相应的代码路径。
其中 execvp 在失败时返回 -1,而且它还会设置 errno 变量。不过要注意,errno 应该在函数调用前明确设置为 0,只有在给定的调用返回后才检查该值。execvp 函数可以接受没有斜线的文件名,这意味着文件是在 PATH 环境变量指定的目录中搜索的。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(void) {const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };execvp("vim", args);exit(EXIT_SUCCESS);
}

假设用户需要创建一个新的进程,并执行给定的程序代码,那么在这种情况下我们可以利用 fork 函数调用与 execvp 相结合。在这种情况下,我们可以利用 fork 函数调用与 execvp 相结合。fork 复制调用的进程,并创建一个新的进程,称为-子进程。在下面的例子中,我们实现了一个自定义函数包装器来创建一个新的进程并加载/执行给定的程序代码。注意,一旦创建了子进程,它就会执行不同的代码,而父进程则会等待,直到子进程退出。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>pid_t spawnChild(const char* program, char** arg_list)
{pid_t ch_pid = fork();if (ch_pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (ch_pid > 0) {printf("spawn child with pid - %d\n", ch_pid);return ch_pid;} else {execvp(program, arg_list);perror("execve");exit(EXIT_FAILURE);}
}int main(void) {const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };pid_t child;int wstatus;child = spawnChild("vim", args);if (waitpid(child, &wstatus, WUNTRACED | WCONTINUED) == -1) {perror("waitpid");exit(EXIT_FAILURE);}exit(EXIT_SUCCESS);
}

其他资源

Linux -- system、.(source)、exec的区别_青椒*^_^*凤爪爪的博客-CSDN博客

exec和system函数_execl system_Lawrence_121的博客-CSDN博客

Linux -- system、.(source)、exec的区别_青椒*^_^*凤爪爪的博客-CSDN博客

exec族函数、system()函数和popen函数_exec函数 system_基尔霍夫原来是码农的博客-CSDN博客 https://www.cnblogs.com/armsom/articles/17523386.html

Linux下对GPIO的操作控制(基于GPIO子系统)_linux 通过按钮控制gpio de_金城孤客的博客-CSDN博客 Linux系统应用层GPIO控制_echo 268 > export增加gpio268_技术の宅的博客-CSDN博客

http://www.lryc.cn/news/104232.html

相关文章:

  • 150行代码写一个Qt井字棋游戏
  • k8s概念-controller
  • Gis入门,根据起止点和一个控制点计算二阶贝塞尔曲线(共三个控制点组成的线段转曲线)
  • 第1集丨Vue 江湖 —— Hello Vue
  • PCB制版技术
  • 大数据课程E7——Flume的Interceptor
  • P2P网络NAT穿透原理(打洞方案)
  • Gof23设计模式之桥接外观模式
  • 微服务性能分析工具 Pyroscope 初体验
  • 工作记录------单元测试(持续更新)
  • C#再windowForm窗体中绘画扇形并给其填充颜色
  • MBA拓展有感-见好就收,还是挑战到底?MBA拓展有感-见好就收,还是挑战到底?
  • 综合布线系统光缆分类及其特点?
  • 前端构建(打包)工具发展史
  • 【数据可视化】(一)数据可视化概述
  • GoogleLeNet Inception V2 V3
  • 【css】背景图片附着
  • 解决运行flutter doctor --android-licenses时报错
  • 在使用Python爬虫时遇到503 Service Unavailable错误解决办法汇总
  • 小研究 - 主动式微服务细粒度弹性缩放算法研究(一)
  • 【LeetCode】215.数组中的第K个最大元素
  • MySQL学习记录:第七章 存储过程和函数
  • Docker中gitlab以及gitlab-runner的安装与使用
  • 一起学SF框架系列5.12-spring-beans-数据绑定dataBinding
  • 火热报名中 | 赛宁独家技术支持第七届“蓝帽杯”网络安全技能大赛
  • 无涯教程-jQuery - Ajax Tutorial函数
  • Android日志
  • 【Golang 接口自动化08】使用标准库httptest完成HTTP请求的Mock测试
  • SpringBoot自定义注解 + AOP+分布式Redis 防止重复提交
  • 3.yum安装分布式LNMP--剧本