Linux 执行新程序:execve() 函数
系统调用execve()函数作用
在Linux程序中,通过调用execve(),进程能够以全新程序来替换当前运行的程序。再次过程中,将丢弃旧有程序,进程的栈.数据以及堆段会被新程序所替换。这个 exec 函数族就提供了一个在进程中启动另一个程序执行的方法。
它根据指定的文件名或目录名找到可执行文件,并用它来代替当前进程的执行映像。也就是说,exec调用并没有生成新进程,一个进程一旦调用 exec函数,它本身就“死亡”了,系统把代码段替换成新程序的代码,放弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,惟一保留的就是进程的 ID。也就是说,对系统而言,还是同一个进程,不过执行的已经是另外一个程序了。
execve()函数原型
#include <unistd.h>
int execve(const char *filename, char *const argv[],char *const envp[]);
- filename:包含准备载入当前进程空间的新程序的路径名。既可以是绝对路径,又可以是相对路径。
- argv[]:指定了传给新进程的命令行参数,该数组对应于c语言main函数的argv参数数组,格式也相同,argv[0]对应命令名,通常情况下该值与filename中的basename(就是绝对路径的最后一个)相同。
- envp[]:最后一个参数envp指定了新程序的环境列表。参数envp对应于新程序的environ数组。
实例1
下面的每个代码我都放到了github上,欢迎大家fork/star
GeneralSandman
t_execve.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
int main(int argc,char * argv[]){char * argVec[10];char * envVec[]={"环境变量1","环境变量2",NULL};argVec[0]=argv[0];argVec[1]=argv[1];argVec[2]="参数1";execve(argv[1],argVec,envVec);printf("the progress can't to here\n");exit(EXIT_SUCCESS);
}
envargs.c
下面的每个代码我都放到了github上,欢迎大家fork/star
GeneralSandman
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
extern char ** environ;
int main(int argc,char * argv[]){int i=0;char ** ep;printf("new progress\n");printf("参数\n");for(i=0;i<argc;i++)printf("\t%s\n",argv[i]);printf("环境变量:\n");for(ep=environ;*ep!=NULL;ep++)printf("\t%s\n",*ep);printf("new progress over\n");exit(EXIT_SUCCESS);return 0;
}
运行结果
程序说明
运行t_execve程序,会调用execve()函数,函数将会调用进程argv[1],也就是调用envargs,并将自己的环境变量,参数传递给他。我们发现,printf(“the progress can’t to here\n”); 永远不会被执行(除非调用execve()失败),因为调用execve(),会转到新的进程,自己会被“杀死”;
实例2
t_execve2.c
下面的每个代码我都放到了github上,欢迎大家fork/star
GeneralSandman
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
int main(int argc,char * argv[],char ** environ){pid_t pid;printf("the example!!!\n");switch(fork()){case -1:printf("fork error\n");exit(EXIT_FAILURE);case 0:printf("child is running\n");printf("child pid=%d, child parent pid=%d\n",getpid(),getppid());printf("child uid=%d, child gid=%d\n",getuid(),getpid());execve(argv[1],argv,environ);printf("child can't in here\n");break;default:wait(NULL);printf("parent is running\n");break;}exit(EXIT_SUCCESS);
}
envargs2.c
下面的每个代码我都放到了github上,欢迎大家fork/star
GeneralSandman
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
int main(int argc,char * argv[],char ** environ){int i;printf("running after the execve()\n");printf(" pid=%d, parent pid=%d\n",getpid(),getppid());printf(" uid=%d, gid=%d\n",getuid(),getpid());printf("the immage over\n");exit(0);
}
运行结果
程序说明
运行t_execve2程序,fork()之后,子进程会调用execve()函数,而父进程会等待子进程退出(也就是等待envargs2退出)。我们发现:执行新程序保持了原来进程的进程 ID、父进程ID、实际用户 ID 和实际组 ID。同时还可以看到,当调用新的可执行程序后,原有的子进程的映像被替代,不再被执行。
执行新程序后的进程除了保持原来的进程 ID、父进程 ID、实际用户 ID 和实际组 ID 之外,进程还保持了许多原有的特征,主要有:
- 当前工作目录
- 根目录
- 创建文件时使用的屏蔽字
- 进程信号屏蔽字
- 未决警告
- 和进程相关的使用处理器的时间
- 控制终端
- 文件锁
exec族
有 6 个以 exec 开头的函数族,他们之间的语法有细微的差别,函数原型如下所示:
- int execl(const char *path, const char *arg, …)
- int execv(const char *path, char *const argv[])
- int execle(const char *path, const char *arg, … , char *const envp[])
- int execve(const char *path, char *const argv[], char *const envp[])
- int execlp(const char *file, const char *arg, …)
- int execvp(const char *file, *const argv[])
区别
实际上有关exec是一个函数族,包括execle,execlp,execvp,execv,execl但是他们具体的实现都是调用execve()之上。它们的区别就在于对路径名,参数以及环境变量的指定上。下面分别从这三个方面来区分这几个函数:
- 路径名:带p的表示可以通过环境变量PATH去查找,所以我们可以不用绝对路径,比如execlp和execvp就可以直接用filename。
- 参数:带l的execle()和execlp()以及execl()要求在调用中以字符串形式指定参数。首个参数相当于新程序main中的argv[0],因而通常与filename中的basename相同(就是绝对路径的最后一个)。
- 环境变量:以e结尾的允许我们通过envp为新程序显式的指定环境变量,其中envp必须以NULL结尾。
Linux 执行新程序:execve() 函数相关推荐
- 用exec()函数执行新程序
使用fork或vfork创建子进程后,子进程通常会调用exec函数来执行另外一个程序.系统调用exec用于执行一个可执行程序以代替当前进程的执行映像. exec调用没有生成新进程.一个进程一旦调用ex ...
- Linux系统运行Windows程序(Linux执行windows程序)
dpkg --add-architecture i386 && apt-get update && apt-get install wine32 需要安装32位wine ...
- linux执行指定程序的命令,linux 下使用指定的用户来执行命令
有时间,我们需要在开机的时候执行一些特定的程序或都脚本,因为涉及到安全主面的问题,所以又不想用root来执行,那怎样办呢. 经过查看 su 的帮助提示,发现: [root@redhat6 ~]# su ...
- 在进程中执行新代码 execl、execle、execlp、execv、execve和execvp函数
在进程中执行新代码 execl.execle.execlp.execv.execve和execvp函数 摘要:本文主要讲述怎样在进程中执行新代码,以及exec系列函数的基本用法. 在进程中执行新代码 ...
- Linux系统调用之execve函数与标准C库exec函数族(有关于进程方面的函数族)
前言 如果,想要深入的学习Linux系统调用里面的execve函数与标准C库中的exec函数族,还是需要去自己阅读Linux系统中的帮助文档. 具体输入命令: man 2 execve man 3 e ...
- linux 脚本 java_Linux 通过脚本执行Java程序
由于要统计不同的IP,代码中应用了HashSet来存放IP地址. 上述Java程序是在Windows下编写的,如果在Linux服务器上运行,只需要把上面文件的路径和文件更换了就可以了. 2.编写好ja ...
- Unix/Linux编程:exec()族函数
执行新程序:execve() 系统调用execve()可以将新程序加载到某一进程的内存空间.在这一操作过程中,将丢弃就有程序,而进程的栈.数据以及堆段会被新程序的相应不见所替换.在执行了各种C语言函数 ...
- Linux内核Hook系统调用execve
资源下载地址:linux内核hook系统调用execve函数-Linux文档类资源-CSDN下载 (已在内核为 4.19.0-amd64-desktop版本uos编译通过,并成功达到目的) 在Linu ...
- linux exec 二程序,二十五、Linux 进程与信号---exec函数
25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...
最新文章
- 对付网络盗贼的三板斧
- DDD领域驱动设计特点及难点
- 导出EXCEL2003
- 拉格朗日插值法(Lagrange)
- Linux上安装wkhtmltopdf,以及调试所遇到的问题
- STM8单片机串口同时识别自定义协议和Modbus协议
- Oracle数据库是如何执行SQL的
- 搞懂这三个指标,数据分析起码少费一半力
- python找到文件夹下指定文件类型_python 读取指定文件夹中的指定文件类型的文件名...
- 海康8700联网网关如何通过GB28181接入安防摄像头互联网直播流媒体解决方案EasyGBS实现web端无插件直播
- React-Native之轮播组件looped-carousel的介绍与使用
- Unity Shader: Blend混合
- Android 扫码盒子全局接收付款码(全局事件上层接收多重下发)
- 华为交换机的应用案例(小)
- Android如何判定一张图片是不是灰度的
- 华为日历登录qq邮箱的解决方案
- linux下用vi,vim编辑时退出编辑模式(wq)无法保存退出
- 《手机拍照与视频》那点事
- 十大ios开发者喜爱的开源库
- 模拟非同期运行java_基于JavaME技术的移动终端设备信息查询系统的设计分析.pdf...
热门文章
- 倾角传感器精度校准检测
- oracle中12560,解决ORA-12560的方法(转载)
- 颠覆物理学的中微子:宇宙中飞行速度几乎达到光速
- 不小心把java文件删除了_如何使用Java恢复已删除的文件?
- oracle找回删除的表
- 虚拟机云服务器6.0教程pdf,虚拟机云服务器6.0教程pdf
- 结合推荐营销和社交媒体的最佳实践有哪些?
- 提升: 建立一个如下的学生情况表,要求先依次输入学生数据元素,然后依次显示当前表中的学生数据元素。 学号	 姓名	 性别	 年龄 2000001 张三 男	 20 2000002
- 显著图(Saliency map)
- java过滤xss_java处理XSS过滤的方法