资讯专栏INFORMATION COLUMN

自己动手实现一个 Unix Shell

546669204 / 1859人阅读

摘要:实验中,我们并不期望信号直接作用于进程本身否则收到信号就终止了,而是需要让将信号转发给前台作业中的子进程及其所属进程组中的所有进程。所以,我们不能让子进程和进程同属一个进程组。

这个实验通过实现一个支持作业控制的Unix Shell,让我们对进程控制和信号控制更加熟悉。课程Lab已经帮助我们搭建起了Shell的整体框架,并实现了与本次实验不太相关的代码,核心部分需要我们自己完成。

整体框架

Shell从标准输入(stdin)读取用户输入的命令,然后解析命令,Shell支持两种类型的命令:如果用户输入的是的内置命令(如quitjobs等),那么直接执行该命令;如果用户输入的是某个可执行文件的路径,那么通过fork一个子进程,在子进程中加载并执行命令。Shell把每次用户输入的命令抽象为一个job,一个job可以包含多个进程(例如管道)。每个job有两种运行方式,如果用户输入的命令以"&"结尾,那么job将会在后台(background)运行,否则,job运行在前台(foreground)。在任意时刻,只允许存在01个前台job,但是可以有0或多个后台job运行。最后,为了支持用户能够向Shell发送信号,我们还需要实现3个信号处理程序,分别处理信号SIGCHLDSIGINTSIGTSTP

需要注意的地方

默认的,一个子进程和它的父进程同属于一个进程组,而Unix系统提供的大量向进程发送信号的机制,都是基于进程组这个概念的。当我们输入Ctrl + C,内核会发送一个SIGINT信号到前台进程组的每个进程,类似的,输入Ctrl + Z会导致内核发送一个SIGTSTP信号给前台进程组中的每个进程。这儿的“前台进程组”指的是Shell进程所属的进程组。实验中,我们并不期望信号直接作用于Shell进程本身(否则Shell收到SIGINT信号就终止了),而是需要让Shell将信号转发给Shell前台作业中的子进程及其所属进程组中的所有进程。所以,我们不能让子进程和Shell进程同属一个进程组。具体做法是通过使用setpgid函数来改变子进程的进程组,当调用setpgid(0, 0)时,内核会创建一个新的进程组,其进程组ID是调用者进程的PID,并且会把调用者进程加入到这个进程组中。

Shell收到信号时,具体的工作需要信号处理函数来完成。例如收到SIGINT信号,那么信号处理函数会把该信号发往前台job中的进程及其所属进程组中的所有进程。实验中,我们是通过kill(pid_t pid, int sig)来发送信号,注意到我们并不仅仅是向PID = pid的进程发送信号,kill函数帮助我们实现了这一点:如果pid小于0kill发送信号sig给进程组|pid|pid的绝对值)中的每个进程。我们可以意识到,上一点需要注意的地方正是为这一点做铺垫的。

父进程(Shellfork了一个子进程后,父进程需要将这个进程作为一个job添加到job队列中去(addjob),当子进程终止时,内核会发送一个SIGCHLD信号给父进程,然后在相应的信号处理程序中,把终止的子进程对应的jobjob队列中删除(deletejob)。考虑一种情况:当父进程fork了一个子进程之后,子进程先于父进程获得调度,并且在父进程执行addjob前,子进程就已经终止了,并发送了SIGCHLD信号给父进程。此时,在信号处理程序中deletejob不会做任何操作,因为此时父进程还没有把job加入到job队列中。出现这个问题的根本原因是在addjob之前调用了deletejob。解决这个问题的方法是:在父进程fork子进程之前,将SIGCHLD信号阻塞,当完成addjob之后,才解除对SIGCHLD信号的阻塞,这样就能保证在子进程被添加到job队列之后再回收该子进程。注意,子进程继承了它们父进程的被阻塞信号集合,所以我们必须在调用execve之前,解除子进程中阻塞的SIGCHLD信号。

代码

Shell Lab的代码在这里。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/9492.html

相关文章

  • set,env,export,source,exec傻傻分不清楚?

    摘要:设置了当前进程的本地变量,本地变量只在当前的进程内有效,不会被子进程继承和传递。一个进程可以生成另一个进程,生成的进程称为子进程,那么相应的就有父进程,所谓子子孙孙无穷尽也。和在系统中进程通过依次调用和系统调用来实现创建一个子进程。 你是否被下面的几个问题困扰过,甚至至今无法真正理解? 什么是export,什么时候用export,为什么有时用了export还要source? 为什么用...

    taoszu 评论0 收藏0
  • 一步步搭建物联网系统——GNU/Linux 强大且Free

    摘要:强大且什么是是一种自由和开放源码的类操作系统内核。是一个领先的操作系统内核,世界上运算最快的台超级电脑运行的都是基于内核的操作系统。开机完成后,就接手初始化硬件设备创建存储器空间的映射,以便为操作系统内核准备好正确的软硬件环境。 GNU/Linux 强大且Free showImg(http://designiot.phodal.com/images/gnu_linux.png); ...

    weapon 评论0 收藏0
  • 一步步搭建物联网系统——GNU/Linux 强大且Free

    摘要:强大且什么是是一种自由和开放源码的类操作系统内核。是一个领先的操作系统内核,世界上运算最快的台超级电脑运行的都是基于内核的操作系统。开机完成后,就接手初始化硬件设备创建存储器空间的映射,以便为操作系统内核准备好正确的软硬件环境。 GNU/Linux 强大且Free showImg(http://designiot.phodal.com/images/gnu_linux.png); ...

    yanwei 评论0 收藏0
  • 一步步搭建物联网系统——GNU/Linux 强大且Free

    摘要:强大且什么是是一种自由和开放源码的类操作系统内核。是一个领先的操作系统内核,世界上运算最快的台超级电脑运行的都是基于内核的操作系统。开机完成后,就接手初始化硬件设备创建存储器空间的映射,以便为操作系统内核准备好正确的软硬件环境。 GNU/Linux 强大且Free showImg(http://designiot.phodal.com/images/gnu_linux.png); ...

    Cc_2011 评论0 收藏0
  • 《跟阿铭学Linux》作者李世明:谈不上告白,就是帮女友转型而已

    摘要:年,阿铭开始为女友撰写电子版入门教程,到目前为止已经累计帮助数十万人。年创建阿铭培训,目前已经培训多期学员。创办阿铭培训班和猿课的初衷是什么最早仅仅是为了满足群里朋友的需求,通过录制一套视频,再结合我写的电子版教程,帮助群友学习。 本文仅用于学习和交流目的,不得用于商业目的。非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/art....

    Render 评论0 收藏0

发表评论

0条评论

546669204

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<