【CSAPP】-shelllab实验

目录

实验目的与要求

实验原理与内容

实验设备与软件环境

实验过程与结果(可贴图)

实验总结


实验目的与要求


【实验目的】:
1、理解进程控制的概念和具体操作方法;
2、理解信号的概念和具体使用方法;
3、理解Unix shell程序的原理和实现方法;
【实验要求】:
本实验的内容是编写一个简单的shell程序“tsh”

实验原理与内容


【实验原理】:
shell是一种交互式的命令行解释器,能代表用户运行程序。shell反复打印一个提示符等待stdin上的命令行,然后按照命令行的内容执行命令,如下图所示:

命令行是由空格分隔的ASCII字符串。命令行的第一个字符串要么是一个内置命令的名称,要么是一个可执行文件的路径名,剩下的字符串则为命令行参数。如果命令行的第一个字符串是一个内置命令,则shell会立即在当前进程中执行该命令。如果命令行的第一个字符串不是一个内置命令,shell会假定该字符串是一个可执行文件的路径名,在这种情况下shell会创建一个子进程并在子进程的上下文中加载和执行该可执行文件。每运行一个可执行文件将创建一个子进程,这些子进程组成shell的工作集,工作集中的各个子进程可以通过Unix管道进行连接。
如果命令行以符号“&”结尾,那么程序会在后台执行,这意味着shell不会等待程序的终止,shell会立即打印提示符并等待下一个命令输入。否则,程序会在前台执行,这意味着shell会等待程序终止后才能接收下一个命令行的输入。因此,在某一时刻系统中最多只能有一个前台任务,但是可以有任意数量的后台任务。
Unix shell支持任务控制的概念,它允许用户将任务在后台和前台之间来回切换,并更改任务中进程的状态(运行、停止或终止)。Unix shell还提供各种支持任务控制的内置命令。例如:
• jobs: 列出正在运行或已经停止的后台任务.  
• bg <job>: 将一个停止的后台任务启动起来.
• fg <job>: 将一个正在执行的或已经停止的后台任务切换到前台并运行起来.  
• kill <job>:终止一个任务.

【实验内容】
“tsh”要具有以下功能:
(1)命令行提示符字符串应为“tsh> ”。
(2)用户输入的命令行应由一个命令名称以及0个或多个参数所组成,命令名称和各个参数之间用一个或多个空格隔开。如果命令名称是一个内置命令,则tsh将在当前进程马上执行该命令然后才能接收下一个命令行输入。否则tsh应该假设该命令名称是一个可执行文件,并在子进程的上下文中加载和执行该可执行文件。
(3)tsh不需要有管道和IO重定向功能。
(4)输入ctrl-c(或ctrl-z)将发送一个SIGINT(或SIGTSTP)信号到当前前台任务以及该任务的任何子进程(它fork出来的任何子进程)。如果当前没有前台任务,则信号不应该产生任何作用。
(5)如果命令行是以“&”结尾的话,则命令要在后台执行,否则要在前台执行。
(6)tsh要给每一个任务分配一个正整数作为进程ID(PID)或任务ID(JID)。JID在命令行通过“%”进行引用,例如“%5”代表JID 5。而PID在命令行中直接通过数字引用,例如“5”代表PID 5。
(7)tsh要支持下列内置命令:
    quit:终止并退出tsh程序;
    jobs:列出所有后台任务;
    bg <job>:给<job>发送一个SIGCONT信号使其在后台继续运行起来,<job>参数可以是PID或JID。
    fg <job>:给<job>发送一个SIGCONT信号使其在前台继续运行起来,<job>参数可以是PID或JID。
(8)tsh要回收其所有的僵死子进程。如果任何进程因接收到没有在其进程中被捕获的信号而终止,那么tsh应该识别到这个事件,并打印一条带有进程PID和对该信号描述的信息。

实验设备与软件环境


1.Linux操作系统—64位 Ubuntu 18.04
2. C编译环境(gcc)
3. 计算机

实验过程与结果(可贴图)

通过make clean和make指令来实现所有程序包括tsh.c的编译,若没有错误则会直接显示gcc编译的文件的指令,一共编译了5个文件;

