Linux进程控制——Linux进程程序替换

news2024/11/14 19:02:15

前言:Linux进程控制包含了进程终止,进程等待,进程程序替换。走到现在我们也只剩下进程程序替换没介绍了,那么让我们来看看进程程序替换到底是什么!


在这里插入图片描述


本篇主要内容:
替换原理
替换函数
实现简易shell

在这里插入图片描述


我们所创建的所有的子进程,执行的代码,都是父进程代码的一部分,如果我们想让子进程执行新的程序,执行全新的代码和访问全新的数据,不在和父进程有瓜葛这就要用到我们的进程替换了!!!


进程程序替换

  • 1. 替换原理
  • 2. 替换函数
    • 2.1 execl类型函数
    • 2.2 execv类型函数
  • 3. 实现简易shell
  • 4. 总结


1. 替换原理

我们先介绍一个exec函数,方便我们读下面的代码
execl:
在这里插入图片描述
我们直接来看代码分析:

  1 #include <stdio.h>
  2 #include <sys/types.h>                                                                                                                                                                 
  3 #include <unistd.h>
  4 #include <wait.h>
  5 int main()
  6 {
  7     pid_t id = fork();
  8     if(id == 0)
  9     {
 10         printf("pid: %d, exec command begin\n", getpid());
 11         sleep(2);
 12         execl("/usr/bin/ls", "ls", "-a", "-l", NULL);
 13         printf("pid: %d, exec command end\n", getpid());
 14     }
 15     else{
 16         pid_t rid = waitpid(-1, NULL, 0);
 17         if(rid > 0)
 18         {
 19             printf("wait success, pid: %d\n", rid);
 20         }
 21     }
 22     return 0;
 23 }

在这里插入图片描述

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

  • 操作系统在调用exec函数时,只要将整个进程的代码和数据用新程序的代码和数据进行替换。
  • 子进程往往会共享父进程的代码和数据,因为有写时拷贝的技术,有新数据写入时,会重新开辟空间所以不会相互影响,保证父子进程的独立性。

在这里插入图片描述


但是我们仔细查看代码和执行结果后发现,竟然有一段代码没有执行!

13  printf("pid: %d, exec command end\n", getpid());

其实是调用exec程序替换,只要exec替换新程序成功了,子进程就回去执行新的程序,因此后面的代码将不会被执行


2. 替换函数

在进程程序替换中,替换函数必不可少,让我们来看看这类函数!

在这里插入图片描述

RETURN VALUE:
The exec() functions error has occurred return only if an The return value is -1 and errno to indicate the error

而exec开头的函数一共介绍6种,它们只会在出错时返回 -1!

我们以一下两点来理解:

  • 必须先找到这个可执行程序怎么执行
  • 必须告诉exec,怎么执行*

2.1 execl类型函数

在这里插入图片描述
在这里插入图片描述

execl我们在上面简单了解了,我们就介绍一下剩下两个

execlp:
在这里插入图片描述

int main()
{
    {
        printf("pid: %d, exec command begin\n", getpid());
        sleep(2);
        execlp("ls", "ls", "-a", "-l", NULL);  
        //第一个ls代表怎么找到这个程序 
        //第二个ls其实是命令的一部分,对应怎么执行                                                                                                                                    
        printf("pid: %d, exec command end\n", getpid());
                     
    }                                              
    return 0;                          
}  

在这里插入图片描述

在使用execlp函数时,我们并没有加上路径,但是我们依然能够获得想要的结果,正是因为p代表了PATH他会自动去环境变量PATH中根据file来寻找可执行程序!!!


execlpe:
在这里插入图片描述

