shell原理

news2024/11/24 16:28:31

shell 是个进程 , exe在user/bin/bash 


[用户名@主机名 pwd]

snprintf

fflush(stdout),在没有\n情况下立马输出


strtok 第一个参数null表示传入上个有效参数

命令行中,有些命令必须由子进程执行, 如ls
有些命令不能由子进程执行,要shell自己执行(内建命令), 如cd

cd命令不能让子进程更改,只能shell本身执行cd,才能改变自己的路径

内建命令:shell自己执行命令,即shell调用自己函数,如chdir

 

shell中的环境变量是由shell自己维护,例如chdir后env中的PWD不会变,要我们自己更新维护

export就是在增添shell环境变量


本地变量不可被子进程继承(没有此方法,main没有接受父进程本地变量的功能/参数)

实现shell源代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;
// 全局的命令行参数表
char *gargv[argvnum];
int gargc = 0;

// 我的系统的环境变量
char *genv[envnum];

// 全局的当前shell工作路径 
char pwd[basesize];
char pwdenv[basesize];

string GetUserName()
{
    string name = getenv("USER");
    return name.empty() ? "None" : name;
}

string GetHostName()
{
    string hostname = getenv("HOSTNAME");
    return hostname.empty() ? "None" : hostname;
}

string GetPwd()
{
    if(nullptr == getcwd(pwd, sizeof(pwd))) return "None";
    snprintf(pwdenv, sizeof(pwdenv),"PWD=%s", pwd);
    putenv(pwdenv); // PWD=XXX
    return pwd;

    //string pwd = getenv("PWD");
    //return pwd.empty() ? "None" : pwd;
}

string MakeCommandLine()
{
    // [whb@bite-alicloud myshell]$ 
    char command_line[basesize];
    snprintf(command_line, basesize, "[%s@%s %s]# ",\
            GetUserName().c_str(), GetHostName().c_str(), GetPwd().c_str());
    return command_line;
}

void PrintCommandLine() // 1. 命令行提示符
{
    printf("%s", MakeCommandLine().c_str());
    fflush(stdout);
}

bool GetCommandLine(char command_buffer[], int size)   // 2. 获取用户命令
{
    // 我们认为:我们要将用户输入的命令行,当做一个完整的字符串
    // "ls -a -l -n"
    char *result = fgets(command_buffer, size, stdin);
    if(!result)
    {
        return false;
    }
    command_buffer[strlen(command_buffer)-1] = 0;
    if(strlen(command_buffer) == 0) return false;
    return true;
}

void ParseCommandLine(char command_buffer[], int len) // 3. 分析命令
{
    (void)len;
    memset(gargv, 0, sizeof(gargv));
    gargc = 0;
    // "ls -a -l -n"
    const char *sep = " ";
    gargv[gargc++] = strtok(command_buffer, sep);
    // =是刻意写的
    while((bool)(gargv[gargc++] = strtok(nullptr, sep)));
    gargc--;
}

void debug()
{
    printf("argc: %d\n", gargc);
    for(int i = 0; gargv[i]; i++)
    {
        printf("argv[%d]: %s\n", i, gargv[i]);
    }
}
// 在shell中
// 有些命令,必须由子进程来执行
// 有些命令,不能由子进程执行,要由shell自己执行 --- 内建命令 built command
bool ExecuteCommand()   // 4. 执行命令
{
    // 让子进程进行执行
    pid_t id = fork();
    if(id < 0) return false;
    if(id == 0)
    {
        //子进程
        // 1. 执行命令
        execvpe(gargv[0], gargv, genv);
        // 2. 退出
        exit(1);
    }
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if(rid > 0)
    {
       // Do Nothing
       return true;
    }
    return false;
}

void AddEnv(const char *item)
{
    int index = 0;
    while(genv[index])
    {
        index++;
    }

    genv[index] = (char*)malloc(strlen(item)+1);
    strncpy(genv[index], item, strlen(item)+1);
    genv[++index] = nullptr;
}
// shell自己执行命令,本质是shell调用自己的函数
bool CheckAndExecBuiltCommand()
{
    if(strcmp(gargv[0], "cd") == 0)
    {
        // 内建命令
        if(gargc == 2)
        {
            chdir(gargv[1]);
        }
        return true;
    }
    else if(strcmp(gargv[0], "export") == 0)
    {
        // export也是内建命令
        if(gargc == 2)
        {
            AddEnv(gargv[1]);
        }
        return true;
    }
    else if(strcmp(gargv[0], "env") == 0)
    {
        for(int i = 0; genv[i]; i++)
        {
            printf("%s\n", genv[i]);
        }
        return true;
    }
    return false;
}

