exec家族与system函数
创始人
2025-05-31 22:24:04
0

exec家族函数

NAMEexecl, execlp, execle, execv, execvp, execvpe - execute a fileSYNOPSIS#include 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[]);

可以观察一些这一组函数的后缀名称,无非就是在exec函数后面加上 l,p,e,v这几个字母。

  1. l : list => 函数参数列表指定进程参数。

  1. p:path => 到PATH环境变量这个路径中查找可执行程序

  1. e:environ => 父进程提供环境变量

  1. v:数组的方式提供进程参数

进程参数

自动搜索PATH

使用当前环境变量

execl()

列表

NO

YES

execlp()

列表

YES

YES

execle()

列表

NO

NO,提供环境变量

execv()

数组

NO

YES

execvp()

数组

YES

YES

execve()

数组

NO

NO,提供环境变量

看一下demo:

#include 
#include 
#include 
#include 
#include int main(int argc,char* argv[])
{char  pids[32] = {0};char* const ps_argv[] = {"pstree","-A","-p","-s",pids,NULL};char* const ps_envp[] = {"PATH=/bin:/usr/bin","TEST=Delphi",NULL};sprintf(pids,"%d",getpid());execl("/bin/pstree","pstree","-A","-p","-s",pids,NULL);execl("pstree","pstree","-A","-p","-s",pids,NULL);execle("/bin/pstree","pstree","-A","-p","-s",pids,NULL,ps_envp);execv("/bin/pstree",ps_argv);execvp("pstree",ps_argv);execve("/bin/pstree",ps_argv,ps_envp);return 0;
}

system函数

NAMEsystem - execute a shell commandSYNOPSIS#include int system(const char *command);

参数:程序名以及进程参数(如:pstree -A -p -s $$)

返回值:进程退出状态值

下面是system(...) 函数运行原理图,和我们自己创建的create_process(...)原理差不多。

来看一下demo1:

#include 
#include 
#include 
#include 
#include /*$$ : 表示当前进程的pid
*/int main(int argc,char* argv[])
{int result = 0;printf("current: %d\n",getpid());result = system("pstree -A -p -s $$");printf("result = %d\n",result);return 0;
}

编译输出:

wj@wj:~/WORK/Learning/DT/07/07-3$ gcc test.c -o test.out
wj@wj:~/WORK/Learning/DT/07/07-3$ ./test.out 
current: 72319
systemd(1)---systemd(1454)---gnome-terminal-(2307)---bash(57230)---test.out(72319)---sh(72320)---pstree(72321)
result = 0

看一下demo2:

//test.sh

echo "Hello world from shell..."
a=1
b=1
c=$(($a+$b))
echo "c = $c"
wj@wj:~/WORK/Learning/DT/07/07-3$ chmod 777 test.sh
wj@wj:~/WORK/Learning/DT/07/07-3$ ./test.sh
Hello world from shell...
c = 2

看一下demo3:

//test.c
#include 
#include 
#include 
#include 
#include /*wait: true  :代表父进程是否等待子进程结束wait: false :代表父进程不等待子进程结束
*/int create_process(char* path,char* const args[],char* const env[],int wait)
{int ret = fork();if(ret == 0){if(execve(path,args,env) == -1){exit(-1);}}if(wait && ret)  // 1.wait为true。2.并且父进程是否成功创建子进程?来共同解决父进程是否等待子进程结束?{waitpid(ret,&ret,0);}return ret;   //1.如果等待,ret为子进程的退出状态;2.如果不等待,返回为子进程的pid
}int main(int argc,char* argv[])
{char* target = argv[1];char* const ps_argv[] = {target,NULL};char* const ps_envp[] = {"PATH=/bin:/usr/bin","TEST=Delphi",NULL};int result =0;if(argc < 2) exit(-1);printf("current: %d\n",getpid());//result = create_process(target,ps_argv,ps_envp,1);result = system(target);printf("result = %d\n",result);return 0;
}
//helloworld.c
#include int main(int argc,char* argv[])
{printf("hello world\n");return 0;
}

编译运行输出:

wj@wj:~/WORK/Learning/DT/07$ gcc test.c -o test.out
wj@wj:~/WORK/Learning/DT/07$ ./test.out ./helloworld.out
current: 73126
hello world
result = 0

wj@wj:~/WORK/Learning/DT/07$ cp 07-3/test.sh ./
wj@wj:~/WORK/Learning/DT/07$ ls
07-3  helloworld.c  helloworld.out  test.c  test.out  test.shwj@wj:~/WORK/Learning/DT/07$ ./test.out ./test.sh
current: 73178
Hello world from shell...
c = 2
result = 0

system 和 create_process区别和联系

  1. system创建的是shell进程,功能比较强大,可以直接调用shell进程函数,但是这个功能强大(相对于我们自己创建的create_process函数来说)是以牺牲性能为代价的。

  1. 如果用 //result = create_process(target,ps_argv,ps_envp,1); 我们自己创建的create_process,则不能够调用shell进程函数。我们自己创建的create_process效率更高。

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...