// mytest源代码
int main()
{
    char *const myenv[] = {
         "myenv1=2004",
         "myenv2=2005",
         "myenv3=2005",
         "myenv4=2005",
          NULL
    };                                                                                                                                                                               
    printf("exec command begin\n");
    execle("./myprocess", "myprocess", NULL, myenv);


// myprocess源代码
int main(int agrc, char *agrv[], char *env[])
{
    for(int i = 0; env[i]; i++)
    {
        printf("[%d]: %s\n", i, env[i]);
    }
    return 0;
} 

在这里插入图片描述
这是exec*函数程序替换,我们在下文会讲


2.2 execv类型函数

execv其实就是在execl的基础上多了一个指针数组,情况大差不差我们就不具体介绍了!具体关系如下图:
在这里插入图片描述

在这里插入图片描述
execv 和 execvp:
在这里插入图片描述

int main()
{
	char *const argv[] = {
		"ls",
		"-a",
		"-l",
		NULL
	};
    printf("pid: %d, exec command begin\n", getpid());
    sleep(2);
    execv("/usr/bin/ls", argv);       
    //execvp("ls", argv);                                                                                                                         
    printf("pid: %d, exec command end\n", getpid());  
      
    return 0;                          
}  

在这里插入图片描述

其实exec这类函数命令有一定的规律:

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

在这里插入图片描述


3. 实现简易shell

我们用程序替换是可以用C语言把C++调用起来的

// test.c
int main()
{
    printf("pid: %d, exec command begin\n", getpid());
    execl("./myprocess", "myprocess", NULL);                                                                                                                               
    return 0;
}

// test.cc
int main()
{
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;                                                                                                                                             
    return 0;
}

Makefile:

.PHONY:all
 all:mytest myprocess
 
 myprocess:test.cc
     g++ -o $@ $^ -std=c++11
  
 mytest:test.c
     gcc -o $@ $^ -std=c99
     
.PHONY:clean
clean:
     rm -f mytest myprocess 

因为我们要同时编译两个程序,所以我们要对Makefile进行一下调整

在这里插入图片描述

我们通过程序替换将C++用C语言调用起来了


那我们除了调用C++还能调用别的嘛?

  • 显而易见当然是可以的!!!
// test.sh
// 会简单编写就好
#!/usr/bin/bash
echo "hello Linux"
echo "hello world"
touch code

// test.c
int main()
{
    printf("pid: %d, exec command begin\n", getpid());
    execl("/usr/bin/bash", "bash", "test.sh", NULL);                                                                                                                               
    return 0;
}

在这里插入图片描述

当然除了我们讲的这两个,其实所有语言都能通过进程程序替换来调用,因为我们用任意语言写的程序都会变成进程,只要是进程就都可以用exec*来替换——系统大于一切


4. 总结

进程程序替换能够让我们只用C语言就可以调用其他任何语言去执行,极大程度上带来了便利,也可以帮助我们完成很多任务,好了,关于Linux进程控制我们先了解到这,下次我们将进入新的章节!

谢谢大家支持本篇到这里就结束了
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux FT260驱动内核学习笔记

目录 1. 安装ft260驱动 2. 编译ft260源码 3. 通过sysfs配置ft260设备 3.1 多功能GPIO配置 3.2 控制GPIO 3.3 配置i2c总线频率 4. UART 5. 使用i2c-tools交互I2C设备 5.1 安装i2c-tools 5.2 探测I2C设备 5.3 读取所有寄存器数据 5.4 读取和写入 5.5 16位地址的读写…

私活更好用:SpringBoot开源项目!!【送源码】

今天分享一款非常香的SpringBoot大屏开源项目&#xff0c;非常适合接私活用。 这是一款基于SpringBoot代码生成器的快速开发平台&#xff01;采用前后端分离架构&#xff1a;SpringBoot&#xff0c;Mybatis&#xff0c;Shiro&#xff0c;JWT&#xff0c;Vue&Ant Design。强…

C++ 日志库 log4cpp 编译、压测及其范例代码 [全流程手工实践]

文章目录 一、 log4cpp官网二、下载三、编译1.目录结构如下2.configure 编译3.cmake 编译 四、测试五、压测源码及结果1.运行环境信息2.压测源码3.压测结果 文章内容&#xff1a;包含了对其linux上的完整使用流程&#xff0c;下载、编译、安装、测试用例尝试、以及一份自己写好…

使用VMware或VirtualBox安装eNSP Pro并使用CRT连接设备

文章目录 使用Oracle Virtual Box安装eNSP Pro创建虚拟机配置网卡配置带外管理网络 使用VMware Workstation安装eNSP Pro转换文件格式及虚拟磁盘模式配置网卡创建虚拟机配置使用CRT连接管理设备 前一段时间是开放了eNSP Pro的账号权限&#xff0c;但是在写博客时&#xff0c;权…

[董晓算法]搜索相关题目及模板

前言&#xff1a; 本系列是学习了董晓老师所讲的知识点做的笔记 董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com) 动态规划系列&#xff08;还没学完&#xff09; 【董晓算法】动态规划之线性DP问题-CSDN博客 【董晓算法】动态规划之背包DP问题&#xff…

html--互动星空

<!doctype html> <html> <head> <meta charset"utf-8"> <title>互动星空</title><style> html,body {margin:0;overflow:hidden;width:100%;height:100%;cursor:none;background:black;background:linear-gradient(to bot…

第十四届蓝桥杯大赛软件赛国赛C/C++ 大学 B 组 拼数字

//bfs只能过40%。 #include<bits/stdc.h> using namespace std; #define int long long int a,b,c,dp[2028]; struct s {int x,y,z;string m; }; map<vector<int>,int>k; signed main() {ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>a…

大模型时代下的先行者:景联文科技引领数据标注新时代

在大模型时代&#xff0c;数据标注不再是简单的分类标注&#xff0c;而是一项融合了技术革新、专业技能、法律合规和精细化管理的综合性任务&#xff0c;对推动AI技术的发展和落地应用具有重要意义。 景联文科技作为AI基础行业的数据供应商&#xff0c;可协助人工智能企业解决整…

使用 cloudflare 免费服务,搭建临时邮箱,无需暴露自己的真实邮箱地址,保护个人隐私

使用 cloudflare 免费服务&#xff0c;搭建临时邮箱 地址 在线演示 &#x1f310;Github地址 https://github.com/find-xposed-magisk/cloudflare_temp_email 功能/TODO Cloudflare D1 作为数据库 使用 Cloudflare Pages 部署前端 使用 Cloudflare Workers 部署后端 email 转…

【合成孔径雷达】合成孔径雷达的多视角理解和时/频成像算法的统一解释

文章目录 一、什么是雷达成像&#xff08;1&#xff09;主要的遥感探测手段&#xff1a;光学、红外和雷达&#xff08;2&#xff09;从数学的角度&#xff1a;雷达成像主要研究什么&#xff1f;数据采集&#xff1a; y T x n yTxn yTxn信息提取&#xff1a; y − > x ? y…

【Image captioning】基于检测模型网格特征提取——以Sydeny为例

【Image captioning】基于检测模型网格特征提取——以Sydeny为例 今天,我们将重点探讨如何利用Faster R-CNN检测模型来提取Sydeny数据集的网格特征。具体而言,这一过程涉及通过Faster R-CNN模型对图像进行分析,进而抽取出关键区域的特征信息,这些特征在网格结构中被系统地…

鸿蒙HarmonyOS开发:List组件结合Badge、swipeAction实现微信消息列表侧滑删除效果

文章目录 一、ListItem的swipeAction属性二、Badge组件三、Search组件四、示例代码五、效果 一、ListItem的swipeAction属性 名称参数类型描述swipeAction{start?: CustomBuilder,end?:CustomBuilder,edgeEffect?: SwipeEdgeEffect,}用于设置ListItem的划出组件。- start: …

[数据集][目标检测]纸箱子检测数据集VOC+YOLO格式8375张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8375 标注数量(xml文件个数)&#xff1a;8375 标注数量(txt文件个数)&#xff1a;8375 标注…

Zynq UltraScale+ RFSoC 配置存储器器件

Zynq UltraScale RFSoC 配置存储器器件 下表所示闪存器件支持通过 Vivado 软件对 Zynq UltraScale RFSoC 器件执行擦除、空白检查、编程和验证等配置操 作。 本附录中的表格所列赛灵思系列非易失性存储器将不断保持更新 &#xff0c; 并支持通过 Vivado 软件对其中所列…

Spring编程使用DDD的小把戏

场景 现在流行充血领域层&#xff0c;在原本只存储对象的java类中&#xff0c;增加一些方法去替代原本写在service层的crud&#xff0c; 但是例如service这种一般都是托管给spring的&#xff0c;我们使用的ORM也都托管给spring&#xff0c;这样方便在service层调用mybatis的m…

PostgreSQL扩展之PGroonga:多语言全文搜索

简介 PGroonga 是一个 PostgreSQL 扩展&#xff0c;它增加了基于 Groonga 的全文搜索索引方法。虽然原生的 PostgreSQL 支持全文索引&#xff0c;但它仅限于基于字母和数字的语言。PGroonga 提供了更广泛的字符支持&#xff0c;使其成为 PostgreSQL 支持的语言的超集&#xff…

malloc_consolidate

此文章用于详细介绍malloc_consolidate。 众所周知&#xff0c;fastbin一般是不能合并&#xff0c;但在malloc_consolidate中是个例外。 1.触发机制 首先构造这样的堆块结构 一个0x40的堆块在fastbin中&#xff0c;一个0x110的堆块在unbin中 随后我们尝试分配一个0x300的堆…

NSSCTF | [SWPUCTF 2021 新生赛]easyupload2.0

先传一个普通的一句话木马试一试 GIF89a <?php eval($_POST[shell]);?> 可以看到回显&#xff0c;不允许上传php文件。 使用Burpsuite抓包只修改ContentType后发现也不能绕过&#xff0c;说明服务器使用了黑名单后缀限制&#xff0c;那么我们可以使用其他的后缀代替ph…

ubuntu CUDA 驱动更新,版本更新,多CUDA版本管理

1 新版本驱动下载 前面介绍过window CUDA驱动更新&#xff0c;但是对于ubuntu 的驱动更新&#xff0c;没有一键操作。 本人笔记本电脑n年前装的CUDA DRIVER仅支持到cuda10.2&#xff0c;实在无法满足这日新月异的科技更新。 左 旧的驱动版本 右 新下载的硬件支持的驱动版本&…

使用RN的kitten框架的日历组件的修改

官方网页地址 下面就是我参考官方封装的时间日期组件&#xff08;主要是功能和使用方法&#xff0c;页面粗略做了下&#xff0c;不好看勿怪&#xff09; import React, {useState} from react; import {StyleSheet, View, TouchableOpacity, SafeAreaView} from react-native; …