Lecture 1: Operating systems
Contents
Handouts
Homework: boot xv6
先去看完Lecture3再来做exercise。。。
Homework: shell
用C实现一个支持管道和重定向的shell
(我们只需补充部分代码,包括之后的作业都是如此)
readings
- Unix hands-on from 6.033
- The UNIX Time-Sharing System
- Chapter 0 of the xv6 book
parser
这部分代码不需要自己写,不过还是解释一下
parser部分的API:
execcmd(void) | execcmd的构造函数 |
pipecmd(struct cmd *left, struct cmd *right) | pipecmd的构造函数 |
redircmd(struct cmd *subcmd, char *file, int type) | redircmd的构造函数 |
getcmd(char *buf, int nbuf) | 从键盘读取命令 |
gettoken(char **ps, char *es, char **q, char **eq) | 从s读取并返回一个token |
peek(char **ps, char *es, char *toks) | 判断s的首个非空字符是否在toks字符串里 |
parsecmd(char *s) | 解析一个命令 |
parseline(char **ps, char *es) | 解析一行命令 |
parsepipe(char **ps, char *es) | 管道的优先级最高,首先解析管道 |
parseexec(char **ps, char *es) | 解析管道间的命令 |
parseredirs(struct cmd *cmd, char **ps, char *es) | 解析重定向符 |
runcmd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
char * add_with_path(char *exe) { DIR *dir; struct dirent *d; char *paths = getenv("PATH"); char *path = strtok(paths, ":"); while (path != NULL) { if ((dir = opendir(path)) != NULL) { while ((d = readdir(dir)) != NULL) { if (strcmp(d->d_name, exe) == 0) { char *final_path = (char *)malloc(strlen(path) + strlen(exe) + 2); final_path = strcat(final_path, path); final_path = strcat(final_path, "/"); final_path = strcat(final_path, exe); return final_path; } } } path = strtok(NULL, ":"); } return exe; } // Execute cmd. Never returns. void runcmd(struct cmd *cmd) { int p[2], r; 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 (execv(add_with_path(ecmd->argv[0]), ecmd->argv) == -1) perror("execv"); break; case '>': case '<': rcmd = (struct redircmd*)cmd; //fprintf(stderr, "redir not implemented\n"); // Your code here ... if (rcmd->type == '<') { close(0); if (open(rcmd->file, rcmd->mode) == -1) perror("open"); } else { close(1); if (open(rcmd->file, rcmd->mode, S_IRWXU) == -1) perror("open"); } runcmd(rcmd->cmd); break; case '|': pcmd = (struct pipecmd*)cmd; //fprintf(stderr, "pipe not implemented\n"); // Your code here ... if (pipe(p) == -1) { perror("pipe"); exit(EXIT_FAILURE); } if (fork1() == 0) { close(1); if (dup(p[1]) == -1) perror("pipe"); close(p[0]); close(p[1]); runcmd(pcmd->left); } if (fork1() == 0) { close(0); if (dup(p[0]) == -1) perror("pipe"); close(p[0]); close(p[1]); runcmd(pcmd->right); } close(p[0]); close(p[1]); wait(&r); wait(&r); break; } exit(0); } |
Lab 1: C, Assembly, Tools, and Bootstrapping
Exercise 1
熟悉汇编语言,参考资料:
- PC Assembly Language Book
- the section “The Syntax” in Brennan’s Guide to Inline Assembly
- 80386 Programmer’s Reference Manual
(我个人推荐CSAPP第二版的第三章,正好也是32位、AT&T语法,非常适合入门)
Exercise 2-12
先去看完Lecture2再来做exercise。。。