Linux下简单Shell实现(三)获取任务列表

Linux下简单Shell的实现 Linux下简单Shell的实现 参考自《操作系统概念》第七版第三章进程下的项目UNIX Shell和历史特点 首先梳理一下Shell的工作原理 Shell进程读入用户命令行的输入,然后建立一个子进程来完成这个命令,等待,当子进程完成后,父进程继续读入用户新的命令 使用fork()命令新建一个子进程后,该子进程将会是父进程的复制品——唯一区别在于fork()的返回参数不同,fork是唯一一个调用一次返回两次的函数,对于父进程,它返回子进程的PID号,对子进程,它返回0 要让子进程执行对应的程序,应当使用e 阅读详情

如果看过上一篇的话,还会记得在本Shell中main函数内第一条实质性的指令是

getTaskList(task_queue);

在本节,就会讲解这个获取任务列表,并存储到任务队列中的函数,到底在干什么。
我先把整个函数摆在下面,然后逐一讲解(先不要看下面这一大段代码)

void getTaskList(queue<string> & task_queue)
{
    while(!task_queue.empty()) task_queue.pop();

    string command_line;
    getline(cin, command_line);

    if(cin.eof())
    {
        exit(0);
    }   

    if(command_line.empty())
        return;

    if(command_line.back() == '&')
    {
        getIfDetach() = true;
        command_line.erase(command_line.end() - 1);

        if(command_line.empty())
            return;
    }
    else
    {
        getIfDetach() = false;
    }

    auto base_iter = command_line.begin();

    for(auto off_iter = command_line.begin(); off_iter != command_line.end(); ++ off_iter )
    {
        if(*off_iter == '|')
        {
            if(off_iter != command_line.begin() && *(off_iter - 1) == '\\')
            {
                off_iter = command_line.erase(off_iter - 1);
                continue;
            }
            task_queue.push(string(base_iter, off_iter));
            base_iter = off_iter + 1;
        }
    }

    task_queue.push(string(base_iter, command_line.end()));
    return;
}

首先函数原型为:

void getTaskList(queue<string> & task_queue);

传入一个std::queue<string>的引用,并把读到的指令按先后顺序存入队列中,之所以使用队列的结构是为了方便使用时先进先出的逻辑。

while(!task_queue.empty()) task_queue.pop();

上述代码块用于检测传入的指令队列是否为空,如果不为空,则将其pop至空,主要是queue没有vector等结构的clear函数,比较麻烦。

    string command_line;
    getline(cin, command_line);

    if(cin.eof())
    {
        exit(0);
    }   

一般Shell中命令都是一行一行输入的,因此读入一行命令,存入command_line是本Shell的获取命令的方式。同时,如果输入ctrl+d也就是文件结束符的话,则退出Shell(模仿bash)。

    if(command_line.empty())
        return;

    if(command_line.back() == '&')
    {
        getIfDetach() = true;
        command_line.erase(command_line.end() - 1);

        if(command_line.empty())
            return;
    }
    else
    {
        getIfDetach() = false;
    }

如果读入的命令行为空的话,直接返回。
如果读入的命令行的最后一个字符为’&’的话,则说明本次输入的命令行为后台执行,将getIfDetach()函数内的static变量Detach置为true,并调用string类的erase函数删除最后的&字符。同时,如果删除&后命令行为空的话,说明用户仅输入了一个&字符,那么也直接返回。
如果最后一个字符不为’&’,则将Detach变量置为false。

    auto base_iter = command_line.begin();

    for(auto off_iter = command_line.begin(); off_iter != command_line.end(); ++ off_iter )
    {
        if(*off_iter == '|')
        {
            if(off_iter != command_line.begin() && *(off_iter - 1) == '\\')
            {
                off_iter = command_line.erase(off_iter - 1);
                continue;
            }
            task_queue.push(string(base_iter, off_iter));
            base_iter = off_iter + 1;
        }
    }

