首页 > 系统相关 >MIT 6.828 Homework: shell

MIT 6.828 Homework: shell

时间:2022-11-11 11:47:44浏览次数:43  
标签:shell const int char sh file open MIT Homework

实验提供了一个shell的简化版本,主要功能是解析shell命令并且执行

在提供的shell代码中已经编写好了对命令进行解析的部分,我们需要的是利用Unix系统调用对命令进行执行

Executing simple commands

任务: 执行简单的命令,如:

$ ls

要完成简单命令的执行,应该补全runcmd函数中“ case ' ' ”部分的代码

查询exec系统调用的man手册:

int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
char *const envp[]);

p - execlp(), execvp(), execvpe()

These functions duplicate the actions of the shell in searching for an executable file if the specified file‐name does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn't defined, the path list defaults to a list that includes the directories returned by confstr(_CS_PATH) (which typically returns the value "/bin:/usr/bin") and possibly also the current working directory; see NOTES for further details.

If the specified filename includes a slash character, then PATH is ignored, and the file at the specified pathname is executed.

综合来看,应该选择exevp()系统调用,接受的参数的包括待执行的文件以及参数列表。其中,*file会在PATH环境变量中搜索,如果含有/,则不在PATH中搜索,而将其视为路径名。这样,无论是类似/bin/ls这样的命令,还是ls这样的命令,都能够成功执行

添加的代码如下:

case ' ':
  ecmd = (struct execcmd*)cmd;
  if(ecmd->argv[0] == 0)
    exit(0);
  if(execvp(ecmd->argv[0], ecmd->argv) == -1)
    fprintf(stderr, "command not found: %s\n", ecmd->argv[0]);
  break;

测试的结果如下:

6.828$ ls
makefile  note.md  sh  sh.c  t.sh  x.txt
6.828$ /bin/ls
makefile  note.md  sh  sh.c  t.sh  x.txt

I/O redirection

任务: 实现 < 和 > 指示的I/O重定向功能

这里要使用open系统调用打开重定向指示的文件,查询man手册可知,open接受两个或三个参数:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

pathname是要打开的文件路径,flags是打开文件所要使用的操作,mode是如果新建文件,文件访问权限的初始值,如果没有新建文件,mode参数会被忽略,参数的具体值详见man手册

这里因为可能需要新建文件,所以使用三个参数的版本:

open(rcmd->file, rcmd->mode, S_IRWXU | S_IRWXG | S_IRWXO)

注意(都是本人踩过的坑):

  1. 在调用open前记得调用close关闭原本的文件描述符rcmd->fd
  2. 关注mode参数的值,避免新建的文件无法被后面的命令打开读取

添加的完整代码如下:

case '>':
case '<':
  rcmd = (struct redircmd*)cmd;
  close(rcmd->fd);
  if(open(rcmd->file, rcmd->mode, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
  {
    fprintf(stderr, "fail to open file %s\n", rcmd->file);
    exit(EXIT_FAILURE);
  }
  runcmd(rcmd->cmd);
  break;

测试的结果如下:

6.828$ echo operating-system > x.txt
6.828$ cat < x.txt
operating-system

Implement pipes

任务: 实现通过管道执行连续的命令

通过Xv6手册的内容结合pipe的man手册的内容可以对管道的使用有一个大概的了解,这里实际上是通过新建一个进程,由父子进程分别执行管道左右两端的命令,通过管道将一侧的命令的输出传递给另一侧命令的输入;这本质上也是一种重定向,将左侧命令的输出重定向,输出到管道的输入端,将右侧命令的输入重定向,从管道的输出端输入

通过man手册查询实验中提示的pipe, fork, close, dup系统调用之后,就可以成功编写出代码了

推荐使用dup2:

int dup2(int oldfd, int newfd);

功能是关闭newfd指向的文件,并让newfd指向oldfd指向的文件,如果newfd和oldfd指向同一个文件,dup2不作任何操作,如果oldfd不是合法的文件描述符,则dup2不会关闭newfd指向的文件,并且系统调用会失败

添加的代码如下:

case '|':
  pcmd = (struct pipecmd*)cmd;
  if(pipe(p) == -1)
  {
    fprintf(stderr, "fail to create a pipe\n");
    exit(EXIT_FAILURE);
  }
  if(fork() == 0)
  {
    dup2(p[1], STDOUT_FILENO);
    runcmd(pcmd->right);
  }
  else
  {
    dup2(p[0], STDIN_FILENO);
    runcmd(pcmd->left);
  }
  break;

测试的结果如下:

2440078$ ls | sort | uniq | wc
makefile  note.md  sh  sh.c  t.sh  x.txt

标签:shell,const,int,char,sh,file,open,MIT,Homework
From: https://www.cnblogs.com/tea-in-the-snow/p/16880042.html

相关文章

  • Android实战简易教程-第四十三枪(Shell Script 运行Command)
    android系统运行于DalvikVM中,有着与Linux雷士的ShellCommand指令,可通过Runtime().getRuntime().exec()来运行指令。下面我们就通过代码来实现这一功能,体验一下命令行。1.a......
  • ulimit命令优化linux进程连接数等…
    在Linux下面部署应用的时候,有时候会遇上Socket/File:Can’topensomanyfiles的问题,比如还有Squid做代理,当文件打开数到900多时速能就非常快的下降,有可能打不开网页.其......
  • python和shell产生随机密码,哪个更方便
    一、Python#@File:生成随机密码.py#@desc:importstringimportrandom####侯选all_words=list(string.ascii_lowercase+string.ascii_uppercase+string.digits......
  • MIT 6.828 Homework: Xv6 System Calls
    PartOne:Systemcalltracing任务:修改Xv6内核的代码来打印出每个系统调用以及返回值根据提示,应该在syscall.c中修改syscall()。首先在syscall.c中增加对应系统调用名......
  • 获取shell脚本所在目录
    前几天写的​​七牛​​​的参赛demo,用bash写了一个便捷安装的脚本,涉及到了路径相关的判断,从​​stackoverflow​​,加上自己的实践整理一下。简单版下面是一个最简单的实现,......
  • MIT6.S081笔记:Lab Xv6 And Unix Utilities
    关于MIT6.S081这门课的前身是MIT著名的课程6.828,MIT的几位教授为了这门课曾专门开发了一个基于x86的教学用操作系统JOS,被众多名校作为自己的操统课程实验。但随......
  • shell脚本 查找出所有包含某关键词的文件名称,并输出第一个
    代码如下:#!/bin/basha=(`grep-r-l“thm_core”src/meta/connectivity`)echo${a[0]}#a是数组变量,需要注意的是“=”与“()”之间不能有空格#grep-r-l查找出在src/......
  • 操作系统实验:Shell脚本编程与Vim编辑器
    SHANGHAIUNIVERSITY操作系统(一)实验报告组号第4组学号姓名20120889实验序号实验六日期2022年9月10日一、实验目的与要求实验目的:掌握v......
  • Shell 脚本一直提示找不到文件或文件夹
    编写shell脚本,在外部命令行执行命令没有问题,放到脚本中后,在执行的过程中却一直提示找不到文件打开test.sh脚本vitest.sh查看脚本文件格式在命令模式下输入:setff......
  • shell中算术运算加减
    在shell脚本中,所有的变量默认都是字符串存储,操作也是按照字符串进行处理的,但我们不可避免的需要对各中数值进行算术运算,如算术的相加减,那么这时怎么处理呢?在shell脚本中,我......