Linux笔记---进程:进程替换

打印 上一主题 下一主题

主题 861|帖子 861|积分 2593

1. 进程替换的概念

进程替换是指在一个正在运行的进程中,用一个新的程序替换当进步程的代码和数据,使得进程开始实行新的程序,而不是原来的程序。
这种技术通常用于在不创建新进程的情况下,改变进程的行为。
我们之前谈到过fork函数,这个函数可以启动一个子进程,子进程继承了父进程的代码和数据。
在谈到进程替换之前,我们只能通过判断fork函数的返回值id来区分父子进程,并让二者运行不同的分支。而利用进程替换技术,我们可以将子进程的代码数据完全替换为另一个程序,实现我们所盼望的,父子进程完全独立为两个不同的进程。
进程替换的原理

进程替换的原理涉及到操作体系的内存管理和进程控制。当一个进程调用exec系列函数时,操作体系会将新程序的代码和数据加载到内存中,并将其与当进步程的地址空间相关联。这个过程通常涉及到以下几个步调:
   

  • 加载新程序:操作体系将新程序的可实行文件从磁盘加载到内存中。
  • 替换代码和数据:新程序的代码和数据会替换当进步程的代码和数据段。
  • 更新进程状态:进程的状态会被更新,以反映新程序的实行状态。
  • 实行新程序:进程开始实行新程序的入口点,通常是main函数。
  在这个过程中,进程的标识符(PID)和其他一些属性(如打开的文件描述符、环境变量等)通常会保持不变。
2. exec进程替换函数

在Linux体系中,进程替换通常通过exec系列函数来实现,该系列函数包罗在头文件<unistd.h>。
这些函数包罗:
   

  • execl:实行一个新程序,参数以列表形式给出。
    1. int execl(const char *pathname, const char *arg, ...);
    复制代码
  • execlp:实行一个新程序,参数以列表形式给出,并在环境变量PATH中搜索程序。
    1. int execlp(const char *file, const char *arg, ...);
    复制代码
  • execle:实行一个新程序,参数以列表形式给出,并提供自界说的环境变量。
    1. int execle(const char *pathname, const char *arg, ...);
    复制代码
  • execv:实行一个新程序,参数以数组形式给出。
    1. int execv(const char *pathname, char *const argv[]);
    复制代码
  • execvp:实行一个新程序,参数以数组形式给出,并在环境变量PATH中搜索程序。
    1. int execvp(const char *file, char *const argv[]);
    复制代码
  • execve:实行一个新程序,参数以数组形式给出,并提供自界说的环境变量。
    1. int execve(const char *pathname, char *const argv[], char *const envp[]);
    复制代码
  • execvpe:实行一个新程序,参数以数组形式给出,并提供自界说的环境变量。
    1. int execvpe(const char *file, char *const argv[], char *const envp[]);
    复制代码
  这些函数的使用方式和参数传递方式略有不同,但它们的基本功能都是相同的:用新程序替换当进步程的代码和数据。
记忆本事:
   

  • l(list):表现参数接纳列表。
  • v(vector):参数用数组。
  • p(path):到环境变量PATH中搜索指定程序,无需完整路径(带p的函数第一个参数为file,代表可实行程序;不带p的函数第一个参数为pathname,代表完整路径)。
  • e(env) : 表现自界说环境变量,不带e的表现继承当前的环境变量。
  使用示例:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main()
  4. {
  5.     char* vector[] = {"ls", "-l", "-a", NULL};
  6.     int id = fork();
  7.     if(id == 0)
  8.     {
  9.         execvp("ls", vector);
  10.         return 0;
  11.     }
  12.     int pid = wait(NULL);
  13.     return 0;
  14. }
复制代码
 注意:传入的参数为命令行参数,也就是说在命令行要实行该程序需要输入什么,参数就传递什么,主要是不要忘记选项是从第二个参数开始的。
第一个参数传什么都不要紧,随你喜欢,但要记得传:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. int main()
  4. {
  5.     char* vector[] = {"cxk", "-l", "-a", NULL};
  6.     int id = fork();
  7.     if(id == 0)
  8.     {
  9.         execvp("ls", vector);
  10.         return 0;
  11.     }
  12.     int pid = wait(NULL);
  13.     return 0;
  14. }
复制代码
execve函数

该函数相比于其他函数具有一定的特殊性,他是上述函数中唯一一个体系调用。
在命令行输入[man exec]能查到如下信息,可以看到并没有execve的存在,且这些函数都在3号手册当中:

只有单独查询execve函数时才气查到,可以看到该函数在2号手册(体系调用接口)中:

 execve函数的特殊性:
   

  • 体系调用层级的基础地位

    • execve在exec函数族中具有特殊的基础性地位。它是直接与体系调用接口紧密相连的函数。其他的exec系列函数(如execl、execv等)在很多情况下终极可能会调用execve来实现实际的进程替换操作。
    • 例如,在一些库函数的实现中,为了提供更方便的参数传递方式(如execl的可变参数列表形式),可能会在内部对参数进行处置惩罚后调用execve来完成进程替换的核心功能。

  • 参数处置惩罚方式的不同

    • execve的参数包罗要实行的程序文件路径、传递给新程序的命令行参数数组以及环境变量数组。这种参数形式与其他exec函数有所不同。
    • 像execl函数,它的参数是以可变参数列表的形式,末了以NULL末端,这种形式在使用上有一定的便利性,但在底层实现中可能需要更多的转换工作才气与体系调用接口对接,而execve的参数形式更直接地反映了体系调用的需求。

  • 安全和权限方面的思量

    • 由于execve是直接进行进程替换的底层函数,在安全和权限管理方面有偏紧张的作用。它对可实行文件的路径、实行权限等有着严格的要求。
    • 当调用execve时,体系会根据文件的权限设置(如是否可实行、所属用户和组等)以及当进步程的权限来判断是否允许进程替换操作。这种严格的权限检查有助于保障体系的安全性。

  • 与内核交互的特点

    • execve在与内核交互时,需要将新程序的代码和数据加载到当进步程的地址空间,同时更新进程的各种状态信息,如程序计数器、堆栈指针等。这个过程涉及到内核中的进程管理、内存管理等多个模块的协同工作。
    • 相比其他exec函数,execve在与内核的这种深度交互方面更为直接,因为其他函数可能会在调用execve之进步行一些额外的参数处置惩罚或环境设置。

   exec函数族调用关系如下:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

篮之新喜

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表