5进程原语:execl(),execlp(),execle(),execv(),execvp(),execvp(),execve()



1.exec族依赖的头文件

#include<unistd.h>

extern char**environ;

2函数声明

//第一个参数:可执行程序所在的绝对位置

//第二个参数:可执行程序运行时所需的参数,这里是一个可变参数,每个参数之间用逗号分割

//参数结束时,最后一个参数是:NULL

int execl(constchar *path, const char *arg, ...);

 

//注意,这里函数名加了p,表示调用了系统的环境变量中配置的PATH,查看环境变量命令:Echo
$PATH

 

//第一个参数:只需要写上文件名即可,不用写全路径,后面的参数和上面的参数相同

int execlp(constchar *file, const char *arg, ...);

 

//第一个参数:全路径

//envp[],表示传递的是环境变量的数组

int execle(constchar *path, const char *arg,

                 
..., char * const envp[]);

 

//这个和第一个exec函数区别是,这里的参数不是可变参数了,而是通过一个传递一个数组的方式进行传递进去。

int execv(constchar *path, char *const argv[]);

 

//execvp和execv的区别仅仅是文件名和路径的区别。

int execvp(constchar *file, char *const argv[]);

 

//这时候传递环境变量

int execvpe(constchar *file, char *const argv[],

                  
char *const envp[]);

 

3.注意:

  
A:这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。

  
B:
这些函数原型看起来很容易混,但只要掌握了规律就很好记。不带字母p(表示

path)的exec函数第一个参数必须是程序的相对路径或绝对路径,例如“/bin/ls”或“./

a.out”,而不能是“ls”或“a.out”。对于带字母p的函数:

如果参数中包含/,则将其视为路径名。

否则视为不带路径的程序名,在PATH环境变量的目录列表中搜索这个程序。

带有字母l(表示list)的exec函数要求将新程序的每个命令行参数都当作一个参数传

给它,命令行参数的个数是可变的,因此函数原型中有…,…中的最后一个可变参数应该是

NULL,起sentinel的作用。对于带有字母v(表示vector)的函数,则应该先构造一个指向

各参数的指针数组,然后将该数组的首地址当作参数传给它,数组中的最后一个指针也应该

是NULL,就像main函数的argv参数或者环境变量表一样。

C:对于以e(表示environment)结尾的exec函数,可以把一份新的环境变量表传给它,其他exec函数仍使用当前的环境变量表执行新程序。

   
D:exec调用举例如下:

char *const ps_argv[] ={"ps","-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};

char *const ps_envp[]={"PATH=/bin:/usr/bin", "TERM=console", NULL};

execl("/bin/ps", "ps","-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);

execv("/bin/ps", ps_argv);

execle("/bin/ps", "ps","-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);

execve("/bin/ps", ps_argv,ps_envp);

execlp("ps", "ps","-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);

execvp("ps", ps_argv);

E:
事实上,只有execve是真正的系统调用,其它五个函数最终都调用execve,所以execve在man手册第2节,其它函数在man手册第3节。这些函数之间的关系如下图所示。

 

4.案例说明:

运行结果:

5.
由于exec函数只有错误返回值,只要返回了一定是出错了,所以不需要判断它的

返回值,直接在后面调用perror即可。注意在调用execlp时传了两个“ps”参数,第一

个“ps”是程序名,execlp函数要在PATH环境变量中找到这个程序并执行它,而第二

个“ps”是第一个命令行参数,execlp函数并不关心它的值,只是简单地把它传给ps程

序,ps程序可以通过main函数的argv[0]取到这个参数。

调用exec后,原来打开的文件描述符仍然是打开的。利用这一点可以实现I/O重定向。

先看一个简单的例子,把标准输入转成大写然后打印到标准输出:

运行结果:

运行结果:

分析:

wrapper程序将命令行参数当作文件名打开,将标准输入重定向到这个文件,然后调用

exec执行upper程序,这时原来打开的文件描述符仍然是打开的,upper程序只负责从标准输入读入字符转成大写,并不关心标准输入对应的是文件还是终端。

   
exec族

l
命令行参数列表

p
搜素file时使用path变量

v
使用命令行参数数组

e
使用环境变量数组,不使用进程原有的环境变量,设置新加载程序运行的环境变量

 

 

 

 

 

 

 

 

 

 

时间: 2024-10-02 11:12:12

5进程原语:execl(),execlp(),execle(),execv(),execvp(),execvp(),execve()的相关文章

4进程原语:fork()函数,getpid()函数和getppid()函数,getuid()函数,getgid()函数,vfork()

 1fork()函数 子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同.fork调用一次返回两次,有以下特点: A:父进程中返回子进程ID B:子进程中返回0 C:读时共享,写时复制 2fork()依赖的头文件 #include <unistd.h> 3fork()函数说明: pid_tfork(void);                            通过该函数创建一个子进程 4案例说明: 总结: A因为读时共享和写时复制,子进程会复制父进程的代码,但是从fo

6进程原语:wait()和waitpid()函数

 1 wait/waitpid 僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程 孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号 进程init进程,称为init进程领养孤儿进程 2依赖的头文件 #include <sys/types.h> #include <sys/wait.h> 3函数声明 pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status

浅谈缓冲区溢出之栈溢出&lt;下&gt;

上回我们简单的介绍了缓冲区溢出的基本原理和机器级代码的解释,对此类问题的分析和研究都必须建立在对程序的机器级表示有一定的了解的基础上.记得有句话是这样说的,"真正了不起的程序员是对自己代码的每一个字节都了如指掌的程序员."我们也许做不到每一字节,但至少得明晰机器级程序的组成结构和执行流程. 言归正传,我们今天在上回的基础上继续探索缓冲区溢出.之前的例子都是简单的通过越界访问来实现对程序执行流程的变动,而且执行的函数都是编译前写入的,那么如何对一个发行版的可执行程序进行缓冲区溢出呢? 首

简单比较C语言中的execl()函数与execlp()函数_C 语言

C语言execl()函数:执行文件函数头文件: #include <unistd.h> 定义函数: int execl(const char * path, const char * arg, ...); 函数说明:execl()用来执行参数path 字符串所代表的文件路径, 接下来的参数代表执行该文件时传递过去的argv(0), argv[1], ..., 最后一个参数必须用空指针(NULL)作结束. 返回值:如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中

linux系统编程之进程(三) exec系列函数和system函数

一.exec替换进程映象 在进程的创建上Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离.这样的好处是有更多的余地对两种操作进行管理.当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行.当然,exec系列的函数也可以将当前进程替换掉. 二.exec关联函数组 包含头文件<unistd.h> 功能用exec函数可以把当前进程替换为一个新进程.exec名下是由多个关联函数组成的一个完整系列,头文件<unistd.h> 原型 in

《APUE》读书笔记—第八章进程控制

本章介绍Unix的进程控制,包括进程创建,执行程序和进程终止,进程的属性,exec函数系列,system函数,进程会计机制. 1.进程标识符 每一个进程都有一个非负整数标识的唯一进程ID.ID为0表示调度进程,即交换进程,是内核的一部分,也称为系统进程,不执行任何磁盘操作.ID为1的进程为init进程,init进程不会终止,他是一个普通的用户进程,需要超级用户特权运行.获取标识符函数如下: #include <sys/types.h>#include <unistd.h> pid_

Linux中用于进程控制的exec函数族

1.简介 在Linux中,并不存在exec()函数,exec指的是一组函数,一共有6个,分别是: #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, ..., cha

linux普通用户获得root密码执行root权限的进程

问题描述 linux普通用户获得root密码执行root权限的进程 我想写一个程序,仿照在非root用户下安装程序时,提示需要root密码,然后就能继续安装.意思就是获得root密码后,我就能执行root权限的进程.这个该什么思路呢?execve函数的第三个参数设置环境变量能不能实现? 解决方案 普通用户执行ROOT权限 解决方案二: 用程序的话就有点麻烦了,可以使用Linux脚本,很方便,SHell脚本 解决方案三: python供你参考: #!/usr/bin/env python3 -*-

跟老齐学Python之折腾一下目录_python

python在安装的时候,就自带了很多模块,我们把这些模块称之为标准库,其中,有一个是使用频率比较高的,就是 os .这个库中方法和属性众多,有兴趣的看官可以参考官方文档:https://docs.python.org/2/library/os.html,或者在交互模式中,用dir(os)看一看. 复制代码 代码如下: >>> import os   #这个动作很重要,不能缺少 >>> dir(os) ['EX_CANTCREAT', 'EX_CONFIG', 'EX_