这一段可能比较难以理解,实际上我们在做的事情是,当用户使用管道调用多个进程时,我们需要把这几个进程从命令行中分开,然后分别存入task_queue中。首先让base_iter为command_line的头迭代器。托C++11的福,一个auto关键字真是解放劳动力。
接下来让off_iter从命令行头至命令行尾遍历,每当发现一个|字符(也就是管道的调用标识),则将base_iter至off_iter之间的字符串存入task_queue中,同时更新base_iter为off_iter的下一个。
如下图所示,给出了以`ls | grep main | more为例的处理流程:
这里写图片描述
注:task_queue中存储的命令是以进程为最小单位,也就是命令行参数和进程是作为同一个任务存到该队列中,并没有分开,如本例中的grep main

    task_queue.push(string(base_iter, command_line.end()));

最后将最后一段命令存入任务列表,即完成该函数全部工作。也就是上例中存入more的步骤。

【Linux】shell简单模拟实现 Shell是一个命令行解释器,它为用户提供了一个与操作系统交互的界面。用户通过 Shell 输入命令,Shell 负责解析这些命令并将其传递给操作系统执行。命令执行:Shell 可以直接执行用户输入的命令。例如,ls用于列出当前目录下的文件和文件夹。脚本编写:Shell 支持编写脚本,这些脚本是由一系列命令组成的文件,能够自动化重复的任务。例如,可以编写一个 Shell 脚本来备份文件、安装软件等。管道和重定向:Shell 支持管道 () 和重定向 ( 阅读详情

相关推荐

Linux下实现简单的shell解释器

什么是shellshell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接受用户输入的命令并把它送入内核去执行。 实际上shell就是一个命令解释器,它解释有用户输入的命令并且把它们送到内核。不仅如此,shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。shell变成语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编

Delete&_all的博客 6785

Shell命令获取服务的进程ID

文章目录背景查看服务进程信息过滤 grep 本身显示服务进程 IDShell 脚本实现小结 背景 最近在学习使用Shell脚本做一些有意思的东西,通过写在Shell脚本中的命令,可以快速的实现对服务器的某个操作。 在没有使用Shell脚本的时候,可能我杀死服务器中运行的某个后台服务程序,需要在终端中输入不止一个命令来实现该操作。但是使用Shell脚本就可以很快速的实现这个操作,我们所需要做的只不过...

活在当下!输出快乐! 4095

超实用的shell脚本--一键获取进程所有信息

转载来源 :超实用的shell脚本–一键获取进程所有信息 :http://www.safebase.cn/article-257427-1.html 摘要: 概述有时我们想只是通过一个进程PID就可以输出该进程的相关信息,可以怎么处理呢?下面用shell脚本来实现这个需求。根据PID过滤进程所有信息#! /bin/bash# copyright by hwb# Function: 根据用户输入的PID,过滤出该PID所有的信息read -p "请输入要查询的PID: " Pn=`ps -aux| awk

qq_40907977的博客 2616

Linux进程间通信详解(三) —— 消息队列及函数

