新程序的执行

一:execve()

之所以叫新程序的执行,原因是这部分内容一般发生在fork()vfork()之后,在子进程中通过系统调用execve()可以将新程序加载到子进程的内存空间。这个操作会丢弃原来的子进程execve()之后的部分,而子进程的栈、数据会被新进程的相应部分所替换。即除了进程ID之外,这个进程已经与原来的进程没有关系了。
举个例子:在shell(shell也是一个进程)中执行最简单的HelloWorld程序。它也是首先调用execve()这个系统调用的,下面用strace跟踪下执行HelloWorld的过程,我们可以看到第一步执行的是execve()。省略了后面信息,如图:

实际上Hello进程的父进程是shell进程,它是shell进程fork出来的一个子进程然后执行execve之后在执行的Hello,所以我们下面来看看这个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数组。

还要注意的是:由于是将调用进程取而代之,因此对execve的调用将永远不能返回,也无需检查它的返回值,因为该值始终为-1,实际上,一旦返回就表明了错误,通常会有error值来判断,下面是几个常用的:
- EACCES:参数pathname没有指向一个常规文件,未对该文件赋于可执行权限,或者因为目录没有x权限。
- ENOTNT:pathname指定的文件并不存在。
- ETXTBSY:存一个或者多个进程已经以写入的方式打开pathname所指定的文件。

下面我们举个例子说明execve的用法:
filename:execve.c

#include<stdio.h>
#include<unistd.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[1];
argVec[1] = "hello world";
argVec[2] = "goodbye";
execve(argv[1],argVec,envVec); //分别传入三个参数
return 0;
}

filename:envargs.c

#include<stdio.h>
#include<stdlib.h>
extern char ** environ;
int main(int argc,char *argv[]) //argv[]相当于上面的argvec[]
{
int j;
char **ep;
for(j = 0;j < argc;j++) {
printf("argv[%d] = %s\n",j,argv[j]);
}
for(ep = environ;*ep != NULL;ep++) { //environ是上面的envVec[]
printf("environ:%s\n",*ep);
}
exit(EXIT_SUCCESS);
return 0;
}

二:exec()函数族

实际上有关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结尾。

下面我们通过这个表格来介绍exec()函数族之间的差异:

函数 执行程序文件 参数 环境变量
execve() 路径名 数组 envp参数
execle() 路径名 列表 envp数组
execlp() 文件名 列表 调用者environ
execvp() 文件名 数组 调用者environ
execv() 路径名 数组 调用者environ
execl() 路径名 列表 调用者environ

执行新程序 execve()的更多相关文章

  1. linux c 执行新程序

    学习进程时,linu c上说新开的进程一般要执行另外一个程序,同时与父进程执行同一个程序没有意义 如下是如何执行一个新的程序 使用exec函数簇 exec函数簇包含如下函数

  2. 在进程中执行新代码 execl、execle、execlp、execv、execve和execvp函数

    摘要:本文主要讲述怎样在进程中执行新代码,以及exec系列函数的基本用法. 在进程中执行新代码 用函数fork创建子进程后,假设希望在当前子进程中运行新的程序,能够调用exec函数运行还有一个程序.当 ...

  3. Linux进程线程学习笔记:运行新程序

    Linux进程线程学习笔记:运行新程序                                         周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...

  4. JVM执行Java程序时内存的划分

    Java虚拟机在执行Java程序过程中会把它所管理的内存区域划分为若干个不同的数据区域. Java虚拟机所管理的内存包括以下几个运行时区域: 1.程序计数器(Program Couter Regist ...

  5. docker~在centos容器中安装新程序

    上一篇我们使用了阿里加速器安装了centos镜像,然后创建了一个新容器,运行了这个镜像,这一讲我们来为这个镜像添加一些应用程序,然后再保存容器,push容器到仓储,大家就可以直接pull我生产的容器了 ...

  6. Java程序导出成.jar文件、生成.exe可执行文件及打包成可执行安装程序(可在无Java环境的计算机上运行)--以个人所得税计算器为例

    Java程序导出成.jar文件.生成.exe可执行文件及打包成可执行安装程序 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 需要准备的软件: jdk, ...

  7. VBA定时执行某程序

    OnTime 方法参阅应用于示例特性安排一个过程在将来的特定时间运行(既可以是具体指定的某个时间,也可以是指定的一段时间之后). expression.OnTime(EarliestTime, Pro ...

  8. Shell脚本实现每个工作日定时执行指定程序

    我们可能会遇到这样的情景:必须在每个工作日定时执行Linux服务器上的某个程序.那么有没有办法实现这一功能呢?答案是肯定的.我们可以运用Shell脚本简单实现这一功能. 原理很简单,Shell脚本内部 ...

  9. 在linux命令行下执行php 程序

    如何在linux命令行下,执行php程序. 例子 打印当前时间 php -r "echo time()" 随机输出一个数字 php -r "echo rand(1,20) ...

随机推荐

  1. element-ui的Tree树组件使用技巧

    目录 1,前言 2,需求 3,解决思路 4,完整代码 5,总结 1,前言 最近这段时间在做一个新的模块,其中有一个三层的树结构,产品经理提出了一个很古怪的需求,整的我只能自己控制树的交互,写完之后,感 ...

  2. linux 上添加多个jdk

    1. 首先将你需要上传的jdk 上传并解压 2.你可以自定义解压的路径 3. alternatives --install /usr/bin/java java /usr/java/jdk1.7.0_ ...

  3. JVM 面试题,安排上了!!!

    肝了一篇非常硬核的 JVM 基础总结,写作不易,小伙伴们赶紧点赞.转发安排起来! 原文链接 据说看完这篇 JVM 要一小时 JVM 的主要作用是什么? JVM 就是 Java Virtual Mach ...

  4. .NET 开发一个服务器 应用管理工具

    一:背景 1.Anno.Deploy Anno.Deploy可以和 Anno集成使用,用于部署新的服务.启动服务.停止服务.清理服务.也可以单独使用,用于守护程序. 使用方法 1.和Anno集成使用 ...

  5. C++核心编程 3 函数提高

    函数默认参数 在C++中,函数的形参列表中的形参是可以有默认值的: 语法:返回值类型 函数名 (参数 = 默认值){ } 实例: #include<iostream> using name ...

  6. 初探区块链数字加密资产标准ERC721

    ERC721介绍 数字加密货币大致可以分为原生币(coin)和代币(token)两大类.前者如BTC.ETH等,拥有自己的区块链.后者如Tether.TRON.ONT等,依附于现有的区块链.市场上流通 ...

  7. CF1082E Increasing Frequency (multiset+乱搞+贪心)

    题目大意: \(给你n个数a_i,给定一个m,你可以选择一个区间[l,r],让他们区间加一个任意数,然后询问一次操作完之后,最多能得到多少个m\) QWQ 考场上真的** 想了好久都不会,直到考试快结 ...

  8. ls命令剖析

    目录 ls命令剖析 资料翻译 SYNOPSIS 使用方式 DESCRIPTION 说明 参数的说明 -l 参数字符的解释 文件权限的解释 FILES 文件夹 实战演练 ls 命令 ls -l 命令 l ...

  9. Go语言核心36讲(Go语言进阶技术一)--学习笔记

    07 | 数组和切片 我们这次主要讨论 Go 语言的数组(array)类型和切片(slice)类型. 它们的共同点是都属于集合类的类型,并且,它们的值也都可以用来存储某一种类型的值(或者说元素). 不 ...

  10. Oil Deposits 新年特辑篇

    链接:E - Oil Deposits 题目: The GeoSurvComp geologic survey company is responsible for detecting undergr ...