首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从零开始手写Shell:详解命令行解释器的实现原理

Shell的本质认知 命令行解释器(Shell)是操作系统的"翻译官",它的核心工作流程可以抽象为: 循环 { 1. 显示提示符 2. 获取命令输入 3....); exit(1); // exec失败时退出 } // 父进程等待 waitpid(id, nullptr, 0); return 0; } 进程管理三剑客...(void)rid; // 消除未使用变量警告(实际应检查返回值) return 0; } /* 主控流程 */ int main() { // 主循环:REPL(Read-Eval-Print...进行字符串分割: 首次调用传入原始字符串 后续调用使用nullptr继续处理 自动构建与main()函数兼容的argv格式 进程管理引擎 Execute()实现经典fork-exec模型: 主控流程...,我们掌握了以下核心技能: 环境变量操作:getenv的灵活使用 进程管理:fork-exec-wait黄金三角 字符串处理:安全分割与格式化 系统编程:理解UNIX设计哲学

9210

【Linux】手把手教你制作一个简易shell——(进程创建fork进程替换wait与进程等待exec的应用)(自定义shell程序设计)

运行程序等 Bash 是 Shell 的一种实现,也是目前最流行的 Shell 之一 【2】Bash的输入原理——指针数组 我们运行Linux时会出现, bash提示符和命令行 ,我们接下来也要实现这两点...故采用行获取接口fgets command参数 接收命令行获取 字符数组usercommand ,我们输入命令后,最终你还是会输入\n——导致执行结果和shell之间出现空行;所以我们在输入完后要把...>模块 1.程序设计框架 我们回顾原理部分: 在父进程bash进程中,创建一个子进程,环境变量也会传递给子进程,并进行 进程等待wait 在子进程中通过 进程替换exec ,执行 指针数组中...中的命令(通过环境变量) 于是我们设计出: fork函数创建子进程 子进程进行进程替换execvp函数,用到 分割usercommand数组后的字符串的地址——的指针数组argv 父进程等待子进程...2.程序设计细节 1. fork函数: 2. execvp函数: 由于我们用到了指针数组argv,所以用exec系列的vp尾缀,execvp , 表示v(vector)数组,p(可以使用环境变量PATH

14010
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【Linux】Linux进程控制>进程创建&&进程终止&&进程等待&&进程程序替换

    会被设置成相应的值以指示错误所在; 参数: pid: Pid=-1,等待任一个子进程。...,不再返回 如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值 4.2.2 命名理解 这些函数原型看起来很容易混,但只要掌握了规律就很好记 l(list) : 表示参数采用列表...shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束 然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。...所以要写一个shell,需要循环以下过程: 获取命令行 解析命令行 建立一个子进程(fork) 替换子进程(execvp) 父进程等待子进程退出(wait) 根据这些思路,和我们前面的学的技术,就可以自己来实现一个...Linux鼓励将这种应用于程序之内的模式扩展到程序之间。如下图 一个C程序可以fork/exec另一个程序,并传给它一些参数。这个被调用的程序执行一定的操作,然后通过exit(n)来返回值。

    16710

    MIT6.828实验2 —— Lab Shell

    首先需要了解几个核心的系统调用: * **fork() :** 该调用会创建一个子进程,会复制一份内存到独立的进程空间,代码中根据返回值来区分是子进程 (返回0) 还是父进程 (返回子进程的pid)。...* **wait():**该方法会阻塞父进程,等待子进程退出后再结束,注意如果fork()了多个子进程,则需要多次调用wait()才能等待所有子进程完成。且wait()是无法等待孙子进程的。...原程序中exec()后面的代码不会再被执行,这也是shell中需要fork进程去exec命令的原因,不然就无法继续处理一条命令了。...主体逻辑 程序的主逻辑是在 main()方法中循环接收标准输入,fork() 出子进程进行处理,首先将接收到字符串分割为字符串数组方便处理,然后进入命令解析和执行。...其中EXEC、PIPE、REDIR这三种命令和我们的nsh实现相似,其余的几种命令则比较简单: * LIST:由分号 ; 分割的顺序命令,实现方法是fork一个子进程执行左命令,wait等待其完成后再执行右命令

    1.8K30

    操作系统课设详细解答

    ” 处输入工程目录。...三、总体设计 1.背景知识 在 Linux 中创建子进程要使用 fork()函数,执行新的命令要使用 exec()系列函数,等待子进 程结束使用 wait()函数,结束终止进程使用 exit()函数。...例如,可以使用 gcc –o fork_demo fork_demo.c 完成编译。 步骤 2:在命令行输入./fork_demo 运行该程序。...例如,可以使用 gcc –o exec_demo exec_demo.c 完成编译。 步骤 2:在命令行输入./exec_demo 运行该程序。 步骤 3:观察该程序在屏幕上的显示结果,并分析。...;反之,消费者经常等待;若缓冲区为空,则必定是生产者运行,缓冲区为满,则消费者运行,生产者等待,而对于结果的表示,则是调用了Append()和Consume()中的循环输出。

    1.1K20

    【Linux】实现一个简易的shell命令行

    一.项目简介 在使用Linux的过程中,相信大家最熟悉的就是Linux的命令行使用方式了,我们可以给命令行输入任意有效指令, 然后命令行会根据我们输入的指令来完成相应的操作。...然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。...所以要写一个shell,需要循环以下过程: 获取命令行 解析命令行 建立一个子进程(fork) 替换子进程(execvp) 父进程等待子进程退出(wait) 三.逐步实现项目功能 该部分只讲功能实现的代码逻辑..., 故可能不会包含宏定义和全局变量等实现细节,如需完整的项目代码,请移步本文第四部分. 1.获取命令行 我们将获取命令行做成一个循环,除非用户主动退出,否则一直保持命令行接收指令的状态:...普通命令的执行不会影响父进程,因此我们可以使用fork()创建子进程,然后使用exec*系列进程替换函数来完成相关操作, 代码如下: void NormalExcute(char *_

    14010

    《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数

    第六章 Linux中的进程监控 学习目的 使学生理解Linux中进程控制块的数据结构,Linux进程的创建、执行、终止、等待以及监控方法。并重点掌握fork函数的使用以及exec系列函数。...理解:Linux进程创建时环境变量、命令行参数的设置,理解父进程等待子进程结束和获得子进程返回值的原理; 掌握:fork函数的使用,以及父子进程间的关系,掌握exec系列函数。...fork(void); ▪ 返回值: - fork函数被正确调用后,可能会在子进程中或父进程中分别返回 - 在子进程中返回值为0(不合法的PID,提示当前运行在子进程中) - 在父进程中返回值为子进程ID...- 可变参数:要执行程序的命令行参数,以空指针结束 - envp::指向环境字符串数组的指针,该数组的最后一个成员必须为空指针 ▪ 返回值 - 出错返回-1 - 成功该函数不返回 (5) 其他exec.... - 就绪态:进程已做好一切准备, 等待获得CPU投入运行. - 睡眠态:进程因等待输入输出或其它系统资源, 而让出CPU资源, 等待运行条件满足。

    19610

    Linux进程控制

    一.进程创建 fork()函数: 在进程概念这篇文章中,我们浅浅地了解了一下fork函数,它的功能是让父进程去创建一个子进程,并且有两个返回值,对应着父进程的返回值和子进程的返回值。...#include pid_t fork(void); 返回值:子进程中返回0,父进程返回子进程id,出错返回-1 先来看三个问题: 1.如何理解fork函数有两个返回值的问题?...例如子进程从fork返回后,调用exec函数。 fork也有调用失败的时候,其原因很大可能是系统中有太多的进程或者实际用户的进程数超过了限制。...如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值。因为成功的返回值没有必要,都已经替换了进程了,即使返回了,这个值也用不了。...,输入一些命令行指令,那么就可以通过execvp去将对应的程序加载到内存,就可以执行这些程序了!

    2.4K30

    【Linux】进程控制,手搓简洁版shell

    2、进程终止 main函数的返回值->返回给父进程或系统。...若WIFEXITED非零,提取子进程退出码(查看进程的退出码) 阻塞和非阻塞 非阻塞等待即让父进程在等待子进程的过程中去做一些自己的事。...{ cout << "我是子进程,pid:" << getpid() << endl; sleep(1); } exit(0); } while (true)//阻塞循环等待...替换原理: 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数来执行另一个程序,当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换...如果给上面的代码加上死循环,再让运行时读取指令,不就是一个简单的命令解释器吗? 程序替换不影响命令行参数和环境变量。

    8510

    UNIX高级环境编程 第三次实验 实现带参数的简单Shell

    当fork()函数返回值为0时表示处 于子进程中;而返回值大于0时表示处于父进程中,此时的返回值是子进程的进程id。因此,fork()的返回值可以用来划分仅仅适合父进程 和子进程执行的程序段。...fork()函数返回值为-1时表示出错。 如果子进程只是运行与父进程完全一样的程序,那用处是很有限的。要让子进程运行不同于父进程的程序,就必须调用execve函数,它是 所有其他exec函数的基础。...本实验仅仅用它使父进程等待子进程结束,因此维持程序1-5的用法即可。 1.2 根据简单shell的输入,构造execve函数的参数。 根据程序1-5,数组buf保存用户的输入,包括命令和参数。...由于shell命令的命令名和各参数之间是用空格分开,因此可以用空格作为分界符。通过一个循环可以把buf数组中的命令和各个参数依次分离开来,并赋给数组argv的各元素适当的指针值。...一般命令都可以由fork+execvp执行,由fork创建一个子进程,调用一种exec函数时,该进程执行的程序完全替换为新程序 而新程序则从其main函数开始执行; 但要注意exec并不创建新进程,所以前后的进程

    96220

    【Linux系统编程】八、进程程序替换

    用 fork 创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支), 子进程往往要调用一种 exec 函数以执行另一个程序。...(包括 envp[] 中也要以 NULL 结尾) 二、共同特性 调用成功则加载新的程序从启动代码开始执行,不再返回 调用出错则返回 -1 exec 函数 只有出错的返回值 而没有成功的返回值(因为成功调用的时候已经开始执行新程序...然后我们的 shell 读取新的一行输入,建立一个新的进程,在这个进程中运行程序并等待这个进程结束。...所以要写一个shell,需要循环以下过程: 获取命令行 解析命令行 建立一个子进程(fork) 替换子进程(execvp) 父进程等待子进程退出(wait) ​ 根据这些思路...main() { // 因为shell是循环输入的,所以要套在死循环里面 while(1) { // 获取命令行 printf("[%s@%s

    4500

    Linux系统-进程控制

    结果: 示图: 2、fork返回值 返回值: fork成功对子进程返回0,对父进程返回子进程的pid 写时拷贝 概念: fork成功之后父子代码共享,当父子不写入数据时,数据也是共享的,当任意一方试图写入...-1,这时errno会被设置成相应的值以指示错误所在 参数pid: Pid=-1,等待任一个子进程,与wait等效 Pid>0,等待其进程ID与pid相等的子进程 参数status...,不再返回(已经将代码和数据全部替换,执行新程序的执行逻辑) 如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值 命名理解: l(list) : 表示参数采用列表的形式传入如何使用程序或者命令...shell视角执行: shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序并等待这个进程结束,再进行新的输入读取 注意: 对于shell来说作为命令行解释器,执行命令需要将执行结果给用户看到...自己执行 具体流程: 获取命令行 解析命令行 建立一个子进程(fork) 替换子进程(execvp) 父进程等待子进程退出(wait) 示图: 注:根据这些思路

    1.5K30

    异步编程举例之闹钟程序

    该程序循环接受用户的输入信息,直到出错或者输入完毕。用户输入的信息第一部分是闹钟等待时间(以秒为单位),第二部分是闹钟时间到达后所显示的信息。...(出错或者到达文件尾部)如果读取长度不大于1,比如直接按下Enter键,则重新循环。 sscanf(), 从字符串中读取与指定格式相符的数据,成功时返回参数数目,失败返回-1。...实际上是把希望用异步方式实现的工作用同步方式实现了。 二 多进程版本 有多种异步实现该程序的方法。其中一种方式是为每个命令使用fork调用生成一个子进程。...这样可以随时输入命令行,彼此独立运行,不会阻塞等待。程序难点在于对子进程的资源回收,不做重点说明。...成功解析输入信息后,创建子进程延时、显示信息。父进程则等待子进程结束并回收资源,通常是调用某个waitpid函数。 WNOHANG属性使父进程不必挂起等待子进程结束。

    76330

    【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

    将父进程部分数据结构内容拷贝至子进程 添加子进程到系统进程列表当中 fork返回,开始调度器调度 关于fork函数的返回值: 返回0给子进程 返回子进程的PID给父进程 创建失败,返回值 < 0 子进程和父进程共享...即父进程会检查一次看子进程有没有退出,没有则返回0,此时父进程可以做一些自己的事,而不是一味的等待子进程的退出,在子进程退出前循环以上的过程,直到子进程退出,返回 >0 的一个数,返回负数则表示等待失败...如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值。...这样就能更好的理解这些函数为什么要这么用了 例如命令行中输入 ls -l -a (以单进程的进程替换来演示) int main() { execl("/usr/bin/ls","ls","-l...所以当我们要put环境变量时,只是将它的地址填入了环境变量表中,而环境变量的内容是由我们自己输入的,在我们自己创建的命令行参数表中,而这个命令行参数表是会变的,但环境变量表依然指向不变,但是其实所指向的内容已经变了

    33910

    【Linux修炼】11.进程的创建、终止、等待、程序替换

    进程的创建、终止、等待、程序替换 本节重点 1. 进程的创建 1.1 fork函数初识 1.2 fork的返回值问题 1.3 写时拷贝 1.4 创建多个进程 2....1.2 fork的返回值问题 对于这个问题,从三个层次去理解。 1. 如何理解fork函数有两个返回值问题?...而exec系列的函数调用成功是没有返回值的,也不需要返回值,因为进程被替换之候原本的代码就没有意义了,即便返回了一个值,也不会有什么作用,还会有额外的开销。...如果调用出错则返回-1 所以exec函数只有出错的返回值而没有成功的返回值。...4.4 应用场景:模拟shell命令行解释器 我们将子进程的代码中的替换注释掉,在添加成这样: 不传入argv[0]的原因是argv[0]代表我的程序:myexec,这样的话就会出现死循环的情况,因为会一直调用

    6.2K00

    Linux进程编程

    Linux进程编程 3.1 fork系统调用 3.1.1 fork工作原理 3.1.2 fork函数 3.1.3 fork编程示例 3.1.4 小结 3.2 exec系统调用 3.2.1 exec函数族作用...返回值:fork被调用一次却能够返回两次且可能有三种不同的返回值: 在父进程中,fork返回新创建子进程的进程ID(通常为父进程PID+1); 在子进程中,fork返回0; 如果出现错误,fork返回一个负值...文件; 按下i键进入编辑模式,输入fork编程示例,该示例创建一个子进程,通过fork()函数返回值判断进程是子进程还是父进程,并打印信息。...按下ESC键退出编辑模式,输入“:wq”回到命令行,使用gcc编译器编译forkProcess.c文件生成可执行文件forkProcess. 输入....; pid:pid>0时:等待进程号为pid的子进程结束、pid=0时:等待组ID等于调用进程组ID的子进程结束、pid=-1时:等待任一子进程结束,等价于调用wait()、pid等待组ID等于

    7.8K20

    Shell 命令及运行原理

    Shell 是 Linux 和 Unix 系统中的 命令行解释器,调用用户输入的命令来与操作系统核心进行交互。 进入 Shell 就像进入一个为您开放的环境,你可以在这里输入指令。...(内置、外部或自定义脚本) ↓ 添加命令到子进程中,fork 和 exec ↓ 运行命令,返回结果,显示于终端 对于 外部命令,运行过程更加详细: Shell 程序通过 fork...调用创建一个新的子进程; 子进程通过 exec 调用加载命令对应的执行文件; Shell 等待子进程运行完成,返回选择状态和输出结果。...查找命令 Shell 通过 PATH环境变量查找 ls 命令在文件系统中的位置。 fork Shell 通过 fork() 创建子进程。...总结 Shell 在操作系统中起着课程解释和命令执行的重要作用,其原理根据以下步骤运行: 输入解析 查找命令 fork 和 exec 执行命令 结果显示 深入了解这个流程,可以在命令行上可以更好地调试和解决问题

    20110

    【Linux】shell命令行简单解释器

    回顾一下,我们前面学习了进程创建,进程终止,进程等待,进程替换,通过这些内容我们可以来进行实现简单的shell命令行解释器!!!...下面我们直接来看一看如何去实现shell命令行解释器: 总体分为(整体需要循环哦): 1.输出提示符 2.输入和获取命令 3.fork创建子进程 4.内建命令 ---- 输出提示符 这里的提示字符为用户名...获取 输入之后,我们自然需要去进行获取,我们需要分割命令行,这个地方用strtok。...fork创建进程 利用fork创建子进程,同时父进程需要等待子进程退出返回结果 另外我们还需要选择替换函数execvp:首先替换函数需要先带上v,可将所有的执行参数放入数组中统一传递,其次还要选择带上...shell运行原理 同时,在理解一下shell的运行原理:shell内部提取命令行做分析,然后调用exec. shell执行命令必须通过创建子进程,如果不创建子进程会把我们所有的shell全部替换,所以执行命令时一般磁盘上的程序必须创建子进程

    23530

    spawn-fcgi原理及源代码分析

    然后fork-exec创建FCGI进程。退出完毕工作。 老方法,main函数使用getopt解析命令行參数,从而设置全局变量。假设设置了-P參数,须要保存Pid文件,就用open系统调用打开文件。...failed: %s\n", strerror(errno)); return -1; } return fcgi_fd; } fcgi_spawn_connection函数的工作是循环一次次创建子进程...基本没啥可说明的。 对于子进程:注意一下dup2函数。由子进程执行,将监听句柄设置为标准输入。输出句柄。比方FCGI_LISTENSOCK_FILENO 0 号在FCGI里面代表标准输入句柄。...对于父进程: 主要须要用select等待一会,然后调用waitpid用WNOHANG參数获取一下子进程的状态而不等待子进程退出。假设失败就打印消息。否则将其PID写入文件。...fork。dup2等。非常久之前看的在这里备忘一下。

    2.2K10

    spawn-fcgi原理及源码分析「建议收藏」

    其功能主要是打开监听端口,绑定地址,然后fork-exec创建FCGI进程,退出完成工作。 老方法,main函数使用getopt解析命令行参数,从而设置全局变量。...创建FCGI的进程 return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, fcgi_fd, fork_count, child_count,...failed: %s\n", strerror(errno)); return -1; } return fcgi_fd; } fcgi_spawn_connection函数的工作是循环一次次创建子进程...对于子进程:注意一下dup2函数,由子进程运行,将监听句柄设置为标准输入,输出句柄。比如FCGI_LISTENSOCK_FILENO 0 号在FCGI里面代表标准输入句柄。...对于父进程: 主要需要用select等待一会,然后调用waitpid用WNOHANG参数获取一下子进程的状态而不等待子进程退出,如果失败就打印消息。否则将其PID写入文件。

    2.5K10
    领券