MIT6.828 Homework 2 : shell

实验出处shell

1.准备阶段

ps:(如果想直接看源码解析请跳转到目录2.源码解析)

1.1 文件I/O(文件重定向)

文件描述符:STDIN_FILENO ---------- 0
		  STDOUT_FILENO---------- 1
		  STDERR_FILENO---------- 2
文件描述符的范围是0~OPEN_MAX

重定向分为 “<", “>”,"<<",">>"
cmd < file: 将文件作为命令的标准输入
cmd < file1 > file2:将文件1作为命令的标准输入,将标准输出重定向到文件2中

1.2 管道

管道:进程通讯工具 半双工通讯

如: ls | wc

将ls的输出流入到管道中,在从管道流出到wc,知道这些我们将引出pipe()函数

int p[2]; //数组用来存储一对文件描述符
pipe(p);
p[0]; //流入管道中的信息
p[1]; //流出管道中的信息

1.3 函数准备

需要认识的函数(均在unix高级编程这本书中可以查阅)

pipe();
access();
dup();
exec(); //系列函数
close();
fork();
fprintf();

这些函数需要细致的弄清楚

2.源码解析(这里我们只提供需要coding的部分)

2.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],F_OK)==0){
    	execv(ecmd->argv[0],ecmd->argv); //判断文件是否存在 存在就执行
    }else{
    	const char* path_get[] = {"/bin/","/usr/bin/"}; //不存在的原因可能是绝对路径的选择,通过数组中绝对路径的选择来再次判断执行
	char* abs_path;
	int found = 0;  //只要找到一个就停止寻找了
	int path_count = sizeof(path_get) / sizeof(path_get[0]);
	for(int i = 0;i<path_count && found==0;i++){
		int len = strlen(path_get[i]) + strlen(ecmd->argv[0]);
		abs_path = (char *)malloc(len+1*sizeof(char));
		strcpy(abs_path,path_get[i]);
		strcat(abs_path,ecmd->argv[0]);
		if(access(abs_path,F_OK)==0)
			execv(abs_path,ecmd->argv);  //正确的绝对路径并且执行
		found = 1;
	}
	free(abs_path);
    }

    break;


2.2 重定向部分

  case '<':
    rcmd = (struct redircmd*)cmd;
    // fprintf(stderr, "redir not implemented\n");
    // Your code here ...
    close(rcmd->fd); //关闭一开始的文件描述符
    if(open(rcmd->file,rcmd->flags, 0644)<0){ //打开文件到标准输入中
	    fprintf(stderr,"open file: %s failed",rcmd->file);
	    exit(0);
    }
    runcmd(rcmd->cmd);
    break;

2.3管道部分

  case '|':
    pcmd = (struct pipecmd*)cmd;
    //  fprintf(stderr, "pipe not implemented\n");
    // Your code here ...
    if(pipe(p) < 0)
	    fprintf(stderr,"pipe failed\n");
    if(fork1()==0){
	  close(0); //关闭标准输入
	  dup(p[0]);  //p[0]代表流出管道流出进入右边的命令
	  close(p[0]);
	  close(p[1]);
	  runcmd(pcmd->right);

    }else { //此时考虑命令流入pipe中 cmd |
    	close(1);  //关闭标准输出
	dup(p[1]); //p[1]代表流入左边命令流入管道
    	close(p[0]);
	close(p[1]);
	runcmd(pcmd->left);
    }
    break;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值