先上代码

shell.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>#define  MAXLINE 4096                        /* max line length */int main(int argc, char *argv[])
{char   buf[MAXLINE];pid_t  pid;int     status;printf("%% ");                         /* print prompt (printf requires %% to print %) */while (fgets(buf, MAXLINE, stdin) != NULL) {if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0'; /* replace newline with NULL */if ((pid = fork()) < 0) {perror("fork error");} else if (pid == 0) {             /* child */execlp(buf, buf, (char *)0); /* The exec() functions return only if an error has occurred. */fprintf(stderr, "couldn't execute: %s: %s\n", buf, strerror(errno));exit(127);} else {                           /* parent */if ((pid = waitpid(pid, &status, 0)) < 0)perror("waitpid error");printf("%% ");}}exit(0);
}

编译

$ gcc shell.c -o shell

运行

$ ./shell
% date
2021年 06月 06日 星期日 01:56:28 CST
% who
liyongjun :0           2021-05-23 09:43 (:0)
liyongjun tty3         2021-05-23 20:24
liyongjun tty4         2021-05-25 00:23
liyongjun pts/2        2021-05-25 00:50 (127.0.0.1)
% ls
shell shell.c
% ^D
$

再讲程序

  • 以上代码便实现了一个简单的 shell 程序。该程序从标准输入读取命令,然后执行这些命令。
  • 该程序使用了一个不同的提示符(%),以区别与系统自带的 shell 的提示符。
  • 第 18 行用标准 I/O 函数 fgets 从标准输入一次读取一行。当键入文件结束符(通常是 Ctrl + D)作为行的第一个字符时,fgets 返回一个 NULL 指针,于是循环停止,进程也就终止。
  • 因为 fgets 返回的每一行都以换行符终止,后随一个 NULL 字节,故用标准 C 函数 strlen 计算此字符的长度,然后用一个 NULL 字节替换换行符。这样做是因为 execlp 函数要求参数以 NULL 而不是以换行符结束。
  • 调用 fork 创建一个新进程。新进程是调用进程的复制品,我们称调用进程为父进程,新创建的进程为子进程。fork 向父进程返回新子进程的进程 ID(大于 0),对子进程则返回 0。因为 fork 创建一新进程,所以说它被调用一次(由父进程),但返回两次(分别在父进程及子进程中)。
  • 在子进程中,调用 execlp 以执行从标准输入读入的命令。这就用新的进程文件替换了子进程原先执行的程序文件。fork 和跟随其后的 exec 两者的组合就是某些操作系统所称的产生(spawn)一个新进程。在 UNIX 系统中,这两个部分相互分隔,构成两个函数。
  • 子进程调用 execlp 执行新程序文件,而父进程希望等待子进程终止,这一要求由调用 waitpid 实现,其参数指定要等待的进程(在这里,pid 参数是子进程 ID)。waitpid 函数返回子进程的终止状态(status 变量)。在此简单程序中,没有使用该值。如果需要,可以用此值准确地判定子进程是因何终止的。
  • 该程序的最主要缺陷是不能向所执行的命令传递参数,例如不能对 ls 指定目录名,只能对工作目录执行 ls 命令。为了传递参数,先要分析输入行,然后用某种约定把参数分开(很可能使用空格或制表符),然后将分隔后的各个参数传递给 execlp 函数,后面有时间的话可以继续完善。

35 行代码实现一个简单的 shell相关推荐

  1. java简单编译器源代码_25行代码实现一个简单的编译器

    起因 <25行JavaScript语句实现一个简单的编译器>实现的是一个简单到不能再简单的玩具的玩具,他的魔法是函数式编程简化了js代码.java 8提供了函数式编程的支持,昨晚脑子抽风突 ...

  2. 【Unity3D】10行代码实现一个简单的角色移动旋转脚本

    一.前言 今天分享一个简单的角色移动脚本,主要用到碰撞器和刚体组件,代码简单易懂,复用性.扩展性较强,跟我一起来看看吧. 二.效果图 三.代码 using UnityEngine;public cla ...

  3. python文本处理入门:44行代码写一个简单的藏头诗生成器

    想必最近大家家庭群里最近都会看到这么一张图: 一惊,这什么玩意儿???后来一搜会发现里面不同的诗句来自于不同的古诗,嘛,这不是很好玩的一件事情吗?这次我们使用Github的唐诗宋词dataset:ht ...

  4. 用python60行代码写一个简单的笔趣阁爬虫!三分一章?

    前言 利用python写一个简单的笔趣阁爬虫,根据输入的小说网址爬取整个小说并保存到txt文件.爬虫用到了BeautifulSoup库的select方法 结果如图所示: 本文只用于学习爬虫 一.网页解 ...

  5. 37行代码实现一个简单的打游戏AI

    不废话,直接上码,跟神经网络一点关系都没有,这37行代码只能保证电脑的对敌牺牲率是1:10左右,如果想手动操控,注释掉autopilot后边的代码即可. 哪个大神有兴趣可以用tensorflow或者s ...

  6. python编写程序输出诗句_Python文本处理简介:44行代码编写一个简单的隐藏诗生成器,python,入门,藏头诗...

    想必最近大家家庭群里最近都会看到这么一张图: 一惊,这什么玩意儿???后来一搜会发现里面不同的诗句来自于不同的古诗,嘛,这不是很好玩的一件事情吗?这次我们使用Github的唐诗宋词dataset:ht ...

  7. 200 行代码实现一个简单的区块链应用1

    区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用区块链来解决的问题,这两者很容易混淆.像 ...

  8. 200 行代码实现一个简单的区块链

    英文原文:Lauri Hartikka 区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用 ...

  9. 35行代码搞定事件研究法(上)

    作者简介: 祝小宇,个人公众号:大猫的R语言课堂 这期大猫课堂将会教大家如何用35行R代码写出最有效率的事件研究法. 注意,本代码主要使用data.table完成,关于data.table包的相应知识 ...

最新文章

  1. Java基础学习总结(3)——抽象类
  2. 7.5 TableLayout布局详解
  3. 从白盒测试到单元测试基础原理
  4. 金融领域下的数据挖掘算法应用:逻辑回归模型
  5. linux c代码出现段错误,在linux下代码运行出现段错误,求大神
  6. 一天测血压的最佳时间_高血压病患者,一天之内在什么时间点测血压最好?
  7. 进程篇—进程整理(转)
  8. Java精品项目源码第111期小蜜蜂扩音器网上商城系统
  9. 涨见识!Java String转int还有这种写法
  10. 软考 - 系统架构设计师(软件架构设计)
  11. 从零开始搭建一个Vue项目
  12. 地毯店人员告诉你如何正确选购合适地毯
  13. 富士服务器A系列说明书,富士伺服驱动器FALDIC-用户手册.pdf
  14. Balsamiq Mockups完全手册
  15. VLDB 2010 论文写作和格式 format 投稿
  16. Transformer T5 模型慢慢读
  17. Unreal Engin_画廊制作笔记 _010给墙画添加灯光
  18. 【区块链】区块链是什么?20问:读懂区块链
  19. 【论文阅读】让数据库听懂人话(Text-to-SQL)
  20. 【2019-游记】中山纪念中学暑期游Day12

热门文章

  1. Gingko Framework:避免数据缓存
  2. 如何用python爬取公众号文章_如何使用 Python 爬取微信公众号文章
  3. Qt发布exe软件及修改exe应用程序图标
  4. NumPy 初学者指南中文第三版·翻译完成
  5. bootstrap多层modal的相关问题
  6. 查看网站历史记录的2种办法,怎样查看网站历史记录?
  7. 【恒指早盘分析】9.25恒指今日复盘及后市思路
  8. 聊一聊上拉电阻、下拉电阻、使用场景及阻值选择
  9. (Ryan的Koa系列博客)6.依赖库:on-finished(本文尚未完成)
  10. Json完整版介绍和工具类解析应用