// 作为一个shell,获取环境变量应该从系统的配置来
// 我们今天就直接从父shell中获取环境变量
void InitEnv()
{
    extern char **environ;
    int index = 0;
    while(environ[index])
    {
        genv[index] = (char*)malloc(strlen(environ[index])+1);
        strncpy(genv[index], environ[index], strlen(environ[index])+1);
        index++;
    }
    genv[index] = nullptr;
}

int main()
{
    InitEnv();
    char command_buffer[basesize];
    while(true)
    {
        PrintCommandLine(); // 1. 命令行提示符
        // command_buffer -> output
        if( !GetCommandLine(command_buffer, basesize) )   // 2. 获取用户命令
        {
            continue;
        }
        //printf("%s\n", command_buffer);
        //ls
        //"ls -a -b -c -d"->"ls" "-a" "-b" "-c" "-d"
        ParseCommandLine(command_buffer, strlen(command_buffer)); // 3. 分析命令

        if ( CheckAndExecBuiltCommand() )
        {
            continue;
        }

        ExecuteCommand();   // 4. 执行命令
    }
    return 0;
}

课堂板书

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

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

相关文章

【进阶OpenCV】 (11)--DNN板块--实现风格迁移

文章目录 DNN板块一、DNN特点二、DNN函数流程三、实现风格迁移1. 图像预处理2. 加载星空模型3. 输出处理 总结 DNN板块 DNN模块是 OpenCV 中专门用来实现 DNN(Deep Neural Networks,深度神经网络) 模块的相关功能&#xff0c;其作用是载入别的深度学习框架(如 TensorFlow、Caf…

考虑促销因素的医药电商平台需求预测研究

一、考虑促销因素的医药电商平台需求预测研究 一、引言 1. 互联网医疗健康的发展 内容&#xff1a;介绍了在互联网的大背景下&#xff0c;医疗健康行业如何迅速发展&#xff0c;举例了&#xff11;药网和叮当快药等平台提供的服务。重点&#xff1a;互联网医疗用户规模和市场…

《人工智能(AI)和深度学习简史》

人工智能&#xff08;AI&#xff09;和深度学习在过去几十年里有了飞跃式的进步&#xff0c;彻底改变了像计算机视觉、自然语言处理、机器人这些领域。本文会带你快速浏览AI和深度学习发展的关键历史时刻&#xff0c;从最早的神经网络模型&#xff0c;一直到现在的大型语言模型…

【技术支持】家里智能电视不能联网重置小米路由器之路

问题现象 最近家里的路由器出现一点问题&#xff0c;现象是手机和电脑连接wifi后&#xff0c;都可以正常打开网页看视频。 但是小爱同学和小米盒子&#xff0c;都出现网络问题&#xff0c;不能正常播放音乐或者视频。 这是小米盒子的网络问题截图 这是和小米盒子连接的智能电…

骨架提取(持续更新)

一 什么是骨架提取 1.1 简介 骨架提取是图像处理或计算机视觉中的一种技术&#xff0c;用于从二值化图像中提取物体的中心线或轮廓&#xff0c;通常称为“骨架”或“细化图像”。这一技术主要用于简化形状表示&#xff0c;同时保留物体的拓扑结构。 这里我们强调了&#xff…

openpyxl -- Cell

文章目录 CellCell的属性MergedCell 版本&#xff1a;openpyxl - 3.0.10 Cell 创建一个单元格&#xff0c;并存入数据、样式、注释等&#xff1b;openpyxl.cell.cell.Cell;获取cell worksheet_obj[“B3”]&#xff0c;根据coordinate获取cell; 也可直接赋值写入&#xff1b;wo…

查找学位论文的数据库有哪些

学位论文分类&#xff1a;一般分为学士论文、硕士论文、博士论文。下面介绍一下能够轻松获取学位论文全文的数据库及获取数据库资源的途径。 1.知网 中国优秀硕士学位论文全文数据库 &#xff08;中国知网CNKI&#xff09; 中国博士学位论文全文数据库 &#xff08;中国知网…

获取时隔半个钟的三天与el-time-select

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

Cyber Weekly #28

