进程替换exec系列介绍

ececl,execlp,execle,execv,execvp   //库函数
execve   //系统调用

1.execl

which  ps

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
   printf("main pid=%d\n",getpid());
   execl("/usr/bin/ps","ps","-f",(char *)0);
   exit(0);
}

注意,就是原来的程序换成了ps程序,但是PCB没有改变,但是PCB里面的有些值被修改了,比如pcb中程序的名字换成了新进程的名字;
思考1,新的进程从哪里执行呢?
新的进程从主函数的第一行开始执行,也就是ps程序的主函数的第一行代码开始执行,这个和fork方法不一样,fork返回以后,从fork所在位置开始执行; 所以可以直接在execl下面打印一个失败,如果成功就根本不会执行到这里; printf("execl error\n");

思考2:如果将execl里面的第二个参数改为"abc",程序还能否执行?
可以正常执行,只是程序命令改为了abc;

execl("/usr/bin/ps","abc","-f",(char *)0);

思考3:如果将execl里面的第一个参数改为"abc",程序还能否执行?
只要execl第一个参数不出错,第一个参数如果出错了,你就找不到这个程序了;  那么就运行不成功了;比如:

execl("/usr/bin/abc","ps","-f",(char *)0);

一定要在exec替换函数之后写:

printf("exec  error!\n");

失败了才运行到这一句.

思考4:去掉\n,会发生什么?

思考5:ps也是由ps.c编译为ps可执行程序的,同理cp也是;
(which ps which cp)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
   printf("main pid=%d\n",getpid());
   execl("/usr/bin/cp","cp","yma.c","ymb.c",(char *)0);
   exit(0);
}

2.execlp

execlp("ps","ps","-f",(char *)0);

只给文件名,不需要给文件路径,因为它可以去环境变量PATH所指的位置去搜索;
注意,第一句,虽然有两个ps,但是不能省,第一个代表我们启动的是ps(去环境变量下搜索),第二个代表的是替换的程序也就是新程序的名字;

3.execle

和execl一样的参数,只是多了最后一个环境变量.

//int main(int argc,char *argv[],char *envp[])
execle("/usr/bin/ps","ps","-f",(char *)0,envp);

思考:如何使用自己的环境变量呢?

4.execv

execv是把参数都放在了一个数组中,然后把这个数组传递进去即可;

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={"ps","-f",0};
execv("/usr/bin/ps",myargv);

5.execvp

第一个参数只要文件名,不要路径;

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={"ps","-f",0};
execvp("ps",myargv);

看帮助手册,execvpe是GNU的扩展,不通用,所以我们这里不做介绍.
(但是我们其实已经知道,execvpe比execvp多了一个e,也就是多了一个环境变量)

6.execve(重点)

int execve(const char * path, char* const argv[],char* const envp[]); //系统调用

代码如下:

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={"ps","-f",0};
execve("/usr/bin/ps",myargv,envp);

总结:

//pathname:新替换的程序的路径+名字
//arg :传给新程序主函数的第一个参数,一般为程序的名字
//arg 后面是剩余参数列表,参数个数可变,必须以空指针作为最后一个参数
int execl(const char* pathname, const char * arg,...);
int execlp(const char* file, const char * arg,...);
int execle(const char* pathname, const char * arg,...,char* const envp[]);
int execv(const char * pathname, char* const argv[]);
int execvp(const char * file, char* const argv[]);
int execve(const char * pathname, char* const argv[],char* const envp[]); //系统调用

//前五个是库函数,最后一个是系统调用,所以本质上上面5个都是通过第六个系统调用实现的

也就是说,上面5个都是调用的execve,不过都是把参数放进数组,然后把数组传递给这个系统调用execve; 也就是说,这些方法没有本质区别; 也就是说,本质上只有一个替换方法,就是execve;

注意,写一个(char *)NULL也是可以的;

助记:
l(list)     参数地址列表,以空指针结尾
v(vector)   存放各个参数地址的指针数组的地址
p(path)   按PATH环境变量指定的目录搜索可执行文件
e(enviroment)  存放环境变量字符地址的指针数组的地址

相关推荐

  1. 进程替换exec系列介绍

    2024-04-09 22:40:02       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-09 22:40:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-09 22:40:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-09 22:40:02       82 阅读
  4. Python语言-面向对象

    2024-04-09 22:40:02       91 阅读

热门阅读

  1. Linux C++ 022-函数模板

    2024-04-09 22:40:02       34 阅读
  2. python把视频按帧转化为图片并保存

    2024-04-09 22:40:02       35 阅读
  3. Linux下I2C驱动框架:I2C 设备驱动

    2024-04-09 22:40:02       42 阅读
  4. 【Linux篇】makefile一次形成两个可执行

    2024-04-09 22:40:02       34 阅读
  5. Kubernetes统一管理vGPU:原理、实现与挑战

    2024-04-09 22:40:02       40 阅读
  6. 大模型从入门到应用——OpenAI基础调用

    2024-04-09 22:40:02       39 阅读
  7. 程序员如何搞副业?

    2024-04-09 22:40:02       38 阅读
  8. Go语言支持重载吗?如何实现重写?

    2024-04-09 22:40:02       41 阅读
  9. @Transactional 详解

    2024-04-09 22:40:02       35 阅读
  10. 雷军给年轻人的五点建议

    2024-04-09 22:40:02       28 阅读