MIT6.828_2019_Lab翻譯_utilities

實驗:Xv6和Unix程序

歡迎大家一起維護中文Lab文檔!共同進步! Github

這個實驗將會讓你熟悉Xv6和它的系統調用

引導Xv6

你必須使用一個X86 Athena machine;也就是說 uname -a 之後應該顯示 i386 GNU/Linux or i686 GNU/Linux or x86_64 GNU/Linux。你可以登陸進一個公共的Athena host,通過使用指令ssh -X athena.dialup.mit.edu

我們已經爲你在Athena machine上建立了相應的編譯器和模擬器。你可以通過運行 add -f 6.828 來使用它們。每次登錄你都必須運行此命令(或者將它添加到環境變量)。如果你在編譯或運行qemu時得到模糊的錯誤,請首先檢查是否將課程資源添加到了環境變量

獲取本Xv6 lab的資源,並檢查util分支:

$ git clone git://github.com/mit-pdos/xv6-riscv-fall19.git  
Cloning into 'xv6-riscv'...  
...  
$ cd xv6-riscv-fall19  
$ git checkout util  

爲了使lab更加簡單,xv6-riscv-fall19代碼倉庫和書中的xv6-riscv只有輕微的不同

在本實驗中你使用的文件是分佈式的,通過使用Git版本控制系統。你要爲你的答案創建一個新的分支(git branch util)。你可以通過Git用戶手冊來學習更多關於Git的知識。CS-oriented overview of Git或許也是有用的。Git允許您跟蹤您對代碼的更改。舉個例子,如果你完成了一個練習,和想提交你的變更,你可以通過運行以下內容提交你的修改:

$ git commit -am 'my solution for util lab exercise 1'  
Created commit 60d2135: my solution for util lab exercise 1  
 1 files changed, 1 insertions(+), 0 deletions(-)  
$  

你可以使用git diff命令跟蹤你的更改。運行git diff將顯示你從上次提交過後更改的代碼,“git diff origin/xv6-riscv-fall19”將會顯示自初始版本以來改變過的代碼。origin/xv6-riscv-fall19就是你下載課程初始代碼的分支的名字。

在Athena上build Xv6:

$ make  
riscv64-linux-gnu-gcc    -c -o kernel/entry.o kernel/entry.S  
riscv64-linux-gnu-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie   -c -o kernel/start.o kernel/start.c  
...  
$ make qemu  
...  
mkfs/mkfs fs.img README user/_cat user/_echo user/_forktest user/_grep user/_init user/_kill user/_ln user/_ls user/_mkdir user/_rm user/_sh user/_stressfs user/_usertests user/_wc user/_zombie user/_cow  
nmeta 46 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 1) blocks 954 total 1000  
balloc: first 497 blocks have been allocated  
balloc: write bitmap block at sector 45  
qemu-system-riscv64 -machine virt -kernel kernel/kernel -m 3G -smp 3 -nographic -drive   file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0  
hart 0 starting  
hart 2 starting  
hart 1 starting  
init: starting sh  
$  

如果你在命令行輸入ls,應該會看到類似於下面的輸出:

$ ls  
.              1 1 1024  
..             1 1 1024  
README         2 2 2181  
cat            2 3 21024  
echo           2 4 19776  
forktest       2 5 11456  
grep           2 6 24512  
init           2 7 20656  
kill           2 8 19856  
ln             2 9 19832  
ls             2 10 23280  
mkdir          2 11 19952  
rm             2 12 19936  
sh             2 13 38632  
stressfs       2 14 20912  
usertests      2 15 106264  
wc             2 16 22160  
zombie         2 17 19376  
cow            2 18 27152  
console        3 19 0  

這些就是在初始mkfs文件系統中包含的程序文件。你只是運行了其中一個:ls

如果你是在非Athena機器上工作,你需要根據Tools page安裝qume和gcc for RISC-V。

提交程序

你將使用提交網站來提交你的作業。在你提交作業或實驗前,你需要從網站上申請一個API key。實驗代碼採用GNU Make規則來簡化提交。在你最後的更改提交後,輸入 make handin 提交你的實驗。

$ git commit -am "ready to submit my lab"  
[util c2e3c8b] ready to submit my lab  
2 files changed, 18 insertions(+), 2 deletions(-)  

$ make handin  
git archive --prefix=util/ --format=tar HEAD | gzip >     util-handin.tar.gz  
Get an API key for yourself by visiting https://6828.scripts.mit.edu/    2018/handin.py/  
Please enter your API key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  
  % Total    % Received % Xferd  Average Speed   Time    Time         Time  Current  
                             Dload  Upload   Total   Spent        Left  Speed  
100 50199  100   241  100 49958    414  85824 --:--:-- --:--:--           --:--:-- 85986  
$  

make handin 將會把API key存在 myapi.key中。如果你需要改變API key,刪除這個文件,然後執行 make handin 再生成一個就可以了(myapi.key不能有換行符)

如果你在 make handin 時有未提交的改變或者有無法追蹤的文件,你將會看到類似下面的輸出:

M hello.c  
?? bar.c  
?? foo.pyc  
Untracked files will not be handed in.  Continue? [y/N]  

檢查上面的,確保你的答案中需要的文件不在上面以??開頭的行中,你可以使用git add filename來使Git能追蹤到你的文件。

如果make handin不能正常工作,你可以使用make tarball來生成tar文件,然後在web上提交

你可以使用make grade來運行評分程序。TAs將使用與你本地相同的評分程序來評分。

Sleep

爲Xv6實現Unix Sleep調用;你的Sleep應該能夠暫停一段用戶指定的ticks時長(tick是內核中定義的一個概念,代表兩次時鐘中斷之間的時間長度)。你的答案應該實現在user/sleep.c

