【解题笔记】CSAPP:shell lab踩坑记

        说实话,shell lab虽然不是一个很难的lab,但的确是一个很麻烦的lab,有许多细节需要注意。尤其是进程间的竞赛问题很难处理,一不小心就会掉进坑里。本人在做的时候,debug也花了很长时间,那么这篇文章就来记录一下,我在做lab的时候犯下的一些错误吧。

        第一个坑:工作列表的处理问题。我们在参考CSAPP中的示例代码时,发现deleteJob这件事是在sigchild handler中完成的。由于我们在接收到SIGINT与SIGTSTP后,仍然需要修改工作列表,那么一个自然的想法是直接在对应的handler中修改工作列表。

        但这样会带来很多问题。首先,在多进程的程序中,修改全局变量是一件很危险的事情,一不小心就会造成各种各样奇奇怪怪的竞赛现象。我们现在把对工作列表的处理分散了,那风险自然就增加了很多。举个例子。在CSAPP中的示例代码中,我们在fork子进程之前,只block掉了SIGCHLD,但如果我们用上述实现方式,我们还要blockSIGTSTP和SIGINT,否则立刻会出现竞赛现象。这对于不了解竞赛现象的人来说(比如刚开始做lab的我),想要注意到这一点并不容易,因而会带来一些逆天的bug。

        其次,你在对应的handler中处理了这些信号,那SIGCONT怎么办?难道你还要写一个SIGCONT handler?或者直接在bg/fg指令中处理SIGCONT?这不仅仅是风格上的不一致问题,而且会带来实实在在的语义问题。比如,谁规定的SIGCONT信号只能由bg/fg指令产生?如果我们真的这样实现,那trace31肯定就过不了。因为trace31的SIGCONT信号就不是由bg/fg产生。

        所以,我们最好在sigchild handler中统一修改对应的工作列表,而不把对工作列表的修改分散到各个地方。说起sigchild handler的修改,那应该是我要说的第二个坑。

        第二个坑:关于sigchild handler。CSAPP中的示例代码呈现的sigchild handler是非常简单的,显然不能满足我们的要求。我们不可以真的只用sigchild handler去回收子进程,而应该同时处理子进程结束,暂停,恢复这三种情况。为了实现这一点,我们就需要 WCONTINUED | WUNTRACED 这些选项,并充分利用status关键字来区分这三种情况。

        另外一点需要注意的是,我们必须要加入WNOHANG这个选项,因为当后台子进程未结束的时候,我们的shell不应该停下,应该继续处理其他进程,所以需要通过WNOHANG的指定,来退出循环。

        第三个坑:进程与进程组。的确,我们shell每fork一次子进程,都会新建立进程组,但子进程仍然可能继续fork其他的子进程,那么在执行kill指令,以及处理SIGINT和SIGTSTP时,我们必须格外的注意区分进程与进程组。

        在writeup里,指定了对于kill指令,进程与进程组明确的格式区分,但十分容易忽略的是,在处理SIGINT和SIGTSTP是,我们需要向整个前台进程组,都发送对应的信号。这就要求我们在调用kill函数的时候,应该传入的是-pid,以把信号传递到整个进程组,只是前台的单个进程。

        第四个坑:烦人的SIGCONT。对于SIGCONT,我们需要对付两种可能的情况:通过bg/fg恢复任务的运行,或者通过其他方式,比如子进程自己向自己发送信号使其恢复。我们之前提到了,在sigchild handler中可以统一处理这两种情况。

        但这里的一个小问题是,我们的sigchild handler不知道SIGCONT命令是用什么方式发送的,而sigchild handler必须决定,是将任务恢复到前台还是后台。为了解决这个问题,我加入了一个全局变量,用以记录是经由fg命令恢复的子进程,还是通过其他方式:这样,我们就可以通过调用该全局变量,决定任务应处于前台还是后台了!

        第五个坑,是我遇到的一个竞赛情况。我在这一点里要说的竞赛,在别的实现里不会遇到。这个竞赛出现在bg指令。我将SIGCONT恢复后台指令后打印的提示信息也放进了sigchild handler中,但可能出现一种情况,就是在bg指令所在处理循环结束后,sigchild handler才被调用,此时tsh >:的提示和后台指令恢复时打印的信息位置将会发生错乱。

        要解决这个问题,可以采取两种方式。一种是,干脆利落的,把提示信息的打印直接从handler里拿出来!实际上我们确实应该这样做,但当时我处理的时候,是在bg指令后,利用sigsuspend指令显式等待sigchild handler的返回。这样处理其实多少有点奇怪,但做lab的时候CPU烧了,恐怕来不及想这么多了(笑)。

        好了,我想说的其实就这么多。在实现的过程中,还遇到了很多乱七八糟的其他bug,但这些多少是因为个人的不小心。这也没什么办法,毕竟那也是几百行代码,结构也挺复杂的。

        顺带一提,由于竞赛这件事并不是一定会被trace的检查发现,有概率我们想要的进程刚好跑赢了,所以即使拿到了满分,也不一定说明代码就写对了。。。我最开始的代码有好几处问题,最后也可以拿到满分,所以我也不确定我的最终代码到底有没有问题。而且,由于时间原因,我也没有心情细心修整代码风格,注释也写得非常草率,望大家见谅了~

        代码传送门:
        Ubuntu Pastebin

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CSAPP Shell Lab是CMU(卡内基梅隆大学)计算机系统导论课程(CS:APP)中的一个实验项目,旨在帮助学生深入理解操作系统的概念和原理。 Shell是一个提供用户与操作系统交互的界面,通过Shell,用户可以在命令行中输入指令,并由操作系统执行相应的操作。Shell Lab要求学生实现一个简单的Shell程序,让用户能够在命令行中使用一些常用的Shell指令。 Shell Lab的源码主要由几个文件组成,其中最重要的是tsh.c。tsh.c包含了Shell程序的主要逻辑,它解析用户输入的命令,并调用相应的函数来执行命令。 Shell Lab还包括其他几个辅助文件,如jobs.c、jobs.h等,用于实现处理后台作业的功能。这些辅助文件定义了一些用于管理作业的数据结构和函数,比如作业列表、前台作业、后台作业等。 在Shell Lab的源码中,还包含一些示例代码,用于引导学生实现不同的功能。学生需要根据这些示例代码,实现一些必要的函数和模块,如解析并执行命令的函数、处理信号的函数、建立作业列表的函数等。 通过实现Shell Lab的源码,学生可深入理解Shell程序的原理和实现,了解操作系统的基本功能和工作原理。此外,这个实验项目还有助于学生提升编程能力和debug技巧,培养分析和解决问题的能力。 总结来说,CSAPP Shell Lab源码是一个用于实现一个简单Shell程序的源代码,通过对源码的学习和实践,学生可以深入理解Shell程序的原理和实现,提升编程技能和操作系统的理解能力。 ### 回答2: CSAPP(计算机系统:深入理解计算机系统)中的Shell Lab是一个实践项目,旨在通过实现一个简单的Unix shell来深入理解操作系统的工作原理。该项目的源码包括一些文件,其中最重要的是`tsh.c`和`jobs.c`。 `tsh.c`是主要的文件,包含了shell的主循环和处理函数。它通过读取用户输入的命令,解析并执行这些命令。`tsh.c`使用了信号处理、进程控制和作业控制等系统调用,以模拟真实的shell环境。 `jobs.c`是一个管理作业的辅助文件。它定义了用于管理和操作作业的数据结构和函数。通过`jobs.c`,我们可以追踪正在运行、已停止和已终止的作业,以及相关的进程。 在Shell Lab项目中,我们需要实现几个关键功能,例如在前台和后台运行作业、支持I/O重定向、支持管道命令和信号处理等。这些功能需要我们在`tsh.c`中添加相应的代码来实现。 实现Shell Lab的过程中,我们可以加深理解操作系统的多进程和作业控制机制。我们不仅需要了解Unix I/O模型和进程管理,还需要考虑如何处理信号、如何僵尸进程处理等问题。通过阅读和修改源码,我们可以深入理解这些概念和机制。 总而言之,CSAPP Shell Lab的源码是一个重要的教学资源,通过实际编程来理解操作系统的工作原理。通过阅读和修改源码,我们可以学习和实践操作系统的关键概念和技术。 ### 回答3: CSAPP shell lab 是CMU计算机系统课程的一个实验项目,旨在让学生通过编写一个简单的Unix Shell来加深对操作系统和进程管理的理解。 该实验提供了一个基本的Shell框架,学生需要在此基础上实现各种功能。主要分为四个部分: 1. 命令行解析:学生需要编写代码来解析用户输入的命令,包括参数、输入输出重定向和管道等功能。 2. 内建命令:学生需要实现一些内建命令,如cd和exit等,这些命令在Shell内部实现,不需要调用外部程序。 3. 外部程序执行:Shell需要能够执行非内建命令,即调用可执行文件或脚本。学生需要编写代码来创建子进程、加载可执行文件并将输出重定向到正确的文件描述符。 4. 作业控制:学生需要实现作业控制功能,即实现前台作业和后台作业的切换,以及作业的挂起和恢复等。 实验的难度较大,需要学生对操作系统和进程管理有一定的理解,并且要能熟练应用Unix系统调用等知识。实验中会提供详细的代码注释和文档,学生可以参考和借鉴。完成实验后,学生可以更深入地了解Shell是如何工作的,并且掌握一些系统编程的技巧。 总的来说,CSAPP shell lab是一个很好的实践项目,通过编写一个简单的Unix Shell,能够加深对操作系统和进程管理的理解,提高系统编程的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值