logo资料库

模拟shell命令解释器操作系统课程设计报告.doc

第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
资料共15页,剩余部分请下载后查看
一、设计目的
二、设计内容
1、概述
在shell命令里,我们将ysh中的命令分成4种:普通命令,重定向命令,管道命令和内部命令。这4种命
2、设计原理
三、详细设计及编码
四、运行结果分析
五、设计小结
六、参考文献
七、源代码
目录 一、设计目的.....................................................................................1 二、设计内容.....................................................................................2 1、概述......................................................................................... 2 2、设计原理................................................................................. 2 三、详细设计及编码.........................................................................5 四、运行结果分析.............................................................................9 五、设计小结...................................................................................11 六、参考文献...................................................................................12 七、源代码.......................................................................................13
一、设计目的 在 Linux/Unix 上 用 C 语 言 开 发 一 个 下 命 令 解 释 程 序 , 软 件 能 在 Linux/Unix 平台下运行,该程序应提供一个命令提示符:如 ysh>,表示接收 用户的输入,每次执行完成后再打印下一个命令提示符 ysh>。要求能够完成 如下功能:能够执行外部程序命令;能够执行调度作业等内部命令;支持管道和 输入输出重定向;支持前后台作业,提供作业控制功能,包括打印作业清单,改 变作业的状态,以及控制作业的运行情况。 1
二、设计内容 1、概述 本次课程设计主要是熟悉操作系统的命令接口及程序接口的基础上,利用 C/C++语言设计简单的命令接口,命令接口基于 Linux 的命令行接口,通过命 令解释程序接受命令及其参数,调用相应的命令接口,完成类似与 shell 命 令提示符功能的系统功能,本次课程设计只是编写部分的命令接口函数,只 是模拟 shell 系统功能调用的整个过程。 初始化环境 打印提示符,获取用户输入的命令 解析命令 寻找命令文件 执行命令 程序结束 图 1 程序设计流程图 在 shell 命令里,我们将 ysh 中的命令分成 4 种:普通命令,重定向命令, 管道命令和内部命令。这 4 种命令的分析和执行各部相同,每一种命令的分析执 行过程包括:初始化环境,打印提示符,获取用户输入的命令,解析命令,寻找 命令文件和执行命令几个步骤。 2、设计原理 2
作业控制的命令主要包括:jobs、bg 和 fg 等。 1. jobs 命令 每个后台运行的作业或被挂起的作业,在链接表中都有一个节点与其对应。 所以,在用户输入命令后的运行一个在后台执行的作业时,作业控制要做的是: 在链表尾部增加一个节点,将该作业的信息保存在新加的节点中。而在一个前台 的作业被挂起时,作业控制要做的工作是:检索链表,如果链表已有改作业对应 的节点,将该作业的信息保存在新加的节点中,当用户输入 jobs 命令时,要做 的工作是:遍历链表,将链表中的每个作业信息(作业号,运行状态和命令名) 显示出来,了解了链表的操作,jobs 这部分的程序就不难完成了。 2. bg 和 fg 命令 bg 命令可以将已被挂起的作业放到后台运行。而 fg 命令则可以将被起的或 在后台运行的作业放到前台来运行。 我们在程序开始时设置了信号处理函数: Signal(SIGTSTP,ctrl_z); SIGTSTP 是交互停止信号。当用户在终端按上下组合键 Ctrl+Z 时,终端 驱动程序会像 shell 发送此信号。而信号处理函数 signal 可以捕捉到这个 SIGTSTP 信号,可以看到函数 signal 的设置:当收到 SIGTSTP 信号时,执行函 数 ctrl+z。在我们的程序中,ctrl_z 函数所做的动作是增加作业节点,并将其 状态设置为 stopped,并用系统调用函数 kill 向前台运行的命令发送一个 SIGSTOP 信号。SIGSTOP 信号的作用是停止一个进程。前台运行的作业在收到这 个 SIGSTOP 信号后将被挂起。前台的运行的作业被挂起后,shell 就会打印出提 示符 ysh>,等待用户输入下一条命令。这时我们就可以使用 bg 和 fg 命令惊醒前 后台切换了。 如果我们希望使一项被挂起的作业在后台执行,用“bg%作业好”这条命令 就能实现。用户输入 bg 命令后,程序首先根据命令,获取用户输入的作业号。 得到作业号后,执行函数 bg_cmd。函数 bg_cmd 要做的工作是:根据作业号,在 jobs 链表中查找到相应节点,在节点信息中得到该作业对应的进程号 pid。再用 系统调用函数 kill 向进程号为 pid 的进程在接收到这个信号。SIGCONT 信号的 作用是使进程继续运行。进程号为 pid 的进程在接收到着这个信号后,就会重新 3
开始运行了。由于我们没有使用函数 waitpid 让父进程等待该进程的完成,所以 刚才重新开始运行的进程是在后台运行的。 当我们要把一项作业放到前台来运行,用“fg%作业号”就能实现。用户输 入 fg 命令后,程序首先根据命令获取用户输入的作业号。得到作业号后,执行 函数 fg_cmd。函数 fg_cmd 中要做的工作是根据作业号,在 jobs 链表中查找到 相应节点,在节点信息中得到该作业对应的进程号 pid。再用系统调用函数 kill 向进程号为 pid 的进程发送一个 SIGCONT 信号。进程号为 pid 的进程在接收到这 个信号后,就会重新开始运行了。与命令不同的是,要在前台运行该作业。所以, 在函数 fg_cmd 中不要用系统调用函数 waitpid,让父进程等待刚才重新开始运 行的进程,这样才能达到在前台运行作业的目的[1]。 4
三、详细设计及编码 由于我们把作业以链表的形式保存起来,所以在处理 jobs 命令时,实际上 就是对链表的操作。 首先定义链表的节点: typedef struct NODE{ pid_t pid; char cmd[100]; char state[100]; struct NODE link; }NODE; NODE *head,*end; head 指针指向链表表头,end 指针指向链表表尾。 在用户输入命令后的运行一个在后台执行的作业时,作业控制要做的是: 在链表尾部增加一个节点,将该作业的信息保存在新加的节点中。而在一个前台 的作业被挂起时,作业控制要做的工作是:检索链表,如果链表已有改作业对应 的节点,将该作业的信息保存在新加的节点中,当用户输入 jobs 命令时,要做 的工作是:遍历链表,将链表中的每个作业信息(作业号,运行状态和命令名) 显示出来,流程图如下: 5
用户输入 运行作业 运 行 一 个 后 台 执 一 个 前 台 作 业 被 行的作业 挂起 在 链 表 尾 部 增 加 一个节点,并将该作 业 的 信 息 保 存 在 新 加的节点中 检索链表,链表中存在 该作业对应的节点 Y 将 该 作 业 的 状 态 改成 stopped N 在 链 表 尾 部 增 加 一个节点,并将该作 业 的 信 息 保 存 在 新 加的节点中 执行 jobs 命令 显示作业的信息,作业号、状态、命令名 结束 图 3 jobs 命令执行时的流程图 用户输入 bg 命令后,程序首先根据命令,获取用户输入的作业号。得到作业 号后,执行函数 bg_cmd。函数 bg_cmd 要做的工作是:根据作业号,在 jobs 链 表中查找到相应节点,在节点信息中得到该作业对应的进程号 pid。再用系统调 用函数 kill 向进程号为 pid 的进程在接收到这个信号。SIGCONT 信号的作用是 6
使进程继续运行。进程号为 pid 的进程在接收到着这个信号后,就会重新开始运 行了。由于我们没有使用函数 waitpid 让父进程等待该进程的完成,所以刚才重 新开始运行的进程是在后台运行的,具体的流程图如下图所示: N 获取命令 和作业号 根据作业号遍历链表 是否存在节点 Y 向对应工作发送 SIGCONT 信 号,使其在后台运行 修改对应的节点 图 4 bg 命令执行时的流程图 用户输入 fg 命令后,程序首先根据命令获取用户输入的作业号。得到作业 号后,执行函数 fg_cmd。函数 fg_cmd 中要做的工作是根据作业号,在 jobs 链 表中查找到相应节点,在节点信息中得到该作业对应的进程号 pid。再用系统调 用函数 kill 向进程号为 pid 的进程发送一个 SIGCONT 信号。进程号为 pid 的进 程在接收到这个信号后,就会重新开始运行了。与命令不同的是,要在前台运行 该作业。所以,在函数 fg_cmd 中不要用系统调用函数 waitpid,让父进程等待 刚才重新开始运行的进程,这样才能达到在前台运行作业的目的,具体的流程图 如下图所示: 7
分享到:
收藏