一些提示:

  • 你可以通過查看/user下的其他程序來學習如何將命令行參數傳入程序。如果用戶忘記傳入參數,sleep程序應該打印error信息
  • 命令行參數作爲字符串傳遞;你可以使用atoi將它轉換成一個整數(見user/ ulib.c)
  • 使用系統調用 sleep (見user/usys.S 與 kernel/sysproc.c)
  • 確保 main 調用 exit() 來退出程序
  • 在makefile中將程序添加到UPROGS並通過 make fs.img 來編譯程序
  • 閱讀Kernighan and Ritchie’s book The C programming language (second edition) (K&R) 來學習C語言

從Xv6 shell運行程序:

  $ make qemu  
  ...  
  init: starting sh  
  $ sleep 10  
  (nothing happens for a little while)  
  $  

如果您的程序行爲如上所示,那麼你的答案是正確的

可選:編寫一個 uptime 的調用程序,打印出uptime的值(tips:uptime是一個系統調用) 。

pingpong

編寫一個程序,該程序使用UNIX系統調用通過一對管道在兩個進程之間``乒乓’'一個字節,每個方向一個。父進程通過向byte_fd [1]寫入字節來發送,而子進程通過從parent_fd [0]讀取來接收字節。子進程從父進程收到一個字節後,通過寫入child_fd [1] 響應,然後由父級讀取。您的解決方案應該在文件user / pingpong.c中。

一些提示:

  • 使用 pipe 創建管道
  • 使用 fork 創建一個子進程
  • 使用 read 讀取管道,並使用 write 寫入管道

從xv6 shell運行該程序,它將產生以下輸出:

$ make qemu  
...  
init: starting sh  
$ pingpong  
4: received ping  
3: received pong  

如果您的程序行爲如上所述,則您的解決方案是正確的。“:”之前的數字是打印輸出的進程的進程ID。您可以通過調用系統調用getpid來獲取進程ID

primes

利用管道編寫一個併發版本的篩素數程序,這個想法來自Unix pipe管道的創始人.web此頁中解釋瞭如何去操作.你的答案應該寫在user/primes.c

你的目標是使用 pipe 和 fork 去創建一個管道。 第一個進程將[2,35]輸入進管道。對於每一個質數,您將安排創建一個進程從其左鄰居讀取在管道並寫入其右鄰居管道。因爲xv6的文件描述符和進程數量是有限制的,所以第一個進程應該在寫入35之後停止寫入。

一些提示:

  • 小心的關閉進程不需要的文件描述符,否則你的程序可能在第一個進程到達35之前耗盡xv6的資源
  • 一旦第一個進程到達35,您就應該安排管道乾淨利落地終止,包括所有子進程(提示:關閉管道的寫端時 read 將返回 EOF)。
  • 直接往管道里寫入32位 intS 而不是格式化的 ACSII I/O 是最簡單的。
  • 你應該根據需求在管道里創建進程

如果你的輸入如下所示,那麼你的答案就是正確的:

$ make qemu  
...  
init: starting sh  
$ primes  
prime 2  
prime 3  
prime 5  
prime 7  
prime 11  
prime 13  
prime 17  
prime 19  
prime 23  
prime 29  
prime 31  
$  

find

編寫UNIX查找程序的簡單版本:在目錄樹中查找名稱與參數字符串匹配的所有文件。 您的解決方案應該在文件user / find.c中。

一些提示:

  • 查看user / ls.c以瞭解如何讀取目錄
  • 使用遞歸來進入子目錄
  • 不要遞歸到“.” 和“…”
  • 對文件系統的更改在qemu的運行中持續存在。 要獲得乾淨的文件系統,請先運行 make clean,然後再make qemu
  • 你需要使用C風格字符串。 查看K&R(C book),例如5.5節

可選:支持使用正則表達式進行名稱匹配。 grep.c 對正則表達式有一些原始支持。

如果產生以下輸出(文件系統包含文件 a/b 時),則您的解決方案是正確的:

$ make qemu  
...  
init: starting sh  
$ mkdir a  
$ echo > a/b  
$ find . b  
./a/b  
$  

xargs

編寫UNIX xargs程序的簡單版本:從標準輸入中讀取每行併爲每行運行一個命令,並將該行的結果作爲參數提供給其他命令。 您的解決方案應該在文件user / xargs.c中。

下面的例子說明了xarg的行爲:

$ xargs echo bye  
hello too  
bye hello too  
ctrl-d  
$  

一些提示:

使用fork和exec系統調用在輸入的每一行上調用命令。 在父級中使用wait等待子級完成命令的運行。
從標準輸入中讀取一個字符,直到換行符(’\n’)。
kernel/param.h 中聲明瞭 MAXARG ,如果您需要聲明 argv ,這可能很有用。
對文件系統的更改在qemu的運行中持續存在。 要獲得乾淨的文件系統,請先運行make clean,然後再進行qemu。

xargs, find, 和 grep 的結合:

$ find . b | xargs grep hello  

以上命令將會在每個擁有文件名爲 b 的文件夾下運行 grep hello

運行 xargstest.sh 腳本來測試你的答案.如果你的答案像接下來輸出的一樣,那麼你的答案就是正確的:

$ make qemu  
...  
init: starting sh  
$ sh < xargstest.sh  
$ $ $ $ $ $ hello  
hello  
hello  
$ $  

您可能需要修復 find 程序中的錯誤。 輸出中有很多 $ ,因爲xv6 shell是很原始的,並且它不會意識到正在處理文件中的命令而不是控制檯中的命令,它會爲文件中的每個命令打印 $

本實驗到此完成。 在實驗室目錄中,使用 git commit 提交更改,然後鍵入 make handin 提交代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章