為 xv6 系統(tǒng)實現(xiàn) UNIX 的 sleep 程序,。你的 sleep 程序應(yīng)該使當前進程暫停相應(yīng)的時鐘周期數(shù),時鐘周期數(shù)由用戶指定,。例如執(zhí)行 sleep 100 ,,則當前進程暫停,等待 100 個時鐘周期后才繼續(xù)執(zhí)行,。
如果系統(tǒng)沒有安裝 vim 的請先使用命令 sudo apt install vim 安裝 vim 編輯器,。 在開始實現(xiàn)程序前,閱讀配套教材的第一章,,其內(nèi)容與實驗內(nèi)容息息相關(guān),。 實現(xiàn)的程序應(yīng)該命名為 sleep.c 并最后放入 user 目錄下。 可以查看 user 目錄下的其他程序(如echo.c,、grep.c和rm.c),,以它們?yōu)閰⒖?,了解如何獲取和傳遞給程序相應(yīng)的命令行參數(shù)。 如果用戶傳入?yún)?shù)有誤,,即沒有傳入?yún)?shù)或者傳入多個參數(shù),,程序應(yīng)該能打印出錯誤信息。 C 語言中的 atoi 函數(shù)可以將字符串轉(zhuǎn)換為整數(shù)類型,,在 xv6 中也已經(jīng)定義了相同功能的函數(shù),。可以參考 user/ulib.c 或者參考機械工業(yè)出版社的《C程序設(shè)計語言(第2版·新版)》附錄B.5,。 使用系統(tǒng)調(diào)用 sleep ,。 確保 main 函數(shù)調(diào)用 exit() 以退出程序。 將你的 sleep 程序添加到 Makefile 的 UPROGS 中,。只有這步完成后,, make qemu 才能編譯你寫的程序。 完成上述步驟后,,運行 make qemu 編譯運行 xv6 ,,輸入 sleep 10 進行測試,如果 shell 隔了一段時間后才出現(xiàn)命令提示符,,則證明你的結(jié)果是正確的,,可以退出 xv6 運行 ./grade-lab-util sleep 或者 make GRADEFLAGS=sleep grade 進行單元測試。
參考 user 目錄下的其他程序,,先把頭文件引入,,即 kernel/types.h 聲明類型的頭文件和 user/user.h 聲明系統(tǒng)調(diào)用函數(shù)和 ulib.c 中函數(shù)的頭文件。 編寫 main(int argc,char* argv[]) 函數(shù),。其中,,參數(shù) argc 是命令行總參數(shù)的個數(shù),參數(shù) argv[] 是 argc 個參數(shù),,其中第 0 個參數(shù)是程序的全名,,其他的參數(shù)是命令行后面跟的用戶輸入的參數(shù)。 首先,,編寫判斷用戶輸入的參數(shù)是否正確的代碼部分。只要判斷命令行參數(shù)不等于 2 個,,就可以知道用戶輸入的參數(shù)有誤,,就可以打印錯誤信息。但我們要如何讓命令行打印出錯誤信息呢,?我們可以參考 user/echo.c ,,其中可以看到程序使用了 write() 函數(shù)。 write(int fd, char *buf, int n) 函數(shù)是一個系統(tǒng)調(diào)用,,參數(shù) fd 是文件描述符,,0 表示標準輸入,,1 表示標準輸出,2 表示標準錯誤,。參數(shù) buf 是程序中存放寫的數(shù)據(jù)的字符數(shù)組,。參數(shù) n 是要傳輸?shù)淖止?jié)數(shù),調(diào)用 user/ulib.c 的 strlen() 函數(shù)就可以獲取字符串長度字節(jié)數(shù),。通過調(diào)用這個函數(shù),,就能解決輸出錯誤信息的問題啦。認真看了提示給出的所有文件代碼你可能會發(fā)現(xiàn),,像在 user/grep.c 打印信息調(diào)用的是 fprintf() 函數(shù),,當然,在這里使用也沒有問題,,畢竟 fprintf() 函數(shù)最后還是通過系統(tǒng)調(diào)用 write() ,。最后系統(tǒng)調(diào)用 exit(1) 函數(shù)使程序退出。按照慣例,,返回值 0 表示一切正常,,而非 0 則表示異常。 接下來獲取命令行給出的時鐘周期,,由于命令行接收的是字符串類型,,所以先使用 atoi() 函數(shù)把字符串型參數(shù)轉(zhuǎn)換為整型。 調(diào)用系統(tǒng)調(diào)用 sleep 函數(shù),,傳入整型參數(shù),,使計算機程序(進程、任務(wù)或線程)進入休眠,。 最后調(diào)用系統(tǒng)調(diào)用 exit(0) 使程序正常退出,。 在 Makefile 文件中添加配置,照貓畫虎,,在 UPROGS 項中最后一行添加 $U/_sleep\ ,,最后這項配置如下。
UPROGS=\ $U/_cat\ $U/_echo\ $U/_forktest\ $U/_grep\ $U/_init\ $U/_kill\ $U/_ln\ $U/_ls\ $U/_mkdir\ $U/_rm\ $U/_sh\ $U/_stressfs\ $U/_usertests\ $U/_grind\ $U/_wc\ $U/_zombie\ $U/_sleep\
// Lab Xv6 and Unix utilities // sleep.c // 引入聲明類型的頭文件 #include "kernel/types.h" // 引入聲明系統(tǒng)調(diào)用和 user/ulib.c 中其他函數(shù)的頭文件 #include "user/user.h" // int main(int argc,char* argv[]) // argc 是命令行總的參數(shù)個數(shù) // argv[] 是 argc 個參數(shù),,其中第 0 個參數(shù)是程序的全名,,以后的參數(shù)是命令行后面跟的用戶輸入的參數(shù) int main(int argc, char *argv[]) { // 如果命令行參數(shù)不等于2個,則打印錯誤信息 if (argc != 2) { // 系統(tǒng)調(diào)用 write(int fd, char *buf, int n) 函數(shù)輸出錯誤信息 // 參數(shù) fd 是文件描述符,,0 表示標準輸入,,1 表示標準輸出,2 表示標準錯誤 // 參數(shù) buf 是程序中存放寫的數(shù)據(jù)的字符數(shù)組 // 參數(shù) n 是要傳輸?shù)淖止?jié)數(shù) // 所以這里調(diào)用 user/ulib.c 的 strlen() 函數(shù)獲取字符串長度字節(jié)數(shù) write(2, "Usage: sleep time\n", strlen("Usage: sleep time\n")); // 當然這里也可以使用 user/printf.c 中的 fprintf(int fd, const char *fmt, ...) 函數(shù)進行格式化輸出 // fprintf(2, "Usage: sleep time\n"); // 退出程序 exit(1); } // 把字符串型參數(shù)轉(zhuǎn)換為整型 int time = atoi(argv[1]); // 調(diào)用系統(tǒng)調(diào)用 sleep 函數(shù),,傳入整型參數(shù) sleep(time); // 正常退出程序 exit(0); }
在 xv6 中輸入命令后一切符合預(yù)期,。 $ sleep 10 $ sleep 1 1 Usage: sleep time $ sleep Usage: sleep time
退出 xv6 運行單元測試。 提示:如果運行測試報錯,,先使用命令 vim grade-lab-util 修改 grade-lab-util 文件,,把第一行改為 #!/usr/bin/env python3 ,,即最后加個數(shù)字3。 通過測試樣例,。 make: 'kernel/kernel' is up to date. == Test sleep, no arguments == sleep, no arguments: OK (0.9s) == Test sleep, returns == sleep, returns: OK (1.4s) == Test sleep, makes syscall == sleep, makes syscall: OK (0.9s)
|