使用make test XX和make rtest XX指令比较traceXX.txt文件在自己编写的shell和shell上的执行结果(相当于使用了”./sdriver.pl -t traceXX.txt -s ./tsh -a “-p”和”./sdriver.pl -t traceXX.txt -s ./tshref -a “-p” 指令,直接使用这两个指令也可以实现),两者的反馈结果相同为正确终止则说明编写的shell是正确的;

在EOF上正常终止,tsh和tshref执行结果相同;
CLOSE、WAIT这两条命令并不由tsh中的内置命令执行,
可以在EOF上正确的终止;

编写实现eval,builtin_cmd函数

首先从命令中提取参数,然后判断是否为内置命令,如果为内置命令,则直接在当前进程执行即可;如果不是内置命令,则需要新建一个子进程,并利用 execve 来通过参数给出的路径寻找出可执行文件并在子进程中执行,如果找不到该可执行文件,则输出命令未找到,并结束子进程。

执行 eval(),在 eval中发现如果命令不是内置命令,则会调用 fork()函数来新建一个子进程,在子进程中调用 execve()函数来寻找路径,并在子进程中运行路径中的可执行文件,如果找不到可执行文件,则说明命令为无效命令,输出命令无效,并用 exit结束该子进程即可。

与quit命令相关则是直接判断是否为quit命令,如果是则exit退出


用test02和test03验证是否正确


我们接下来看一下job的成员
job struct由pid(当前进程的ID)、jid(作业id)、state(状态,如右图分为未定义、前后台、停止四种)、cmdline(命令)组成


直接在eval函数进行作业添加至后台作业管理的功能的添加

Test04验证结果

jobs内建命令就是打印作业列表的功能
jobs: 列出正在运行或已经停止的后台任务.
在原有builtin_cmd函数中添加一个判断函数,如果命令是内置jobs,则执行listjobs函数(打印作业表)


验证结果

Trace06的结果是正确执行终止进程并且输出了一条相关信息
实现sigint_handler()、waitfg()、sigchld_handler()函数

sigint_handler函数需要实现终止作业的功能(主要使用kill函数实现SIGINT信号的发送)

waitfg的作用与waitpid的作用类似,它是在pid进程变成非前台进程之前保持阻塞状态

首先得到进程ID为pid的作业,接着使用while(1)循环来保证在满足条件job被终止或者停止(ST状态由fg加ctrl-z得到)前一直是阻塞状态


sigchld_handler()回收僵死函数
首先利用waitpid函数得到被终止或停止的子进程id、参数WUNTRACED|WNOHANG检测子进程终止或停止,status获得状态;后面用WIFEXITED(status),WIFSIGNALED(status),WIFSTOPPED(status)等来获得waitpid中终止或者停止的子进程的退出状态,根据该状态来进行不同的处理;

通过验证trace06和07,查看tsh与标准tshref的执行结果是否相同


实现sigtstp_handler捕获TSTP响应、验证trace08
该命令的作用是将在前台作业停止(STOP)


正确的捕获了TSTP响应,将前台进程停止,输出的作业列表与tshref标准输出除了pid外相同,说明sigtstp_handler函数的编写完全可行

实现内建命令bg和fg的do_bgfg处理函数
判断是否会出现命令错误。找到需要操作的进程(注意‘%’号,有则表示为通过jid以及getjobjid函数找到job后得到pid,无则表示通过pid以及getjobpid函数得到job判断job是否存在),然后用kill函数对它发出SIGCONT信号


trace09中bg %2命令被正确执行后会将作业2放到转为后台运行,jobs后[2]显示running;trace10中执行fg %1会将后台的作业1停止之后添加到前台运行直到终止,故jobs后列表为空,可以看出执行结果已经与ref-tsh一致


到了这里的话我们的函数就已经实现完成了,
下面是将其他的trace验证是否一致的过程


11


我这里显示的ps a是一样的,所以正确

12

13

 


14


15

16

后面我直接看tshref.out文件,对比了一下
证明了我的函数实现也是没问题的


实验总结


通过这个实验,我更加了解了shell在linux下的运行原理,这对我来说算是一个打基础的过程,对于shell的理解更加深刻,在慢慢理清了运行顺序和情况、信号的作用、进程的运行情况和周期以及运行过程,然后一步步的实现,理解了操作系统和硬件如何协作处理异常,掌握了异常处理程序的设计与实现,增强了对系统底层机制的洞察力。
 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值