您的位置:首页 > 运维架构 > Shell

xv6-----shell

2015-11-18 09:37 429 查看
这是操作系统原理课程的第一个编程作业,补全shell的功能。

主要实现了基础的三类命令

可执行的程序命令

重定向命令

管道命令

实现的"基类" (原谅我用了这个词)就是struct cmd这个结构体就一个成员,用于记录命令的类型.

三类, ' ' 表示可执行程序 '|' 表示管道命令,  '<' 和'>' 表示重定向类型.

每一个类型分别继承基类,派生出对应的三类结构体

struct execcmd

struct redircmd

struct pipecmd

void runcmd(struct cmd * cmd);

这个函数是真正驱动调用实现shell的核心.负责调用系统接口函数 execv(), open(), close(), dup(), pipe()等等一系列函数,来完成我们既定的目标.

作业也就是补全这个函数.

这是个递归的函数!

下面是来自github上的代码,仅摘录runcmd函数

 1 void
runcmd(struct cmd *cmd)
{
int p[2]; // used for pipe line in shell
int r;    // return value
struct execcmd *ecmd;
struct pipecmd *pcmd;
struct redircmd *rcmd;

if(cmd == 0)
exit(0);

switch(cmd->type){
default:
fprintf(stderr, "unknown runcmd\n");
exit(-1);

case ' ':
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0)
exit(0);
//fprintf(stderr, "exec not implemented\n");
// Your code here ...
if (access(ecmd->argv[0], S_IXUSR | S_IRUSR) == 0)
{
execv(ecmd->argv[0], ecmd->argv);
}
else
{
if(chdir("/bin/") < 0)
{
printf("change directory failed in line %d\n", __LINE__);
exit(0);
}
execv(ecmd->argv[0], ecmd->argv);
}
fprintf(stderr, "execv() %s failed in line %d\n", ecmd->argv[0], __LINE__);
break;

case '>':
case '<':
rcmd = (struct redircmd*)cmd;
//fprintf(stderr, "redir not implemented\n");
// Your code here ...
close(rcmd->fd);
if(open(rcmd->file, rcmd->mode) < 0)
{
fprintf(stderr, "Try to open :%s failed\n", rcmd->file);
exit(0);
}
runcmd(rcmd->cmd);
break;

case '|':
pcmd = (struct pipecmd*)cmd;
//fprintf(stderr, "pipe not implemented\n");
// Your code here ...
if(pipe(p) < 0)
{
fprintf(stderr, "call syscall pipe() failed in line %d\n", __LINE__);
exit(0);
}

if(fork1() == 0)
{
close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
runcmd(pcmd->left);
}

if(fork1() == 0)
{
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
runcmd(pcmd->right);
}

close(p[0]);
close(p[1]);
wait();
wait();
break;
}

exit(0);
}


有兴趣可以点击查看详情
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: