




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、實(shí)驗(yàn)一實(shí)現(xiàn)帶參數(shù)的簡單shell實(shí)驗(yàn)一利用課本第9頁程序1-5的框架,實(shí)現(xiàn)允許輸入命令帶參數(shù)的簡單shello 原來的實(shí)現(xiàn)是不能夠帶參數(shù)的。輸入命令所能帶的參數(shù)個數(shù),只受到系統(tǒng)鍵盤輸 入緩沖區(qū)長度(以及shell輸入緩沖區(qū)長度)的限制,該緩沖區(qū)的缺省長度是4096 個字節(jié)。實(shí)現(xiàn)時要解決的主要問題有:1. 正確理解并使用系統(tǒng)調(diào)用fork(), execve()和waitpid(),特別是execve()函數(shù)。 fork()函數(shù)創(chuàng)建一個新的進(jìn)程。新進(jìn)程就是所謂的子進(jìn)程,它是執(zhí)行fork()函數(shù)的 進(jìn)程(父進(jìn)程)的“克隆”,也就是說,子進(jìn)程執(zhí)行的程序與父進(jìn)程的完全一-樣。 當(dāng)fork()函數(shù)返回值為
2、0時表示處于子進(jìn)程中;而返回值大于0時表示處于父進(jìn) 程中,此時的返回值是了進(jìn)程的進(jìn)程ido因此,fork()的返回值可以用來劃分僅 僅適合父進(jìn)程和子進(jìn)程執(zhí)行的程序段。fork()函數(shù)返回值為1時表示岀錯。如果子進(jìn)程只是運(yùn)行與父進(jìn)程完全-樣的程序,那用處是很有限的。要讓子進(jìn)程 運(yùn)行不同于父進(jìn)程的程序,就必須調(diào)用execve函數(shù),它是所冇其他exec函數(shù)的 基礎(chǔ)。execve函數(shù)把調(diào)用它的進(jìn)程的程序,替換成execve函數(shù)的參數(shù)所指定的 程序。運(yùn)行execve函數(shù)成功后,進(jìn)程將開始運(yùn)行新的程序,也就是execve函數(shù) 的參數(shù)所指定的程序。execve 函數(shù)原型:int execve(const c
3、har * path, const char *argvf,const char * envpf); 其中:path:要執(zhí)行的程序路徑名,比如“/bin/ls”,“cd”,“/usr/bin/gcc”等等。argv:參數(shù)表,比如is命令屮可帶的命令行參數(shù)等。注意,argv的第一個元 素必須是要執(zhí)行的程序(命令)的路徑名。envp:環(huán)境變量表,供要執(zhí)彳亍的命令使用。實(shí)參數(shù)用null或系統(tǒng)環(huán)境變量environ 均口j。注意,因?yàn)閑nviron由系統(tǒng)提供,屬于外部變量,所以說明時必須用“extern” 修飾。例子:char *argv = “gcc", “g", “hello.
4、c", null;char *argvl = “/bin/ls",null;execve(t7usr/bin/gcc, argv, environ); / 編譯程序"hello.c” execve(4t/bin/ls, argvl, null); / 執(zhí)行命令 “is 1 a” execvec7usr/ls”, argvl, null); 出錯,因?yàn)槟夸?usr/下沒有 is 程序。注意,在argvl的第一個字符串“/bin/ls”中,只有is是有用的。系統(tǒng)調(diào)用waitpid()用于等待子進(jìn)程結(jié)束、獲取子進(jìn)程的運(yùn)行狀態(tài),詳細(xì)說明在第 八章。木實(shí)驗(yàn)僅僅用它使父進(jìn)程等
5、待了進(jìn)程結(jié)束,因此維持程序1-5的用法即可。2. 根據(jù)簡單shell的輸入,構(gòu)造execve函數(shù)的參數(shù)。根據(jù)程序15,數(shù)組buf保存用戶的輸入,包括命令和參數(shù)。由于shell命令的命 令名和各參數(shù)之間是用空格分開,因此可以用空格作為分界符。通過一個循環(huán)可 以把buf數(shù)組中的命令和各個參數(shù)依次分離開來,并賦給數(shù)組argv的各元素適當(dāng) 的指針值。argv數(shù)組的最后個指針必須是null。接著就可以調(diào)用 execve(argv0,argv, environ)來執(zhí)行用廣1輸入的命令。捉示:argv數(shù)組中各指針?biāo)赶虻淖址?,可以直接利用buf的存儲空間,不需 要另外分配內(nèi)存。3. 正確編譯程序。曲于書中
6、例子用到了本書第一版中作者自己定義的error.c文件,因此編譯吋要記 得把error.c文件和源代碼文件一起編譯,error.c文件可以到cs8的 /home/luwei/common目錄下復(fù)制??梢杂萌绮访罹幾g:gcc v源文件名error.c - ov可執(zhí)行文件名實(shí)驗(yàn)二 同步與異步write的效率比較1、程序的參數(shù)和輸入實(shí)驗(yàn)要求程序必須指定輸出的文件名,而該文件是否按同步方式打開,則是可以 選擇的。因此程序至少帶一個、至多兩個輸入?yún)?shù)。程序默認(rèn)從標(biāo)準(zhǔn)輸入 stdin_filen0讀取輸入文件,可以利用shell的輸入定向功能選擇具體的輸入 文件。2、系統(tǒng)調(diào)用times()的說明#inc
7、lude <sys/times.h>clock_t times(struct tms *buf);struct tms clock_t tms_utime; /*記錄進(jìn)程除系統(tǒng)調(diào)用外所使用的cpu時間*/ clock_t tms_stime; /*記錄進(jìn)程的系統(tǒng)調(diào)用所使用的cpu時間*/ clock_t tms_cutime; /*記錄子進(jìn)程除系統(tǒng)調(diào)用外所使用的cpu時間*/ clock_t tms_cstime; /*記錄子進(jìn)程的系統(tǒng)調(diào)用所使用的cpu時間*/ ; times函數(shù)的返回值是進(jìn)程迄今為止的存活時間。所冇時間都是以“滴答”為單 位的,函數(shù)sysconf(_sc_clk
8、_tck)可獲得所運(yùn)行系統(tǒng)每秒的滴答數(shù)(參考課木 p33)。3、計算write耗費(fèi)的吋間為了準(zhǔn)確計算write耗費(fèi)的時間,很重要的就是要避免將read的時間計入,因?yàn)?i/o操作的時間通常是毫秒級的,不可以忽略。一種有效的方法是,設(shè)置一個與 輸入文件長度相同的緩沖區(qū),一次性地將輸入文件讀入緩沖區(qū),而后就不必再讀 輸入文件。這樣就可以有效避免計入read的時間。有同學(xué)可能會問,難道可以在內(nèi)存中創(chuàng)建一個幾十上百兆乃至上g的緩沖區(qū)嗎? 回答是沒問題!因?yàn)槲覀兯\(yùn)行的操作系統(tǒng)系統(tǒng)具有虛擬存儲管理功能。設(shè)置輸入緩沖區(qū)時需要知道輸入文件的長度。除了使用系統(tǒng)調(diào)用suit外,更簡單 的方法是利用lseek的返
9、冋值來獲取文件的長度。在按每一個給定大小的輸出緩沖區(qū)計算寫文件時間時,應(yīng)當(dāng)在開始寫之前調(diào)用 times。,記錄下開始吋間,然后在整個輸入緩沖區(qū)都復(fù)制到輸出文件之后,再調(diào) 用times(),兩次調(diào)用times()的時間間隔,就是在這個給定大小的輸出緩沖區(qū)的 限制卜,復(fù)制整個輸入文件所耗費(fèi)的寫時間。至于在每一次寫的時候所執(zhí)行的其 他語句,它們相較于i/o操作,所花費(fèi)的時間極小,可以忽略不計。注意,在開始按一個給定大小的輸出緩沖區(qū)復(fù)制輸入文件吋,應(yīng)當(dāng)先將輸出文件 的寫位置復(fù)位到輸出文件的開頭(這意味著不能以o-append方式打開輸出文 件)??梢允褂胠seek做到這一點(diǎn),以避免多次打開、關(guān)閉輸出文
10、件。實(shí)驗(yàn)三目錄樹的遍歷實(shí)驗(yàn)三主要以課本99-102頁程序47為框架,在此基礎(chǔ)上進(jìn)行擴(kuò)展。需要 注意的問題主要有:1. 正確理解程序47。程序47遞歸降序遍歷口錄層次結(jié)構(gòu),并按照文件類型進(jìn) 行計數(shù)。主要涉及到三個函數(shù),ftw4(), dopath()和myfunc()o ftw4()函數(shù)以所 帶參數(shù)pathname為要遍歷的起始目錄,計算出該目錄下各種不同類型的文件 的個數(shù)和所占百分比,并顯示出來。它調(diào)用了另外兩個函數(shù),一個是dopath() 函數(shù),這是一個遞歸函數(shù),對指定的起始目錄下的毎個目錄項(xiàng),按深度優(yōu)先 進(jìn)行遍歷;而對所訪問的節(jié)點(diǎn),則調(diào)用myfunc()進(jìn)行處理。main函數(shù)輸擊統(tǒng) 計結(jié)果
11、。三個函數(shù)的參數(shù)含義如下:(1) myftw(char* pathname, myfunc* func); pathname給出指要遍丿力開始的目錄。func是myfunc類型的函數(shù)指針,定義訪問的實(shí)際操作。(2) dopath(myfunc* func);參考第一個函數(shù)(3) int myfunc(const char * pathname,const struct stat *statptr,int type); pathname指向當(dāng)前訪問節(jié)點(diǎn)的路徑名。statptr指向當(dāng)前訪問節(jié)點(diǎn)的i節(jié)點(diǎn)的結(jié)構(gòu),該結(jié)構(gòu)保存有許多該文件的 信息。type給出當(dāng)前訪問節(jié)點(diǎn)的類型,在實(shí)驗(yàn)中可以自己定義它的涵
12、義。 myfunc()的返回值通常是0,實(shí)際上在程序4-7中它的值總是0。但是在 dopath()函數(shù)屮,myfimc()的返回值非0意味著終止遍歷。另外,程序47中用到課本23中的函數(shù)path_alloc(),用于分配存放路徑名 的內(nèi)存空間。2. 實(shí)驗(yàn)三要求根據(jù)用戶輸入的命令行選項(xiàng)的不同,來實(shí)現(xiàn)三種功能:(1) argc為2時,命令格式為myfind <pathname>它除了實(shí)現(xiàn)程序47功能外,還要統(tǒng)計出,在常規(guī)文件屮,文件長度不大于4096字節(jié)的常規(guī)文件,在所冇允許訪問的普通文件屮所占的百 分比。程序也不允許打印出任何路徑名。這個功能實(shí)現(xiàn)比較簡單,只要 略加修改myfunc(
13、)和main()這兩個函數(shù)就可以了。(2) argc為4且argv2= “comp"時,命令格式為myfind <pathname> comp <filename>它的功能是,輸出在<pathname>目錄子樹之下,所有與vfilename文件 內(nèi)容一致的文件的絕對路徑名。不允許輸出任何其它的路徑名,包括不 可訪問的路徑名。為提高程序效率,在比較文件是否相同時,可先比較 兩個文件的大小,如果大小不同,則內(nèi)容肯定不同,這樣就免去了讀文 件所浪費(fèi)的時間;如果大小相同,則再通過讀文件進(jìn)行比較。此時應(yīng)當(dāng) 注意輸入緩沖區(qū)不必開的太大,你可以從實(shí)驗(yàn)二得到啟發(fā)。
14、由于要求輸 出符合要求的文件的絕對路徑名,因此當(dāng)參數(shù)pathname不是絕對路徑 時,要調(diào)用getcwd()等函數(shù)來取得文件的絕對路徑名。(3) argc大于等于4且argv2 = 6<-name,?時,命令格式為myfind <pathname> -name <str>.vsu>是一個以空格分隔的文件名序列(不帶目錄)。命令輸出在 <pathname> 口錄子樹之下,所有與vstr>序列屮文件名相同的文件的絕 對路徑名。不允許輸出不可訪問的或無關(guān)的路徑名。實(shí)現(xiàn)方法可以通過 循環(huán),把當(dāng)前遍歷的文件名和vsti>這個序列中的文件名進(jìn)行比
15、較,如杲 和序列屮的一個文件名相同,就符合條件,此時輸岀符合條件的文件的 絕對路徑名。3. 在實(shí)現(xiàn)上述三種功能吋,主要是通過實(shí)現(xiàn)三個不同的myfunco來完成的。第 一個功能只須對myfunc()略加修改即口j。而第二個和第三個功能,則需要分別定 義另外兩個函數(shù),不妨分別稱做myfunc2()和myfunc3(),去完成指定的功能。至 于dopath()函數(shù)則基本不必修改,因?yàn)樗皇前瓷疃葍?yōu)先完成對目錄樹的遍丿力, 這是一種“標(biāo)準(zhǔn)”操作。而遍歷時對節(jié)點(diǎn)(即文件或目錄)的操作(所謂的“訪 問”)則是由具體參數(shù)func()決定的。不過,如果你覺得程序輸出的絕對路徑名 因?yàn)楹小啊倍粔蛎烙^,則也可
16、以對dopath()函數(shù)略做修改來糾正這個缺欠。實(shí)驗(yàn)四模擬“五個哲學(xué)家”問題該實(shí)驗(yàn)的要點(diǎn)是,解決并發(fā)環(huán)境下,多進(jìn)程z間的同步與互斥問題。進(jìn)程 間的同步互斥必然涉及進(jìn)程間的通信(信息交換)。但是進(jìn)程的內(nèi)存空間是彼此 隔離的,因此它們之間的通信只能通過如下手段:ipc機(jī)制、管道、信號或文件。 就目前所學(xué)知識和實(shí)驗(yàn)要求而言,使用文件是可行的,有關(guān)方法見目錄"common" 下的文件“ lock.h” 和 “l(fā)ock.c”。由于程序要生成多個進(jìn)程,因此述要對作業(yè)控制的機(jī)制冇所了解,這部分 內(nèi)容請參考第九章。如在課堂上所說的,如果哲學(xué)家中同時存在左撇子和右撇子,則哲學(xué)家問 題有解。模
17、擬程序的框架如下所示,其中,函數(shù)lock()和unlock()的定義見前面 所說的文件。定義5個文件,分別表示5個叉子。其文件名可以按如下方式說明: static char* forks5 = “forko“,“forkl“, ufork2u, “fork3“, “fork4“;哲學(xué)家的行為可以用如下函數(shù)描述:void philosopher(int i)while(l) thinking(i, nsecs); takefork (i); eating(i, nsecs); putfork(i);/哲學(xué)家i思考nsecs秒/哲學(xué)家i拿起叉子/哲學(xué)家i進(jìn)餐nsecs秒/哲學(xué)家i放下叉子在主程序里
18、,可以用下面的程序段生成5個哲學(xué)家進(jìn)程:#define n 5for(i = 0; i < n; i+) pid = fork(); if( pid = 0 ) philosopher(i); wait(null); /*注意,如果父進(jìn)程不等待子進(jìn)程的結(jié)束,那么需要終止程序 運(yùn)行時,就只能從控制臺刪除在后臺運(yùn)行的哲學(xué)家進(jìn)程*/拿起叉子可以如此定義: void takefork(i)if( i = n 1 ) lock( forks0); lock( forksi);else lock( forki); lock( forkfi + 1);放下叉子可以如此定義: void putfork(
19、i)if( i = n 1 ) unlock( forksfo); unlock( forksi);else unlock( forki); unlock( forkfi + 1);實(shí)驗(yàn)五信號處理本實(shí)驗(yàn)要求利用可靠信號機(jī)制解決信號處理時可能出現(xiàn)的時間窗口,以及非 局部轉(zhuǎn)移等問題,將學(xué)習(xí)使用 sigaction, alarm, sigpending, sigsetjmp 和 siglongjmp 等函數(shù)解決在處理信號時遇到的問題。一個方便的開始:在程序清單1-8的基礎(chǔ)上進(jìn)行修改??梢灾苯永孟到y(tǒng)shell(在cs8是bash): execl('7bin/sh", “sh&quo
20、t;, buf, (char *) 0);這樣程序sigtest就具有系統(tǒng)shell的全部功能。如果命令帶選項(xiàng),則在創(chuàng)建 執(zhí)行上面函數(shù)的子進(jìn)程之前,必須設(shè)置鬧鐘;在子進(jìn)程結(jié)束之后,必須將鬧鐘清 零。需要處理的信號:因?yàn)樾枰褂敏[釗a所以實(shí)驗(yàn)需要處理兩個信號:sigalrm和sigquit。 如果當(dāng)前程序正在執(zhí)行用戶命令,則信號處理函數(shù)必須“殺死”用戶命令進(jìn)程: kill(pid, sigkill); / pid 為用戶命令進(jìn)程的 id對于信號sigquit述冇一種可能:正在接收用戶輸入的命令串。此時需要 放弄當(dāng)前輸入,重新開始接收輸入。解決方法可能需要使用非局部轉(zhuǎn)移機(jī)制。信號sigalrm和s
21、1gqu1t之間嵌套關(guān)系的處理如果這兩個信號同時發(fā)生,或者在處理信號sigalrm時產(chǎn)生信號sigquit (或者反過來),那么應(yīng)當(dāng)如何處理?無論如何,如果同時存在多個未決信號, 系統(tǒng)總是一個信號處理完了,再處理下一個信號,但是在處理完全部未決信號之 前,不會返回被屮斷的函數(shù)或系統(tǒng)調(diào)用。因此合理的處理方法是,無論上述兩個信號哪個先處理,另一個未決信號就 應(yīng)該忽略(清除未決信號);在處理其中一個信號時,屏蔽另_個信號(如果發(fā) 生,就是未決信號)。static volatile pid_t pid; 全局變量,存放執(zhí)行用戶命令的子進(jìn)程的id,/非0表正在執(zhí)行用戶命令設(shè)置信號sigalrm處理方式的
22、代碼(供參考):struct sigaction act, oact;act.sa_handler = func; / 信號 sigalrm 的處理函數(shù)sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, sigquit); 在處理信號 sigalrm 時,屏蔽信號/ sigquitact.sa_flags = 0;#ifdef sa_restart /如果定義了該常量,則系統(tǒng)默認(rèn)不重啟,應(yīng)改為重啟 act.sa_flags 1= sa_restart;#endifsigaction(sigalrm, &act, &
23、oact);信號sigquit處理函數(shù)的末尾應(yīng)該包含如下代碼段(供參考):sigset_t pendmask;sigemptyset(&pendmask);sigpending(&pendmask); /獲得未決信號集合pid = 0;/表示當(dāng)前無正在執(zhí)行的用戶命令alarm(o); /清除鬧鐘if(sigmember(&pendmask, sigalrm) / 存在未決信號 sigalrm signal(sigalrm, sig_ign);/ 清除未決信號 sigalrmsigaction(sigalrm, &act, null); / 恢復(fù)原來的處理方法實(shí)驗(yàn)
24、六用線程解決“n個哲學(xué)家”問題在這個實(shí)驗(yàn)里,待解決的就是如何使用線程描述的問題。由于同一個進(jìn)程屮 的所有線程共享相同的內(nèi)存空間,因此口j以使用全局變量表示叉子。但是,為了 避免“時間窗口”,仍然必須使用“原了”操作進(jìn)行互斥??梢允褂迷趕emaphore.h 里說明的信號量完成這個需求,具體細(xì)節(jié)參考課件和聯(lián)機(jī)文檔。模擬程序的框架 如下:定義一個全局的信號量指針,表示叉子。可以按如下方式說明: static sem_t *forks;哲學(xué)家的行為可以用如下函數(shù)描述:void * philosopher(void *n) int i = (int) n;while(l) thinking(i, nsecs); / 哲學(xué)家 i 思考 nsecs 秒takefork(i);/哲學(xué)家i拿起叉子eating(i, nsecs); / 哲學(xué)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國PVC電子包裝盒數(shù)據(jù)監(jiān)測研究報告
- 2025年中國稀土鋼絞線市場調(diào)查研究報告
- 2025年中國泌尿外科診療床市場調(diào)查研究報告
- 2025年中國商場設(shè)施市場調(diào)查研究報告
- 8彩色的夢(教學(xué)設(shè)計)-2023-2024學(xué)年語文二年級下冊統(tǒng)編版
- 繪制圖形(教學(xué)設(shè)計)2024-2025學(xué)年五年級上冊信息技術(shù)電子工業(yè)版
- 2025年高可靠性感應(yīng)式電度表項(xiàng)目建議書
- 2024-2025學(xué)年新教材高中數(shù)學(xué)課時分層作業(yè)3集合的基本關(guān)系含解析新人教B版必修第一冊
- 2024-2025學(xué)年高中數(shù)學(xué)課下能力提升十五隨機(jī)事件的概率新人教A版必修3
- 2024-2025學(xué)年高中物理課時分層作業(yè)13電能的生產(chǎn)與利用電和磁的完美統(tǒng)一含解析魯科版選修1-1
- 關(guān)于與旅游發(fā)展集團(tuán)成立合資公司的可行性研究報告
- 第一部分-氣排球運(yùn)動介紹課件
- 世界局勢與主再來課件
- 思維游戲(小孩都喜歡玩的游戲)教學(xué)內(nèi)容課件
- 儲能技術(shù)課后參考答案梅生偉
- 蘇教版科學(xué)2023四年級下冊全冊教案教學(xué)設(shè)計及反思
- 過渡金屬氧化物催化劑及其催化作用
- 溫濕度對果蔬儲存的影響
- 遺傳性耳聾基因檢測標(biāo)準(zhǔn)Ppt
- 電是怎么產(chǎn)生的
- 八-十-天-環(huán)-游-地-球(讀書)專題培訓(xùn)課件
評論
0/150
提交評論