【Linux系统】进程替换 自主实现shell(简易版)

1.先看代码 && 现象

 我们用exec*函数执行新的程序,

exec*系列的函数,执行完毕后,后续的代码不见了,因为被替换了。

execl的返回值可以不关心了,只要替换成功,就不会向后继续运行,只要继续运行了,一定是替换失败了!

2.解释原理

 进程 = 内核数据结构 + 代码数据

进程的程序替换,有没有创建新的进程?? 没有的

站在被替换进程的角度:本质就是这个程序被加载到内存了!

怎么加载?exec*类似于Linux上的加载函数

3.将代码改成多进程版

fork创建子进程,让子进程自己去替换,wait等待

创建子进程,让子进程完成任务:

  1. 让子进程执行父进程代码的一部分
  2. 让子进程执行一个全新的程序

4.使用所有的替换方法,并且认识函数参数的含义

下面我们查的是这些替换方法,用man 3 execl

3手册是c语言的标准库GNU标准,所以我们实际查的是几个内含系统调用的c语言函数。

 

 这是6个exec*系列函数。

 第一个execl函数:

path:我们要执行的程序,需要带路径(怎么找到程序你得告诉我)

exec后面的l -- list:就是要存放的选项列表,在命令行中怎么执行,你就怎么传参!ls -a -l 

execl("/usr/bin/ls", "ls", "-a", "-l", NULL);

路径代表你想执行谁,选项代表你想怎么执行!!!

带l的是我们要传入一个列表选项,那么带v的呢?

 v:有动态数组的意思。

 明显是要我们传入一个数组,这个数组就包含我们想要的选项,

 带p的exec函数:

用户可以不传要执行的文件的路径(但是文件名要传),直接告诉exec*,我要执行谁就行

p:查找这个程序,系统会自动在环境变量PATH中进行查找。

 

 e:environment环境变量。

envp[]:整体替换所有的环境变量!

  1. 用全新的给子进程。
  2. 用老的环境变量给子进程,environ。
  3. 老的环境变量稍微修改,给子进程。

上面的程序替换 ,我们替换的都是系统命令,可不可以替换我们自己写的程序呢?

支持不同的应用场景!!!

当然可以。 而且可以替换用任何语言写的无论是c++,java,python等语言都可进行替换,替换之后原程序pid不会改变,创建的子进程也不会改变,因为进程的替换,只是代码和数据的替换,不影响原程序的pcb。

系统调用接口execve。

 上面的函数最终都将会走到系统调用接口。

5.写一个自己的Shell(简易版)