赛博新闻 1、特斯拉发布无人驾驶汽车Cybercab和Robovan 本周五&#xff08;10月11日&#xff09;&#xff0c;特斯拉公布两款车型Cybercab和Robovan&#xff0c;以及他们的Robotaxi无人驾驶出租车计划。Cybercab没有方向盘&#xff0c;没有充电孔&#xff0c;也没有脚踏板和后…

动态规划的优化与高级应用

姊妹篇&#xff1a; 动态规划基础与经典问题-CSDN博客 贪心算法&#xff1a;原理、应用与优化_最优解-CSDN博客​​​​​​贪心算法&#xff1a;原理、应用与优化_最优解-CSDN博客 一、动态规划的优化策 动态规划在提高时间效率的同时&#xff0c;往往会占用较多的空间。因…

【电商搜索】现代工业级电商搜索技术-中科大-利用半监督学习改进非点击样本的转化率预测

【电商搜索】现代工业级电商搜索技术-中科大-利用半监督学习改进非点击样本的转化率预测 0. 论文信息 RecSys24: Utilizing Non-click Samples via Semi-supervised Learning for Conversion Rate Prediction inproceedings{huang2024utilizing, title{Utilizing Non-click S…

微生物测序报告中的多样性数据详细解读

随着技术的发展&#xff0c;高通量测序技术已成为研究微生物群落的重要工具。这种技术使得科学家们能够解析巨量微生物DNA序列&#xff0c;从而获得丰富的微生物组数据&#xff0c;包括16S rRNA基因、ITS序列和宏基因组。然而&#xff0c;这些数据只是迈向揭示微生物群落复杂性…

docker启动MySQL容器失败原因排查记录

背景 最近在尝试容器搭建MySQL集群时碰到一个错误&#xff0c;启动MySQL时碰到一个&#xff0c;经过排查解决&#xff0c;在此做一个记录 问题过程 1、启动MySQL容器 $ sudo docker run -d -p 3306:3306 \ > --name mysql \ > -v /opt/mysql/log:/var/log/mysql \ &g…

java项目之大型商场应急预案管理系统(源码+文档)

项目简介 大型商场应急预案管理系统实现了以下功能&#xff1a; 大型商场应急预案管理系统的主要使用者管理员功能有个人中心&#xff0c;员工管理&#xff0c;预案信息管理&#xff0c;预案类型管理&#xff0c;事件类型管理&#xff0c;预案类型统计管理&#xff0c;事件类…

【vue】03-指令补充+样式绑定+计算属性+侦听器

代码获取 知识总结 ⼀、指令补充 1.指令修饰符 1.1 什么是指令修饰符&#xff1f; 所谓指令修饰符就是让指令的 功能更强⼤&#xff0c;书写更便捷 1.2 分类 1.2.1 按键修饰符 keydown.enter&#xff1a;当enter键按下时触发 keyup.enter&#xff1a;当enter键抬起时触…

执行powershell脚本出错:未对文件进行数字签名

解决执行powershell脚本时出错&#xff1a;未对文件 \test.ps1进行数字签名。无法在当前系统上运行该脚本 前言 今天从github上下载了一个PowerShell脚本要在本地运行&#xff0c;运行的时候出现了未对文件进行数字签名的问题&#xff0c;然后在这里记录下怎么解决 解决方法…

选择2024年开发App的理由,费用分析与效益

App开发费用受复杂度、团队、地理位置、平台等因素影响。低代码平台如ZohoCreator提供经济高效开发方案&#xff0c;降低费用并提升灵活性。2024年&#xff0c;企业需考虑这些因素制定长期规划。 调查显示&#xff1a; 企业估算应用开发费用时&#xff0c;常采用以下公式&…

大厂面试真题-组合和聚合的区别是什么

组合和聚合比较类似&#xff0c;二者都表示整体和部分之间的关系。 聚合关系的特点是&#xff1a;整体由部分构成&#xff0c;但是整体和部分之间并不是强依赖的关系&#xff0c;而是弱依 赖的关系&#xff0c;也就是说&#xff0c;即使整体不存在了&#xff0c;部分仍然存在…

算法专题六: 模拟与分治快排

目录 模拟1. 替换所有的问号2. 提莫攻击3. Z字形变换4. 外观数列5. 数青蛙分治快排1. 颜色分类2. 排序数组3. 数组中的第K个最大元素4. 库存管理Ⅲ 模拟 1. 替换所有的问号 算法思路: 本题就是简单的模拟, 只需按照题目的思路遍历所有的字符, 如果为?则将其替换, 替换时寻找2…