Linux 进程(十) 进程替换

        用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec*函数以执行另一个程序。当进程调用一种exec*函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec*并不创建新进程,所以调用exec*前后该进程的id并未改变。

        进程属于内核数据结构,所以要对进程做修改只能通过系统调用!

替换函数 

其实有六种以exec开头的函数,统称exec函数:

#include <unistd.h>`
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);

首先我们来演示execl:

     拿execl为例子,如果想让我们的进程中执行ls -a -l 的命令与在命令行解释器上执行出的效果一样,该怎么使用这个函数呢

执行结果: 在我们写的可执行程序中也可以实现在命令行上执行出来的一样的效果。

注意:

  1. 从上面程序的执行结果可以看出,begin打印出来了,但是end并没有打印出来,说明程序一旦替换成功,exec*后续代码不在执行,因为被替换成新的代码了。
  2. exec* 只有失败返回,没有成功返回。
  3. 替换完成,不创建新的进程,我们可以通过查看前后两个进程的pid,发现没有改变,可以说明是一个进程。
  4. 创建一个进程,先创建pcb,地址空间,页表等,然后再把程序加载进来。

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

        最后一个字母p:表示PATH 表示你不用告诉系统绝对或者相对路径,只要告诉系统名字就好。系统替换的时候,会自动去PATH中寻找。

        同时命名中带“l” 的表示list 表示使用时要按照列表的形式传递,也就是一个一个的传,命名中带“v ” 的就是吧要执行的放置在一个指针数组中,然后直接把指针数组的地址传递过去。

        我们我会发现前两个参数都是 “ls” 这重复吗?不重复!!!第一个表示怎么执行程序的名,后面的就是命令行参数怎么写那里就怎么写。这就比如生活中有两个人叫一样的名字,但不能说这两个是同一个人。

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

那么如何让自己写的程序调用自己的程序呢?

首先我们来写一个简单的c++文件。

如何让make 一下生成两个可执行程序呢?

首先定义一个为目标 all 表示 该命令都是被执行,但是没有依赖方法。

如果不这样写的话make 一下只能生成一个可执行程序,因为make 会寻找第一个目标文件 并且编译成为最终文件。

这样make一下会生成两个可执行程序。 

 用我们自己写的c程序调用c++程序。

为什么这样可以呢?不管任何语言写的代码,只要运行起来都是进程!!!!!

当程序执行起来,我们可以发现程序不仅仅能够替换,也能够拿到我们的命令行参数,并且也能够打印出来。 

那么我们在子进程中替换我们的程序,看一看子进程是否会继承父进程的环境变量呢?

#include<iostream>
using namespace std;
#include <unistd.h>int main(int agrc,char* argv[])
{for(int i = 0;environ[i];i++){printf("environ[%d]:%s\n",i,environ[i]);}cout << "hello c++"<<endl;cout << "hello c++"<<endl;cout << "hello c++"<<endl;cout << "hello c++"<<endl;cout << "hello c++"<<endl;cout << "hello c++"<<endl;cout << "hello c++"<<endl;return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>int main()
{printf("i am a process, pid:%d\n",getpid());pid_t id = fork();if(id == 0){execl("./mytest","mytest","-a","-b","-c",NULL);printf("############## end   ################\n");}pid_t rid = waitpid(id,NULL,0);if(id > 0){printf("wait success:rid:%d\n",rid);}return 0;
}

通过以上的执行结果我们可以看出子进程确实可以继承父进程的环境变量。

默认可以通过进程地址空间继承的方式,让所有的子进程拿到环境变量。

进程程序替换不会替换环境变量的数据。

综上所诉:子进程默认能够继承父进程的环境变量。

如果要新增环境变量就要使用 putenv

putenv("MYVAL=bbbbbbbbbbbbbbbbbbbbbbbbbbbb");

如果单纯想要子进程继承新的环境变量呢?

int execle(const char *path, const char *arg, ...,char *const envp[]);

这时就要使用我们的程序调用函数了,首先我们需要自己定义一个环境变量表,然后使用程序替换的时候传进去。

执行结果如下,这样我们替换的程序就能够拿到我们自己定义的环境变量了 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/324398.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国诗歌史上的九座高峰

中国是诗的国度&#xff0c;诗歌在中国的影响远远大于其他文学艺术的影响力。自古以来&#xff0c;诗在我们的精神世界里占据着重要的位置&#xff0c;而且几乎人人都会吟诵古诗。 作为中国古诗的爱好者&#xff0c;认为许多的排名有局限性&#xff0c;只是从个人的爱好出发。…

Python新年烟花代码

Pygame 绘制烟花的基本原理 1&#xff0c;发射阶段&#xff1a;在这一阶段烟花的形状是线性向上&#xff0c;通过设定一组大小不同、颜色不同的点来模拟“向上发射” 的运动运动&#xff0c;运动过程中 5个点被赋予不同大小的加速度&#xff0c;随着时间推移&#xff0c;后面的…

JDBC数据库访问——数据库操作

与指定的数据库建立连接后&#xff0c;就可以使用JDBC提供的API对数据库进行操作&#xff0c;包括查询、新增、更新、删除等。 1.查询操作 和数据库建立连接后&#xff0c;对数据库表进行查询操作的步骤如下&#xff1a; ①创建statement对象 由已创建的Connection对象con调…

js逆向第8例:猿人学第1题-js 混淆-源码乱码

题目1:抓取所有(5页)机票的价格,并计算所有机票价格的平均值,填入答案。 老规矩打开控制台调试,出现debugger 过掉这个很简单了,右键点击“一律不在此处暂停” 这样就可以查看具体的网络请求如下: m是加密值,熟悉的大佬能发现这串加密字符非常像md5,|后面的就是时…

抓包工具:fiddler和wireshark对比

了解过网络安全技术的人都知道一个名词“抓包”。那对于局外人&#xff0c;一定会问什么是抓包&#xff1f;考虑到&#xff0c;大家的技术水平不一&#xff0c;我尽可能用非专业的口吻简单的说一下。 抓包就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作&a…

【Leetcode】2487. 从链表中移除节点

文章目录 题目思路代码 题目 2487. 从链表中移除节点 思路 1、递归移除节点&#xff1a; 如果头节点为空&#xff0c;直接返回空。递归调用函数处理下一个节点 head->next。在递归返回后&#xff0c;判断当前节点的值是否小于之前记录的最大值 maxVal。如果小于 maxVal…

力扣1944.队列中可以看到的人数--单调栈

思路&#xff1a; 由题知一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 矮 &#xff0c;也就是说&#xff0c;在自己右边第一个比自己高的人后面的人就肯定看不到了那么只需要找到右边第一个比自己高的人与自己之间的所有满足要求的人就行了&#xff0…

【Python可视化实战】钻石数据可视化

一、项目引言 1.背景和目标 钻石作为一种珍贵的宝石&#xff0c;其价格受到多种因素的影响。为了深入了解钻石价格的决定因素&#xff0c;我们收集了大量关于钻石的数据&#xff0c;并希望通过数据可视化来揭示钻石特征与价格之间的关系。 2.内容 收集钻石的各项特征数据&a…

QT5.14 实现ModbusTCP客户端 Demo

本文在QT5.14平台&#xff0c;基于QModbusClientTcp类&#xff0c;实现了客户端对单个寄存器的读写&#xff0c;用ModbusSlave做服务器做测试。 1.界面 (1)更改读按钮的名称为bt_Read (2)更改写按钮的名称为bt_Write 2.修改pro文件的第三行 greaterThan(QT_MAJOR_VERSION, 4)…

UE5 C++(十一)— 碰撞检测

文章目录 代理绑定BeginOverlap和EndOverlapHit事件的代理绑定碰撞设置 代理绑定BeginOverlap和EndOverlap 首先&#xff0c;创建自定义ActorC类 MyCustomActor 添加碰撞组件 #include "Components/BoxComponent.h"public:UPROPERTY(VisibleAnywhere, BlueprintRea…

vmware安装centos 7.6 操作系统

vmware安装centos 7.6 操作系统 1、下载centos 7.6 操作系统镜像文件2、安装centos 7.6操作系统3、配置centos 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载centos 7.6 操作系统镜像文件 这里选择 2018年10月发布的 7.6 版本 官方下载链…

1月5日代码随想录完全二叉树的节点个数

222.完全二叉树的节点个数 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在…