• Linux进程替换


    进程替换

    假如操作系统正在执行某一个程序,我们可以利用程序替换函数指定一个新的程序,让操作系统去执行我们新指定的程序。也就是这样一种情形下,我们fork一个进程,如果fork成功,子进程会和父进程执行相同的代码,而我们创建子进程是希望子进程执行指定的操作,这个要实现在本程序复制之后执行其它程序的过程,我们叫做进程替换

    要实现进程替换,我们就要使用exec系列函数

    execl

    execlp

    execle

    execv

    execvp

    execve

    其中,替换函数都是以exec开头,后面不同的字符例如:l、v、p、e代表不同的使用方法,一般有如下规律:
    l(list) : 表示参数采用列表
    v(vector) : 参数用数组
    p(path) : 有p自动搜索环境变量PATH
    e(env) : 表示自己维护环境变量

    其中只有exeve为系统调用,剩下的函数都是调用exeve

    我们在Linux中用man命令可以查看exec系列函数族

    关于execl系列函数,只是从声明来看,参数中是需要路径

    而execv系列函数则是不需要路径的

    当系统执行单个execl函数,执行一个新的进程时

    对应的虚拟地址和物理地址和磁盘对应的关系图如下

    理论部分介绍没有办法深刻理解,我们通过对exec系列函数使用进一步理解

     execl

     这个是不添加fork的单一使用的exec的使用

    可以看到execl函数的使用是 路径+参数+结尾标记

    这个结尾标记的使用是必须的

    (char*)NULL

    NULL和\0,0的意义相同,但是(char*)的强转的一定不能少的

    单单看到这一步是无法理解execl的使用的

    我们对这个程序进行编译运行

    可以看到这里运行了我们函数中声明的ps -f命令

    那么在程序中为什么没用输出 parent voer!!!

    这里我们就要和命令就行 对比来说明

    如果我们在终端中给一个错误的命令

    这里就是在提示我们错误的原因

    那么我们如果在刚刚的main程序中也给出错误的参数

    那么结果会如何呢 

     

    这里我们把参数改成lss

    看看编译运行后会有什么不同的结果

     

    我们可以看到最下面就是fork运行的结果,那么可以看到给出了错误的结果还运行了execl后面的代码

    这里就涉及了execl的底层运行

    如果给出的参数正确,那么代码到execl处就会结束

    如果给出的参数不正确,才会执行execl下方的代码 

    那么这里我们还看到一个新的输出函数  perror

    这个其实和之前学习的标准错误类似

    这个函数其实也可以用printf代替,但是用perror可以给出错误的结果

    在后续的学习中,我们也可以将perror经常运用

    然后还有一个点 这是第一次遇见

    我们对main函数进行改变

     

     

     我们运行编译之后再分析结果

    可以看到我们这里替换的是系统的ls -a命令

    我们再执行一下系统的ls -a命令

     

    这里看到系统的ls -a对于可执行程序的颜色是不同于我们替换的ls -a的颜色的

    那这是怎么回事呢

    其实这是ls的底层执行

    实际上我们使用系统的命令执行的ls 是 ls --color 

    这里其实是命令的参数执行的规则  --后面会解析为一个单次 例如ls --color

    -后面会解析为单个命令 例如 ps -ef

     然后我们修改execl的参数

    就可以达到和系统一样的效果

     

    这样就可以实现和系统一样的效果

    当然我们也可以调用我们自己编写的可执行程序

    比如这里我们编写一个简单的main程序

     

    前提是要编译出可执行程序

     

     

    可以看到这里就也可以替换成我们自己编译的main程序

    execl和fork结合

    我们之前使用的execl都是单独使用

    这里我们将execl和fork结合使用

    pid=0 说明是子进程

    那我们看看这个程序在运行时会有什么问题

     

    这里可以看到没有什么问题

    我们将程序放到后台运行

     

    这里就可以看到

    子进程比父进程先结束,产生了僵尸进程现象

    不了解僵尸进程可以翻看往期博文

    Linux——僵尸进程,文件操作_iccoke的博客-CSDN博客 

    那么我们肯定要解决这个僵尸进程问题

    我们使用wait子进程等待父进程结束并给出退出码

    我们这里并不要求获取子进程的退出码,所以我们只用wait即可

     

     可以看到我们解决了僵尸进程问题

    接下来我们可以介绍剩下的几个函数

    在execl的基础下理解就容易的多

    execlp和execvp

    这两个使用就是不用带上路径

    然后execl类 和execv类区别就是 execv的参数储存在数组中

    而execle和execve都是会加上一个环境变量

    用envp数组存储

    这里就涉及到信号问题,我们下一节再讨论

  • 相关阅读:
    JDBC教程
    第八章 贪心
    Java概述
    MySQL学习系列(10)-每天学习10个知识
    uniapp u-tabs表单如何默认选中
    代谢ADMET在线网页预测工具SwissADME 、SOMP 、BioTransformer
    [附源码]计算机毕业设计JAVAjsp教学辅助系统
    [SICTF 2023] web&misc
    基于路网层次收缩的快速分布式地图匹配算法
    JAVA 三元运算符
  • 原文地址:https://blog.csdn.net/iccoke/article/details/128043424