Xv6的lecture
LEC 1 Operating systems
L1: O/S overview
L1:O/S概述
* 6.828 goals
6.828的目標
Understand operating systems in detail by designing and implementing a small O/S
通過設計並實現一個小型的系統在細節上理解操作系統。
Hands-on experience with building systems("Applying 6.033")
構建系統來完成練習。
* What do applications want from an O/S?
從程序角度看操作系統需要提供什么?
* Abstract the hardware for convenience and portability
對硬件進行抽象使其方便使用和移植
* Multiplex the hardware among multiple applications
在多個程序間復用硬件資源
* Isolate applications to contain bugs
隔離程序阻止錯誤蔓延
* Allow sharing among applications
允許程序間共享資源
* What is an OS?
什么是操作系統?
* e.g. OSX, Windows, Linux
例如OSX、Windows和linux
* the small view: a h/w management library
狹義:硬件的管理庫
* the big view: physical machine -> abstract one w/ better properties
廣義:物理機器 -> 具有更好特性的抽象機器
* Organization: layered picture
結構:分層圖像
h/w: CPU, mem, disk
硬件:CPU、內存、磁盤
kernel: [various services]
內核:多種服務
user: applications, e.g. vi and gcc
用戶:應用程序,如vi和gcc
we care a lot about the interfaces and internel kernel structure
我們更關心接口和內核的內部結構
* What services does an O/S kernel typically provide?
一個典型的操作系統內核需要提供什么服務?
* processes
進程
* memory
內存管理
* file contents
文件內容
* directories and file names
目錄和文件名稱
* security
安全
* many others: users, IPC, network, time, terminals
其他:用戶、IPC、網絡、時間和終端
* What does an O/S abstraction look like?
操作系統的抽象看來什么樣?
* Applications only see them via system calls
應用程序僅能通過系統調用看到它們。
* Examples, from UNIX / Linux:
例如:在UNIX或Linux中:
```
fd = open("out", 1);
write(fd, "hello\n", 6);
pid = fork();
```
* Why is O/S design/implementation hard/interesting?
為什么操作系統的設計和實現是如此難又是有趣的?
* the environment is unforgiving: weird h/w, no debugger
實驗環境不好:古怪的硬件、沒有調試器
* it must be efficient (thus low-level?)
它必須是高效的(那么就是低層次的?)
...but abstract/portable (thus high-level?)
…但是抽象/可移植(這是高層次的?)
* powerful (thus many features?)
功能強大(更多特性?)
...but simple (thus a few composable building blocks?)
…但是簡單(較少的可組合的構建模塊?)
* features interact: `fd = open(); ...; fork()`
內部特性: fd = open(); …; fork()
* behaviors interact: CPU priority vs memory allocator.
內部行為:CPU特權對比內存分配
* open problems: security, multi-core
開放的問題:安全、多核心
* You'll be glad you learned about operating systems if you...
學習操作系統后你可能會願意做以下事情…
* want to work on the above problems
想要解決上面的問題
* care about what's going on under the hood
關心那層布下面發生了什么
* have to build high-performance systems
願意去構建一個高效的系統
* need to diagnose bugs or security problems
願意去分析錯誤或是安全問題
Class structure
課程結構
* See web site: http://pdos.lcs.mit.edu/6.828
* Lectures
課程
* basic O/S ideas
基本的操作系統概念
* extended inspection of xv6, a traditional O/S
Xv6,一個傳統的操作系統的擴展的分析
* several more recent topics
幾個較新的話題
* xv6 programming to re-inforce xv6 understanding
從xv6的編碼到對重新加強的xv6的理解
* Lab: JOS, a small O/S for x86 in an exokernel style
實驗:JOS,為x86平台所寫的一個小型的微內核操作系統
* you build it, 5 labs + final lab of your choice
你要完成5個實驗和一個最終的選做實驗
* kernel interface: expose hardware, but protect -- no abstractions!
內核接口:暴露硬件,但要在沒有抽象的前提下進行保護!
* unprivileged library: fork, exec, pipe, ...
非特權庫:fork,exec,pipe,…
* applications: file system, shell, ..
應用:文件系統,shell,…
* development environment: gcc, qemu
開發環境:gcc,qemu
* lab 1 is out
實驗1已經不合適了
* make grade
升級吧
Code review
代碼概述
* Two quizzes: one in class hours, one in final's week
兩個小測驗:一個是隨堂測驗,另一個在本周結束
## Shell and system calls
Shell和系統調用
* 6.828 is largely about design and implementation of system call interface. let's start by looking at how programs use that interface.
6.828大部分內容都是設計和實現系統調用接口。讓我們從一個程序如何使用接口開始看。
example:
例如:
the Unix shell.
Unix的shell。
* the shell is the Unix command UI
Shell是unix的命令接口
* typically handles login session, runs other processes
典型的場合是處理登錄和運行其他進程
* you saw it in 6.033: http://web.mit.edu/6.033/www/assignments/handson-unix.html
你能在6.033上看到:
* the shell is also a programming/scripting language
Shell也是一個可編程或腳本語言
* look at some simple examples of shell operations, how they use different O/S abstractions, and how those abstractions fit together. See [Unix paper](../readings/ritchie78unix.pdf) if you are unfamiliar with the shell.
查看一些shell操作的簡單例子,了解他們如何使用不同的O/S抽象,這些抽象如何一些工作。如果你不熟悉這些shell,請看[Unix文件](https://pdos.csail.mit.edu/6.828/2014/readings/ritchie78unix.pdf)
* [Simplified xv6 sh.c](../homework/sh.c)
簡單的xv6中的shell源文件sh.c
* See [chapter 0 of xv6 book](../xv6/book-rev8.pdf)
讀xv6課本的第0章
* Basic organization: parsing and executing commands (e.g., ls, ls | wc, ls > out)
基本結構:解釋並執行命令(如:ls,ls | wc, ls > out)
* Shell implemented using system calls (e.g., read, write, fork, exec, wait) conventions: -1 return value signals error, error code stored in errno, perror prints out a descriptive error message based on errno.
Shell通過系統調用(如:read,write,fork,exec和wait)來實現功能:返回-1表明出錯,錯誤碼保存在errno中,perror可以打印errno代表的錯誤描述。
* Many systems calls are encapsulated in libc calls (e.g., fgets vs read)
很多系統調用被封裝在libc庫的函數調用中(如:fgets封裝了read)
Demo:
- open sh.c in emacs
- look at main()
- look at runcmd()
- look at fgets()
- man 3 fgets()
* Trace system calls $ls
跟蹤系統調用 ls
* On OSX: sudo dtruss ./a.out (where a.out is the compiled sh.c)
在OSX中:sudo dtruss ./a.out (這里a.out是sh.c編譯后的文件)
* On Linux: strace ./a.out
在Linux中:strace ./a.out
- compile sh.c
編譯sh.c
- run ./a.out
運行./a.out
- strace ./a.out
跟蹤./a.out
* what does fork() do?
Fork()都做了什么?
copies user memory
拷貝用戶內存
copies process kernel state (e.g. user id)
拷貝進程的內核狀態(如:用戶id)
child gets a different PID
子進程獲得一個不同的PID
child state contains parent PID
子進程的狀態信息中包含父進程的PID
returns twice, with different values
以不同的返回值返回兩次
* parent and child may run concurrently (e.g., on different processors).
你進程和子進程可能會同步運行(比如:在不同的處理器上)
* what does wait() do?
Wait()都做了什么?
waits for any child to exit
等待任何子進程退出
what if child exits before parent calls wait?
如果子進程在父進程調用wait之前結束會發生什么?
- strace /bin/sh
- study output:
read()
write()
stat()
etc.
* what are file descriptors? (0, 1, 2, etc. in read/write)
文件描述符是什么?(0、1、2文件描述符,比如在讀寫中)
[echo.c](l-overview/echo.c)
* what is i/o redirection?
什么是i/o重定向?
How would you implement ">" in sh.c
在sh.c中你如何實現“>”?
* what are pipes? (ls | wc )
什么是管道?( ls | wc)
[pipe1.c](l-overview/pipe1.c)
[pipe2.c](l-overview/pipe2.c)
How would you implement them in sh.c?
在sh.c中你是怎么實現它們的?
* Homework assignment for [shell](../homework/xv6-shell.html)
關於shell的課后作業安排(https://pdos.csail.mit.edu/6.828/2014//homework/xv6-shell.html)
Homework: shell
作業:shell
This assignment will make you more familiar with the Unix system call interface and the shell by implementing several features in a small shell, which we will refer to as the 6.828 shell. You can do this assignment on any operating system that supports the Unix API (a Linux Athena machine, your laptop with Linux or MacOS, etc.). Submit your 6.828 shell to the submission web site as a text file with the name "hwN.c", where N is the homework number as listed on the schedule.
這個安排能讓你更熟悉unix的系統調用接口和shell(通過在一個6.828版本中使用的小型shell中實現幾個功能特性)。你可以在任何支持unix API(linux的雅典娜機器、你的裝有linux或MacOS的筆記本等等)的操作系統上完成它。將你的6.828 shell以文本文件格式並且命名為”hwN.c”發送到提交網址,這里N是進度表中的作業序號。
Read Chapter 0 of the xv6 book.
閱讀xv6課本的第0章
If you are not familiar with what a shell does, do the Unix hands-on from 6.033.
如果你不熟悉shell的功能,請查看6.033的Unix手冊。
Download the 6.828 shell, and look it over. The 6.828 shell contains two main parts: parsing shell commands and implementing them. The parser recognizes only simple shell commands such as the following:
下載6.828shell[https://pdos.csail.mit.edu/6.828/2014/homework/sh.c]。它包含兩個主要部分:解析shell命令和實現它們。解析器僅能識別簡單的shell命令,有下面所示:
ls > y
cat < y | sort | uniq | wc > y1
cat y1
rm y1
ls | sort | uniq | wc
rm y
Cut and paste these commands into a file t.sh
剪切並粘貼這些到文件t.sh。
To compile sh.c, you need a C compiler, such as gcc. On Athena, you can type:
為了編譯sh.c,你需要一個C編譯器,比如gcc。在雅典娜機器上,你可以輸入以下命令:
$ add gnu
to make gcc available. If you are using your own computer, you may have to install gcc.
確保gcc可用。如果你使用自己的機器,你可能需要安裝gcc。
Once you have a gcc, you can compile the skeleton shell as follows:
一旦你安裝了gcc,你就可以用如下的命令來編譯這個簡單的shell:
$ gcc sh.c
which produce an a.out file, which you can run:
這會產生一個叫a.out的可執行文件。
$ ./a.out < t.sh
This execution will print error messages because you have not implemented several features. In the rest of this assignment you will implement those features.
由於你沒有實現那幾個功能特性,所以上面的執行會顯示出錯信息。在作業的剩余部分,你將實現那些功能特性。
Executing simple commands
執行簡單命令
Implement simple commands, such as:
實現簡單的命令,例如:
$ ls
The parser already builds an execcmd for you, so the only code you have to write is for the ' ' case in runcmd. You might find it useful to look at the manual page for exec; type "man 3 exec", and read about execv. Print an error message when exec fails.
解析器已經幫你完成了execmd函數,你要做的就是寫runcmd部分中的那空白case。你可以在exec的手冊上找到有用的信息;鍵入”man 3 exec”命令,閱讀關於execv的內容。當exec失敗時要打印一條錯誤信息。
To test your program, compile and run the resulting a.out:
測試你的程序,編譯並運行生成的a.out文件:
6.828$./a.out
This prints a prompt and waits for input. sh.c prints as prompt 6.828$ so that you don't get confused with your computer's shell. Now type to your shell:
這會顯示一個提示符並等待輸入。Sh.c顯示一個6.828$的提示符,這樣你就不會和你機器上的shell混淆。現在為你的shell輸入命令:
6.828$ ls
Your shell should print an error message (unless there is a program named ls in your working directory). Now type to your shell:
你的shell將會顯示一條錯誤信息(除非在你的工作目錄中有一個名叫ls的程序)。現在為你的shell輸入命令:
6.828$ /bin/ls
This should execute the program /bin/ls, which should print out the file names in your working directory. You can stop the 6.828 shell by tying ctrl-d, which should put you back in your computer's shell.
這會執行/bin/ls的程序,它會顯示你工作目錄下的文件名稱。你可以通過按ctrl-d組合鍵來終止6.828 shell的執行,這會返回到你機器中的shell。
You may want to change the 6.828 shell to always try /bin, if the program doesn't exist in the current working directory, so that below you don't have to type "/bin" for each program. If you are ambitious you can implement support for a PATH variable.
如果程序不在你當前的工作目錄,你可能想改變6.828 shell讓它總是試圖在/bin目錄下尋找,而不需要你為每個程序都鍵入”/bin”。
I/O redirection
I/O重定向
Implement I/O redirection commands so that you can run:
實現I/O重定向命令,以便你可象下面這樣使用命令:
echo "6.828 is cool" > x.txt
cat < x.txt
The parser already recognizes ">" and "<", and builds a redircmd for you, so your job is just filling out the missing code in runcmd for those symbols. You might find the man pages for open and close useful。
解析器已經可以辨識”>”和”<”符號,並且替你完成了redircmd函數,所以你的工作僅僅是將runcmd中缺少的已做了符號標識的代碼補全。你可以在關於open和close的手冊部分找到有用的信息。
Make sure you print an error message if one of the system calls you are using fails.
要確保當你使用的一個系統調用失敗后顯示一條錯誤信息。
Make sure your implementation runs correctly with the above test input. A common error is to forget to specify the permission with which the file must be created (i.e., the 3rd argument to open).
使用上面的測試輸入來確保你實現在部分正確運行。一個覺的錯誤是忘記為一個必須創建的文件指定權限(比如,open的第三個參數)。
Implement pipes
實現管道
Implement pipes so that you can run command pipelines such as:
實現管道功能以便你可以象下面的命令一樣使用命令管道:
$ ls | sort | uniq | wc
The parser already recognizes "|", and builds a pipecmd for you, so the only code you must write is for the '|' case in runcmd. You might find the man pages for pipe, fork, close, and dup useful.
解析器已經可以辨識”|”符號,並且替你完成了pipecmd部分,所以你必須編寫runcmd函數中”|”分支部分的代碼。你能在手冊中關於pipe、fork、close和dup部分找到用有信息。
Test that you can run the above pipeline. The sort program may be in the directory /usr/bin/ and in that case you can type the absolute pathname /usr/bin/sort to run sort. (In your computer's shell you can type which sort to find out which directory in the shell's search path has an executable named "sort".)
運行上面的管道命令來測試。Sort程序可能位於/usr/bin/目錄,在這種情況下你可鍵入一個絕對路徑/usr/bin/sort來運行它(在計算機的shell中,你可以鍵入sort,是因為在shell的可執行文件的搜索路徑中可以找到它)。
Now you should be able the following command correctly:
現在可以正確使用下面的命令:
6.828$ a.out < t.sh
Make sure you use the right absolute pathnames for the programs.
確保你為程序使用了正確的路徑名稱。
Don't forget to submit your solution to the submission web site, with or without challenge solutions.
別忘了向提交網站[https://ccutler.scripts.mit.edu/6.828/handin.py/]提交你的解決方案,帶不帶挑戰練習解決方案都可以。
Challenge exercises
挑戰練習
You can add any feature of your choice to your shell. But, you may want consider the following as a start:
你可以向你的shell中添加任何你想要的功能特性。但你可以考慮從下面的開如:
Implement lists of commands, separated by ";"
實現命令列表,它以”;”分隔。
Implement sub shells by implementing "(" and ")"
實現子shell通過”(“和”)”符號支持的實現
Implement running commands in the background by supporting "&" and "wait"
通過支持”&”符號和”wait”命令來支持后台運行命令。
All of these require making changing to the parser and the runcmd function.
所有的這些需求都要修改解析器和runcmd函數。