#include<stdio.h>    
#include<stdlib.h>    
#include<string.h>    
#include<ctype.h>    
#include<unistd.h>    
#include<errno.h>    
#include<sys/types.h>    
#include<sys/wait.h>    #define SIZE 512    
#define ZERO '\0'    
#define SEP " "    
#define NUM 32    
#define SkipPath(p) do{p += (strlen(p)-1);while(*p != '/')--p;}while(0)    char cwd[SIZE * 2];    
char* gArgv[NUM];    
int lastcode = 0;    void Die()    
{    exit(1);    
}    
const char* GetHome()    
{    const char* home = getenv("HOME");                                                                                                                                                   if(home == NULL) return "None";    return home;    
}    
const char* GetUserName()
{    const char* username = getenv("USER");if(username == NULL) return "None";return username;
}const char* GetHostName()
{const char* hostname = getenv("HOSTNAME");if(hostname == NULL) return "None";return hostname;
}const char* GetCwd()
{const char* cwd = getenv("PWD");if(cwd == NULL) return "None";return cwd;
}
//commandline:output
void MakeCommandLineAndPrint()
{char line[SIZE];const char* username = GetUserName();const char* hostname = GetHostName();const char* cwd = GetCwd();const char* GetCwd()
{const char* cwd = getenv("PWD");if(cwd == NULL) return "None";return cwd;                                                                                                                                                                          
}
//commandline:output
void MakeCommandLineAndPrint()
{char line[SIZE];const char* username = GetUserName();const char* hostname = GetHostName();const char* cwd = GetCwd();SkipPath(cwd);snprintf(line, sizeof(line), "[%s@%s %s]>", username, hostname, strlen(cwd) == 1 ? "/" : cwd + 1);printf("%s", line);fflush(stdout);
}
int GetUserCommand(char command[], size_t n)
{char* s = fgets(command, n, stdin);if(s == NULL) return -1;command[strlen(command) - 1] = ZERO;return strlen(command);
}
void SplitCommand(char command[], size_t n)
{(void)n;//"ls -a -l" ->  "ls", "-a", "-l"gArgv[0] = strtok(command, SEP);int index = 1;                                                                                                                                                                       while((gArgv[index] = strtok(NULL, SEP)))index++;// done, 故意写成=,表示先赋值,在判断,分割之后,strtok会返回NULL,刚好让gArgv最后一个元素是NULL,并且while判断结束
}void ExecuteCommand()
{pid_t id = fork();if(id < 0) Die();else if(id == 0){//childexecvp(gArgv[0], gArgv);exit(errno);}else {//fatherint status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){lastcode = WEXITSTATUS(status);if(lastcode != 0) printf("%s:%s:%d\n", gArgv[0], strerror(lastcode), lastcode);}}
}
void Cd()
{const char* path = gArgv[1];if(path == NULL) path = GetHome();//path一定存在chdir(path);//刷新环境变量char temp[SIZE * 2];getcwd(temp, sizeof(temp));snprintf(cwd, sizeof(cwd), "PWD=%s", temp);putenv(cwd);//ok
}
int CheckBuildin()
{int yes = 0;const char* enter_cmd = gArgv[0];if(strcmp(enter_cmd, "cd") == 0){yes = 1;Cd();}else if(strcmp(enter_cmd, "echo") == 0 && strcmp(gArgv[1], "$?") == 0){yes = 1;printf("%d\n", lastcode);lastcode = 0;}return yes;
}
int main()
{int quit = 0;while(!quit)                                                                                                                                                                         {//1.我们需要输出一个命令行MakeCommandLineAndPrint();//2.获取用户命令行字符串char usercommand[SIZE];int n = GetUserCommand(usercommand, sizeof(usercommand));if(n <= 0) return 1;//3.命令行字符串分割SplitCommand(usercommand, sizeof(usercommand));//4.检测命令是否是内键命令n = CheckBuildin();if(n) continue;//5,执行命令ExecuteCommand();}return 0;
}

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

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

相关文章

单片机是否有损坏,怎沫判断

目录 1、操作步骤&#xff1a; 2、单片机损坏常见原因&#xff1a; 3、 单片机不工作的原因&#xff1a; 参考&#xff1a;细讲寄存器读写与Bit位操作原理--单片机C语言编程Bit位的与或非屏蔽运算--洋桃电子大百科P019_哔哩哔哩_bilibili 1、操作步骤&#xff1a; 首先需要…

前置章节-熟悉Python、Numpy、SciPy和matplotlib

目录 一、编程环境-使用jupyter notebook 1.下载homebrew包管理工具 2.安装Python环境 3.安装jupyter 4.下载Anaconda使用conda 5.使用conda设置虚拟环境 二、学习Python基础 1.快排的Python实现 (1)列表推导-一种创建列表的简洁方式 (2)列表相加 2.基本数据类型及运…

Navicat上新啦

前言 Navicat&#xff0c;在数据库界&#xff0c;几乎是一个神奇的存在&#xff0c;似乎统治了数据库开发工具的“一片天”。且看下图&#xff1a; 红的蓝的绿的橙的…&#xff0c;可以说&#xff0c;留给它的color不多了。 那么商业BI到服务监控、从云托管到云协作&#xff…

最强文生图模型Stable Diffusion 3 Medium 正式开源

Stability AI 宣布 Stable Diffusion 3 Medium 现已开源&#xff0c;是 Stable Diffusion 3 系列中最新、最先进的文本生成图像 AI 模型 —— 官方声称是 “迄今为止最先进的开源模型”&#xff0c;其性能甚至超过了 Midjourney 6。 Stable Diffusion 3 Medium 模型规格参数达到…

【鸿蒙学习笔记】位置设置

官方文档&#xff1a;位置设置 目录标题 align&#xff1a;子元素的对齐方式direction&#xff1a;官方文档没懂&#xff0c;看图理解吧 align&#xff1a;子元素的对齐方式 Stack() {Text(TopStart)}.width(90%).height(50).backgroundColor(0xFFE4C4).align(Alignment.TopS…

Spring+Vue集成AOP系统日志

新建logs表 添加aop依赖 <!-- aop依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 新建获取ip地址工具类 import javax.servlet.http.H…

昇思25天学习打卡营第12天|ShuffleNet图像分类

1. 学习内容复盘 ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&a…

自然语言处理:第三十八章: 开箱即用的SOTA时间序列大模型 -Timsfm

自然语言处理:第三十八章: 开箱即用的SOTA时间序列大模型 -Timsfm 文章链接:[2310.10688] A decoder-only foundation model for time-series forecasting (arxiv.org) 项目链接: google-research/timesfm: TimesFM (Time Series Foundation Model) is a pretrained time-ser…

【FFmpeg】avformat_alloc_output_context2函数

【FFmpeg】avformat_alloc_output_context2函数 1.avformat_alloc_output_context21.1 初始化AVFormatContext&#xff08;avformat_alloc_context&#xff09;1.2 格式猜测&#xff08;av_guess_format&#xff09;1.2.1 遍历可用的fmt&#xff08;av_muxer_iterate&#xff0…

C : 线性规划例题求解

Submit Page TestData Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 93 Solved: 49 Description 求解下述线性规划模型的最优值min &#xfffd;1&#xfffd;1&#xfffd;2&#xfffd;2&#xfffd;3&#xfffd;3&#xfffd;.&#xfffd;. &…

【SkiaSharp绘图13】SKCanvas方法详解(二)填充颜色、封装对象、高性能绘制、点(集)(多段)线、圆角矩形、Surface、沿路径绘制文字

文章目录 SKCanvas方法DrawColor 填充颜色DrawDrawable 绘制封装对象DrawImage 高性能绘制图像SKBitmap与SKImage对比DrawPicture 绘制图像SKPicture DrawPoint / DrawPoints 绘制点DrawRoundRect/DrawRoundRectDifference绘制圆角矩形DrawSurface 绘制SurfaceDrawTextOnPath沿…

Android - 利用 jitpack 免费发布闭源 aar

一、简述 目前(Android/java) library 的主要发布仓库有 MavenCentral 和 jitpack,我之前也对这两种仓库的发布流程做了详细介绍: 发布至 MavenCentral: https://juejin.cn/post/6953598441817636900发布至 jitpack: https://juejin.cn/post/7040733114506674183#heading-…

C# 入门—实现 Hello, World!

目录 一、.net 平台与.NET Framework框架 .NET Framework的构成 CLR&#xff1a;公共语言运行库 FCL&#xff1a;框架类库 WinForms ASP.NET ADO.NET WPF WCF WF LINQ Entity Framework Parallel LINQ 二、.net 能干什么 .net 两种交互模式 .net 能干什么 .net …

优化模型验证30:多车场车辆路径问题模型及Gurobipy验证

目录 1 数学模型 1.1 用到的符号集合 1.2 模型公式 2 模型验证代码 2.1 Gurobipy代码 2.2 结果可视化 多车场车辆路径问题的定义:大型的物流公司拥有多个车场,而每个车场都有若干车辆用于配送,决策者需要根据客户的所在位置,将客户分配到合适的车场和车辆中。 1 数学模…

c++静态成员变量和静态成员函数

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 我们可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成…

华为云鲲鹏架构docker部署2048小游戏

华为云鲲鹏架构docker部署2048小游戏 1. 鲲鹏架构ESC2. 配置docker3. 上传2048镜像4. 删除容器,镜像 1. 鲲鹏架构ESC 2. 配置docker 安装dockeryum -y install docker开机启动 systemctl enable docker启动docker服务 systemctl start docker查询docker的运行版本 docker -v3…

注意力机制之ECA-Net:Efficient Channel Attention for Deep Convolutional Neural Network

论文link&#xff1a;link code&#xff1a;code 1.摘要 近年来&#xff0c;通道注意机制被证明在改善深层卷积神经网络&#xff08;CNN&#xff09;的性能方面提供了巨大的潜力。然而现有的大多数方法都致力于开发更复杂的注意模块以获得更好的性能&#xff0c;这不可避免地增…

1.linux操作系统CPU负载

目录 概述CPU平均负载查看平均负载结束 概述 CPU 使用率 和CPU 平均使用率。 CPU平均负载 单位时间内系统处于 [可运行状态] 和 [不可中断状态] 的平均进程数&#xff0c;就是平均活跃进程数&#xff0c;和CPU使用率并没有直接关系 可运行状态 正在使用CPU或者正等待CPU的进…

从头开始构建一个小规模的文生视频模型

OpenAI 的 Sora、Stability AI 的 Stable Video Diffusion 以及许多其他已经发布或未来将出现的文本生成视频模型&#xff0c;是继大语言模型 (LLM) 之后 2024 年最流行的 AI 趋势之一。 在这篇博客中&#xff0c;作者将展示如何将从头开始构建一个小规模的文本生成视频模型&a…

C# 实现websocket双向通信

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C# &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff…