目录
一、设计目的.....................................................................................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