消息队列的概念 消息队列就是一个消息的链表,每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该队列的大量信息,包括消息队列的键值、用户ID、组ID、消息数目、读写进程ID等。其定义如下: struct msg_queue { struct ipc_perm q_perm; time_t q_stime; // last msgsnd time time_t q_rtime; // last msgrcv ti

码农爱学习的博客 1036

tasklist能列出所有的进程,和相应的信息

:怎么才能关掉一个用任务管理器关不了的进程?我前段时间发现我的机子里多了一个进程,只要开机就在,我用任务管理器却怎么关也关不了

redbeat-example:使用RedBeat python软件包和Celery Beat进行动态任务调度的示例

CeleryBeat与RedBeatScheduler 有关如何在CeleryBeat上运行RedBeatScheduler的简短示例。 这将需要两个终端窗口才能运行: $ celery worker -A cluster -l info -P eventlet $ celery beat -A cluster -l info 然后在第三个窗口中: $ python >>> import cluster >>> from redbeat import RedBeatSchedulerEntry as Entry >>> e = Entry('thingo', 'cluster.add_task', 10, args=[15, 4], app=cluster.app) >>> e.save() >>> key = e.key() 您应该在celery worker终端中看到cluste

Java 多线程

多线程 9.1 进程与线程 进程是程序的一次动态执行过程,从代码加载,执行到执行完毕的完整过程。 多线程是实现并发机制的一种有效手段。 多线程是指一个进程在执行过程中可产生多个更小的程序单元(线程),这些线程可同时存在,同时运行,而一个进程可能包括多个同时执行的线程。 9.2 Java中线程的实现 继承Thread类 class 类名称 extends Thread{ 属性...; 方法...; public void run(){ 线程主体 } } 为什么启动线程不能直接使用run()方法? 答:线程的

weixin_45833157的博客 1394

CODESYS V3.5 SP17编程环境全攻略:从安装到多语言编程实战

本文全面解析CODESYS V3.5 SP17编程环境,从安装配置到多语言编程实战技巧。详细介绍了运行时环境设置、六种IEC 61131-3语言的特性对比与混合编程策略,以及高级功能开发如自定义算法模块和实时通信配置。适合工业自动化工程师快速掌握这一强大工具。

weixin_30632089的博客 489

shell脚本实例---编写shell脚本用于创建mq队列

实现功能:创建队列的脚本,在81人行端执行 #!/bin/bash #创建队列的脚本,在81人行端执行 ./etc/profile .~/.bashrc #运行前按需修改:队列管理器名称、机构代码、机构名称、IP!!! # 本机MQ队列管理器名称生产:QM_FTZMIS_0900_01测试:QM_FTZMIS_TEST_0900_01 QMNAME=QM_FTZMIS_10000_01 # 金融机构12位编码 JGBM=99999 # 金融机构名称 JGMC=BeiJi...

xiaozhuangyumaotao的博客 1233

官网下载stm32Fx固件库(标准外设)详细步骤

官网下载stm32f407固件库(标准外设)详细步骤

qq_52632983的博客 1万+

最新Mamba环境配置教程:从CUDA到causal-conv1d的完整安装流程

本文提供最新Mamba环境配置教程,涵盖从CUDA到causal-conv1d的完整安装流程。针对深度学习领域的长序列处理需求,详细指导如何正确配置CUDA工具链、安装PyTorch及关键依赖causal-conv1d,解决常见报错问题,并验证mamba-ssm集成效果。

bush的博客 418

【Linux】——简易版SHELL实现

本文借助进程相关知识实现了一个简易版的SHELL,并附有代码

麦麦的博客 2290

C#实战:5分钟搞定Modbus RTU通讯(基于NModbus4库)

本文详细介绍了如何使用C#和NModbus4库快速实现Modbus RTU通讯,包括环境配置、核心功能实现、性能优化及常见问题排查。通过代码示例和实用技巧,帮助开发者高效完成工业自动化设备的数据采集与控制任务。

weixin_30689307的博客 467

【Linux学习】实现一个简单版的Shell

本篇文章主要讲解一个简单版的`shell的实现`,看完这篇文章,你可以对`shell的运行原理,Linux进程相关知识`等有一个更深入的认识和理解,适合刚入门Linux的初学者学习。 自定义shell根据下面所述的原理一共分为四个部分实现。(分别为就`命令行的输入`,`解析`,`执行`,`内建指令的执行`)还包括了对一些`细节`的处理... 本篇文章主要讲解一个简单版的`shell的实现`,看完这篇文章,你可以对`shell的运行原理,Linux进程相关知识`等有一个更深入的认识和理解,适合刚入门Linux

2301_77509762的博客 2254

华为OD机试 - 最佳对手(Python/JS/C/C++ 2025 A卷 200分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。游戏里面,队伍通过匹配实力相近的对手进行对战。但是如果匹配的队伍实力相差太大,对于双方游戏体验都不会太好。给定n个队伍的实力值,对其进行两两实力匹配,两支队伍实例差距在允许的最大差距d内,则可以匹配。要求在匹配队伍最多的情况下,匹配出的各组实力差

学Java,找哪吒 1379

信创服务器(麒麟 V10 SP3)安装 NVIDIA GeForce RTX 5070 驱动

本文介绍了在麒麟V10 SP3系统上安装NVIDIA RTX 5070显卡驱动的详细步骤。首先需要关闭nouveau驱动,安装必要的编译环境和工具,确保内核版本与kernel-devel完全一致。最后运行NVIDIA驱动安装程序,关键选择包括启用DKMS支持、编译模块、禁用32位兼容和nouveau驱动。整个流程适用于海光CPU和Blackwell架构GPU的国产操作系统环境。

猿小白的博客 673

【Linux】—简单实现一个shell(myshell)

shell本质上就是一个进程,所谓的命令行参数,环境变量,就是shell内部的表(指针数据组),如果是表的话可以通过(env、expect…)这些命令会围绕着这张表来让shell来自主定义与维护这张表。

m0_73523775的博客 3812

从零构建法律案例数据库:Python爬虫实战与法律文本挖掘全攻略

在当今数字化浪潮席卷全球的背景下,法律行业正经历着前所未有的变革。法律案例数据库作为法律大数据的重要组成部分,已经成为法律从业者、研究人员、法学院学生乃至企业法务部门的必备工具。然而,商业法律数据库如北大法宝、威科先行、LexisNexis等往往价格不菲,且数据访问受限。对于个人研究者或小型机构而言,构建一个定制化的法律案例数据库不仅能节省成本,更能根据特定研究需求灵活调整数据结构。

2201_76125261的博客 538

【Linux】实现一个简单的shell

1.shell原理shell就是运用程序替换的原理进行实现的。 何为程序替换? 假如操作系统正在执行某一个程序,然后我们利用程序替换函 数指定一个新的程序,让操作系统去执行我们新指定的程序。也就是这样一种情形下,我们fork一个进程,如果fork成功,子进程会和父进程执行相同的代码,而我们创建子进程是希望子进程执行指定的操作,所以需要执行exec族函数。 何为程序替换函数? 程序替

天涯海角 2万+

Nacos 从困惑到蒙圈(9)Nacos 适配 达梦数据库【最新版】

介绍Nacos适配达梦数据库的详细步骤,包括对最新版本的支持改造。

甘蓝的专栏 1376

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Linux——shell程序的简单实现

本章思维导图:注:本章思维导图对应的.xmind和.png文件都已同步导入至,可免费查阅在学习完有关进程的知识后,我们就可以开始尝试自己实现一个简单的shell程序了。注:在编写简单的shell程序之前,你首先需要掌握:👉👉👉。

Forward♞的博客 1666

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Linux - 实现一个简单的 shell

所以,当系统运行起来的时候,或者说我们进行登录的时候,系统就是要运行一个 shell 程序。比如在 Linux 当中就是 bash 命令行解释器。而 ,我们知道 各个进程的 环境变量是来自于 bash 父进程的,那么 bash 的环境变量从那里来呢?其实在 自己用户,当前的工作目录下,有一写配置文件,如 Linux 当中这个文件当中:所以,当用户登录的时候,shell 会读取当前用户目录下的 .bash_profile 这个配置文件在个文件当中存储了环境变量导入到方式。

chihiro1122的博客 1319

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

[Linux] Linux 模拟实现 Shell

[Linux] Linux 模拟实现 Shell

石墨博客 1598

linux实现shell,Linux实现一个简单的shell

Linux实现一个简单的shellLinux实现一个简单的shell实现一个minishell1.从标准输入获取用户的输入2.将字符串进行解析,将获取的字符串划分为命令和参数的格式3.创建子进程4.进行进程替换shell中处理命令是通过创建子进程后进程替换实现功能,但还有一部分功能使系统的内建功能,例如cd重定向实现思路:对传入的字符串进行解析,重定向符号的前是命令,重定向后是文件名称在子进程程序...

weixin_36200896的博客 616

linux shell 获取进程pid,linux shell 根据进程名获取pid的实现方法

导读Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运行进程,因此在获取进程 pid 上二者也有所区别。交互式 Bash Shell 获取进程 pid在已知进程名(name)的前提下,交互式 Shell 获取进程 pid 有很多种方法,典型的通过 grep 获取 pid 的方法为(这里添加 -v grep是为了避免匹配到 grep 进程):ps -...

weixin_29957761的博客 5193

linux shell 列表循环,shell脚本中,for基于列表进行循环的实现方法

需求描述:在写脚本中需要这么个需求,需要对一个列表中的值进行循环比如,列表中的值mysqld,zookeeper,hbase简单来说,for基于列表值的循环。脚本测试过程:1.测试脚本#!/bin/bashfor i in {mysql,zookeeper,hbase}doecho $idone或者#!/bin/bashfor i in mysql zookeeper hbasedoecho $i...

weixin_35301706的博客 5045
上一篇: Linux下简单Shell实现(二)基本功能---主函数及init()函数
下一篇: C++ Primer 复习杂记(第七章)
skillness2
博客等级 码龄16年 1粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值