shell实现实习报告
目录
TOC \o "1-3" \h \z \u HYPERLINK \l "_Toc286402948"内容一:总体概述 PAGEREF _Toc286402948 \h 3
HYPERLINK \l "_Toc286402949"内容二:任务完成情况 PAGEREF _Toc286402949 \h 3
HYPERLINK \l "_Toc286402950"任务完成列表(Y/N) PAGEREF _Toc286402950 \h 3
HYPERLINK \l "_Toc286402951"具体Exercise的完成情况 PAGEREF _Toc286402951 \h 3
HYPERLINK \l "_Toc286402952"内容三:遇到的困难以及解决方法 PAGEREF _Toc286402952 \h 13
HYPERLINK \l "_Toc286402953"内容四:收获及感想 PAGEREF _Toc286402953 \h 13
HYPERLINK \l "_Toc286402954"内容五:对课程的意见和建议 PAGEREF _Toc286402954 \h 13
HYPERLINK \l "_Toc286402955"内容六:参考文献 PAGEREF _Toc286402955 \h 13
内容一:总体概述
本次实习需要实现用户程序shell。shell是提供使用者使用界面的软件(命令解析器),他接收用户命令,然后调用相应的应用程序。本次shell实现的基础是前面已经完成的相关功能。注意到nachos已经实现简单的shell,我们只需要在此基础上进行相关的修改。
内容二:任务完成情况
任务完成列表(Y/N)
Exercise
Y
具体Exercise的完成情况
设计实现一个用户程序shell,通过./nachos -x shell进入用户交互界面中。在该界面中可以查询支持的功能、可以创建删除文件或目录、可以执行另一个用户程序并输出运行结果,类似Linux上跑的bash。
你实现的越完善,碰到的问题越多,学到的也会越多。
本实验所修改的代码包括内核和用户程序两部分。
首先,需要解析输入的命令,这部分现有程序已经完成
Write(prompt, 2, output);
Read(&buffer[i], 1, input);
因为在Lab6中,我没有考虑标准输入和标准输出的问题,所以需要修改exception.cc处理read系统调用和处理write系统调用的部分
针对处理read系统调用的部分,如果系统调用的第3个参数是0(表示标准输入),那么读取从用户界面输入的字符串存入相应的位置
if(fd == 0){
for (int i = 0; i < count; i++)
content[i] = getchar();
}
针对处理write系统调用的部分,如果系统调用的第3个参数是1(表示标准输出),那么输出缓冲区字符串到用户界面
if(fd == 1) {
for(int i = 0; i < count; i++)
putchar(content[i]);
}
执行./nachos -x ../test/shell,shell启动
然后,确定需要实现的命令
功能
命令
使用方法
执行用户程序
x
x 用户程序
显示当前路径
pwd
pwd
列出当前目录
ls
ls
切换当前路径
cd
cd 路径
创建文件
nf
nf 文件名
创建文件夹
nd
nd 文件夹名
删除文件
df
df 文件名
删除文件夹
dd
dd 文件夹名
显示帮助信息
h
h
退出
q
q
部分指令的实现依赖已经实现的系统调用,部分指令的实现需要新的系统调用,添加系统调用的流程
(1)syscall.h中定义系统调用接口、系统调用号;
(2)start.s中添加链接代码;
(3)exception.cc中增加系统调用的处理过程.
执行用户程序 x
基本思路是通过已经实现的系统调用Exec执行用户程序,通过已经实现的系统调用Join等待用户程序执行结束
shell.c
if (buffer[0] == 'x' && buffer[1] == ' ') {
newProc = Exec(buffer + 2);
Join(newProc);
}
测试结果如下,用户程序正常执行
显示当前路径 pwd
基本思路是添加系统调用Pwd,基于C函数system实现显示当前路径
syscall.h
#define SC_Pwd 11
void Pwd();
start.s
Pwd:
addiu $2,$0,SC_Pwd
syscall
j $31
.end Pwd
exception.cc
shell.c
if (buffer[0] == 'p' && buffer[1] == 'w' && buffer[2] == 'd'
&& buffer[3] == '\0')
Pwd();
列出当前目录 ls
基本思路是添加系统调用Ls,基于C函数system实现显示当前路径
syscall.h
#define SC_Ls 12
void Ls();
start.s
Ls:
addiu $2,$0,SC_Ls
syscall
j $31
.end Ls
exception.cc
shell.c
if (buffer[0] == 'l' && buffer[1] == 's' && buffer[2] == '\0')
Ls();
显示当期路径,列出当前目录,结果符合实际
切换当前路径 cd
基本思路是添加系统调用Cd,基于C函数chdir实现切换当前路径
syscall.h
#define SC_Cd 13
void Cd(char* name);
start.s
Cd:
addiu $2,$0,SC_Cd
syscall
j $31
.end Cd
exception.cc
shell.c
if (buffer[0] == 'c' && buffer[1] == 'd'&& buffer[2] == ' ')
Cd(buffer + 3);
首先切换到上级目录(..),然后切换到目录test,结果符合实际
创建文件nf
基本思路是通过已经实现的系统调用Create创建文件
shell.c
if (buffer[0] == 'n' && buffer[1] == 'f'&& buffer[2] == ' ')
Create(buffer + 3);
删除文件 df
基本思路是添加系统调用Remove,基于已经实现的Remove函数实现文件的删除,删除文件时使用添加的系统调用Remove
syscall.h
#define SC_Remove 14
void Remove(char* name);
start.s
Remove:
addiu $2,$0,SC_Remove
syscall
j $31
.end Remove
exception.cc
shell.c
if (buffer[0] == 'd' && buffer[1] == 'f'&& buffer[2] == ' ')
Remove(buffer + 3);
在文件夹Lab7创建删除部分文件,结果符合实际
创建文件夹 nd
基本思路是添加系统调用CreateDir,基于C函数mkdir实现文件夹的建立
syscall.h
#define SC_CreateDir 15
voi