操作系统课设 简单 shell 命令行解释器的设计与实现
1、实验目的
本实验主要目的在于进一步学会如何在 Linux 系统下使用进程相关的系统调用,了解 shell 工作的基本原理, 自己动手为 Linux 操作系统设计一个简单的命令接口。
2、背景知识
本实验要使用创建子进程的 fork()函数,执行新的命令的 exec()系列函数,通常 shell 是等待子进程结束后再接受用户新的输入,这可以使用 waitpid()函数。以上相关的系统函数调用的说明请参见实验二的背景知识。
3、设计内容与要求
要设计的 shell 类似于 sh,bash,csh 等,必须支持以下内部命令:
- cd<目录>更改当前的工作目录到另一个<目录>。如果<目录>未指定,输出当前工作目录。如果<目录>不存在,应当有适当的错误信息提示。这个命令应该也能改变
PWD 的环境变量。 - environ 列出所有环境变量字符串的设置(类似于 Linux 系统下的 env 命令)。
- echo <内容 > 显示 echo 后的内容且换行
- help 简短概要的输出你的 shell 的使用方法和基本功能。
- jobs 输出 shell 当前的一系列子进程,必须提供子进程的命名和 PID 号。
- quit,exit,bye 退出 shell。
提示: shell 的主体就是反复下面的循环过程
while(1){
接收用户输入的命令行;
解析命令行;
if(用户命令为内部命令)
直接处理;
else if(用户命令为外部命令)
创建子进程执行命令;
else
提示错误的命令;
}
注意:linux上创建一个文件,复制下面代码,改文件名为.c编译运行即可.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
//help方法
void help()
{
char str[100];
scanf("%s", str);
if(strcmp("help", str) == 0){
printf("cd <目录>更改当前的工作目录到另一个<目录>\n");
printf("environ 列出所有环境变量字符串的设置\n");
printf("echo <内容 > 显示 echo 后的内容且换行\n");
printf("help 简短概要的输出你的 shell 的使用方法和基本功能\n");
printf("jobs 输出 shell 当前的一系列子进程,必须提供子进程的命名和 PID 号\n");
printf("quit,exit,bye 退出 shell\n");
}else
printf("程序错误!\n");
}
//quit||exit||bye退出方法
void quit()
{
char str[100];
scanf("%s", str);
if(strcmp("quit", str) == 0 || strcmp("exit", str) == 0 || strcmp("bye", str) == 0)
{
printf("shell 命令行解释器模拟结束!\n");
_exit(0);
}else
printf("程序错误!\n");
}
//cd跳转目录方法
void cd()
{
char sr[100];
char strpwd[301];
memset(strpwd,0,sizeof(strpwd));//出释怀数组函数
getcwd(strpwd,300);//获取当前工作目录字符串放到strpwd的前300个位置上
int i, j = 0;
char str[100];
char s[100];
int flag = 1;
fgets(str, 100, stdin);//获取输入的IO流 (命令行上的一行输入)
if(str[0] == 'c' && str[1] == 'd')
{
for(i = 3; i < strlen(str) ; i++)
{
if(str[i] == ' ')
{
flag = 0;
break;
}else
s[j++] = str[i];
}
for(i = 0; i < strlen(s) - 1; i++)
sr[i] = s[i];
if(flag == 0)
printf("当前目录是:%s\n",strpwd);
if(flag == 1)
{
printf("%d ", chdir(sr));
printf("当前目录是:%s\n",getcwd(strpwd,300));
}
}else
printf("程序错误!\n");
}
//environ显示环境变量字符串的设置
void environ()
{
char str[100];
fgets(str, 100, stdin);
pid_t pid = fork();
if(str[0] == 'e' && str[1] == 'n' && str[2] == 'v')
{
if(pid == 0)
execlp("env", "", NULL);
if(pid > 0)
wait(NULL);
}
}
//echo显示内容方法
void echo()
{
int i;
char str[100];
fgets(str, 100, stdin);
if(str[0] == 'e' && str[1] == 'c' && str[2] == 'h' && str[3] == 'o')
{
for(i = 5; i < strlen(str); i++){
putchar(str[i]);
}
printf("\n");
}else
printf("程序错误!\n");
}
//jobs显示子进程
void jobs()
{
char str[100];
fgets(str, 100, stdin);
pid_t pid = fork();
if(str[0] == 'j' && str[1] == 'o' && str[2] == 'b' && str[3] == 's')
{
if(pid ==0)
{
execlp("pstree", " ", "-p", NULL);
}
if(pid > 0)
wait(NULL);
}
}
int main()
{
int t;
while(1)
{
printf("-----------_-------_------\n");
printf(" shell 命令行解释器 \n");
printf("1:cd\n");
printf("2:environ\n");
printf("3:echo\n");
printf("4:help\n");
printf("5:job\n");
printf("6:quit||exit||bye\n");
printf("__------__----__---___--___--__-\n");
printf("请输入你要执行的操作:\n");
scanf("%d", &t);
switch(t){
case (1):
getchar();
cd();
break;
case (2):
getchar();
environ();
break;
case (3):
getchar();
echo();
break;
case (4):
getchar();
help();
break;
case (5):
getchar();
jobs();
break;
case (6):
getchar();
quit();
break;
}
}
return 0;
}