實驗六進程控制_第1頁
實驗六進程控制_第2頁
實驗六進程控制_第3頁
實驗六進程控制_第4頁
實驗六進程控制_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、實驗六、進程控制一、實驗?zāi)康?1.實踐并發(fā)進程的創(chuàng)建和控制方法。觀察和體驗進程的動態(tài)特性。2.進一步理解進程生命期期間創(chuàng)建、變換、撤銷狀態(tài)變換的過程。3.練習(xí) Linux 系統(tǒng)中進程創(chuàng)建與控制有關(guān)的系統(tǒng)調(diào)用的編程和調(diào)試技術(shù)。 二、 實驗說明 1)與進程創(chuàng)建、執(zhí)行有關(guān)的系統(tǒng)調(diào)用說明 進程可以通過系統(tǒng)調(diào)用fork()創(chuàng)建子進程并和其子進程并發(fā)執(zhí)行.子進程初始的執(zhí)行映像是父進程的一個副本.子進程可以通過 exec()系統(tǒng)調(diào)用族裝入一個新的執(zhí)行程序。父進程可以使用wait()或waitpid()系統(tǒng)調(diào)用等待子進程的結(jié)束并負責(zé)收集和清理子進程的退出狀態(tài)。 fork()系統(tǒng)調(diào)用語法: #include &

2、lt;unistd.h> pid_t fork(void); fork 成功創(chuàng)建子進程后將返回子進程的進程號,不成功會返回-1. exec 系統(tǒng)調(diào)用有一組 6個函數(shù),其中示例實驗中引用了execve 系統(tǒng)調(diào)用語法: #include <unistd.h> int execve(const char *path, const char *argv, const char * envp); path 要裝入的新的執(zhí)行文件的絕對路徑名字符串. argv 要傳遞給新執(zhí)行程序的完整的命令參數(shù)列表(可以為空). envp 要傳遞給新執(zhí)行程序的完整的環(huán)境變量參數(shù)列表(可以為空). exec

3、執(zhí)行成功后將用一個新的程序代替原進程,但進程號不變,它絕不會再返回到調(diào)用進程了。如果 exec 調(diào)用失敗,它會返回-1。 wait() 系統(tǒng)調(diào)用語法: #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid,int *status,int option); status 用于保留子進程的退出狀態(tài) pid 可以為以下可能值: -1 等待所有PGID等于PID的絕對值的子進程 1 等待所有子進程 0 等待所有PGID等于調(diào)用進程的子進程 >

4、;0 等待PID等于pid 的子進程 option 規(guī)定了調(diào)用 waitpid 進程的行為: WNOHANG 沒有子進程時立即返回 WUNTRACED 沒有報告狀態(tài)的進程時返回 wait和 waitpid 執(zhí)行成功將返回終止的子進程的進程號,不成功返回-1。 getpid()系統(tǒng)調(diào)用語法: #include <sys/types.h> #include <unistd.h> pid_t getpid(void); pid_t getppid(void); getpid返回當(dāng)前進程的進程號,getppid 返回當(dāng)前進程父進程的進程號 2) 與進程控制有關(guān)的系統(tǒng)調(diào)用說明 可

5、以通過信號向一個進程發(fā)送消息以控制進程的行為。信號是由中斷或異常事件引發(fā)的,如:鍵盤中斷、定時器中斷、非法內(nèi)存引用等。信號的名字都以 SIG 開頭,例如 SIGTERM、SIGHUP??梢允褂?kill -l 命令查看系統(tǒng)當(dāng)前的信號集合。 信號可在任何時間發(fā)生,接收信號的進程可以對接收到的信號采取3種處理措施之一: · 忽略這個信號 · 執(zhí)行系統(tǒng)默認的處理 · 捕捉這個信號做自定義的處理 信號從產(chǎn)生到被處理所經(jīng)過的過程: 產(chǎn)生(generate)->掛起(pending)->派送(deliver)->部署(disposition)或忽略(igor

6、e) 一個信號集合是一個C 語言的 sigset_t數(shù)據(jù)類型的對象,sigset_t數(shù)據(jù)類型定義在<signal.h>中。被一個進程忽略的所有信號的集合稱為一個信號掩碼(mask)。 從程序中向一個進程發(fā)送信號有兩種方法:調(diào)用 shell的 kill命令,調(diào)用kill系統(tǒng)調(diào)用函數(shù)。kill能夠發(fā)送除殺死一個進程(SIGKILL、SIGTERM、SIGQUIT) 之外的其他信號,例如鍵盤中斷(Ctrl+C)信號SIGINT,進程暫停(Ctrl+Z)信號SIGTSTP 等等。 調(diào)用 pause 函數(shù)會令調(diào)用進程的執(zhí)行掛起直到一個任意信號到來后再繼續(xù)運行。 調(diào)用 sleep 函數(shù)會令調(diào)用

7、進程的執(zhí)行掛起睡眠指定的秒數(shù)或一個它可以響應(yīng)的信號到來后繼續(xù)執(zhí)行。 每個進程都能使用 signal 函數(shù)定義自己的信號處理函數(shù),捕捉并自行處理接收的除SIGSTOP和SIGKILL之外的信號。以下是有關(guān)的系統(tǒng)調(diào)用的語法說明。 kill系統(tǒng)調(diào)用語法: #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); pid 接收信號的進程號 signal 要發(fā)送的信號 kill發(fā)送成功返回接收者的進程號,失敗返回-1。 pause系統(tǒng)調(diào)用語法: include <unistd.h>

8、 int pause(void); pause 掛起調(diào)用它的進程直到有任何信號到達。調(diào)用進程不自定義處理方法,則進行信號的默認處理。只有進程自定義了信號處理方法捕獲并處理了一個信號后,pause 才會返回調(diào)進程。pause 總是返回-1,并設(shè)置系統(tǒng)變量errno為 EINTR。 sleep 系統(tǒng)調(diào)用語法: #include <unistd.h> unsigned int sleep(unsigned int seconds); seconds 指定進程睡眠的秒數(shù) 如果指定的秒數(shù)到,sleep返回 0。 signal系統(tǒng)調(diào)用語法為: #include <signal.h>

9、 typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); signum 要捕捉的信號 handler 進程中自定義的信號處理函數(shù)名 signal 調(diào)用成功會返回信號處理函數(shù)的返回值,不成功返回-1,并設(shè)置系統(tǒng)變量errno 為SIG_ERR。三、實驗內(nèi)容與步驟 以下實驗示例程序應(yīng)實現(xiàn)一個類似子 shell子命令的功能,它可以從執(zhí)行程序中啟動另一個新的子進程并執(zhí)行一個新的命令和其并發(fā)執(zhí)行. 1) 打開一終端命令行窗體,新建一個文件夾,在該文件夾中建立以下名為pctl.c的C

10、語言程序: /* * Filename : pctl.c * copyright : (C) 2006 by zhanghonglie * Function : 父子進程的并發(fā)執(zhí)行 */ #include "pctl.h" int main(int argc, char *argv) int i; int pid; /存放子進程號 int status; /存放子進程返回狀態(tài)char *args = "/bin/ls","-a",NULL; /子進程要缺省執(zhí)行的命令 signal(SIGINT,(sighandler_t)sigcat

11、); /注冊一個本進程處理鍵盤中斷的函數(shù) pid=fork() ; /建立子進程 if(pid<0) / 建立子進程失敗? printf("Create Process fail!n"); exit(EXIT_FAILURE); if(pid = 0) / 子進程執(zhí)行代碼段 /報告父子進程進程號 printf("I am Child process %dnMy father is %dn",getpid(),getppid(); pause(); /暫停,等待鍵盤中斷信號喚醒 /子進程被鍵盤中斷信號喚醒繼續(xù)執(zhí)行 printf("%d ch

12、ild will Running: n ",getpid(); / if(argv1 != NULL) /如果在命令行上輸入了子進程要執(zhí)行的命令 /則執(zhí)行輸入的命令 for(i=1; argvi != NULL; i+) printf("%s ",argvi); printf("n"); /裝入并執(zhí)行新的程序 status = execve(argv1,&argv1,NULL); else /如果在命令行上沒輸入子進程要執(zhí)行的命令 /則執(zhí)行缺省的命令 for(i=0; argsi != NULL; i+) printf("%s

13、 ",argsi); printf("n"); /裝入并執(zhí)行新的程序 status = execve(args0,args,NULL); else /父進程執(zhí)行代碼段 printf("nI am Parent process %dn",getpid(); /報告父進程進程號 if(argv1 != NULL) /如果在命令行上輸入了子進程要執(zhí)行的命令 /則父進程等待子進程執(zhí)行結(jié)束 printf("%d Waiting for child done.nn"); waitpid(pid,&status,0); /等待子進

14、程結(jié)束 printf("nMy child exit! status = %dnn",status); else /如果在命令行上沒輸入子進程要執(zhí)行的命令 /喚醒子進程,與子進程并發(fā)執(zhí)行不等待子進程執(zhí)行結(jié)束, if(kill(pid,SIGINT) >= 0) printf("%d Wakeup %d child.n",getpid(),pid) ; printf("%d don't Wait for child done.nn",getpid(); return EXIT_SUCCESS; 2) 再建立以下名為 pct

15、l.h的 C語言頭文件: #include <sys/types.h> #include <wait.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> /進程自定義的鍵盤中斷信號處理函數(shù) typedef void (*sighandler_t) (int); void sigcat() printf("%d Process continuen",getpid(); 3) 建立以下項目管理文件

16、 Makefile head = pctl.h srcs = pctl.c objs = pctl.o opts = -g -c all: pctl pctl: $(objs) gcc $(objs) -o pctl pctl.o: $(srcs) $(head) gcc $(opts) $(srcs) clean: rm pctl *.o 4) 輸入 make 命令編譯連接生成可執(zhí)行的 pctl程序 $ g make gcc -g -c pctl.c gcc pctl.o -o pctl 5) 執(zhí)行 pctl程序(注意進程號是動態(tài)產(chǎn)生的,每次執(zhí)行都不相同) $ ./pctl I am Chi

17、ld process 4113 My father is 4112 I am Parent process 4112 Wakeup 4113 child. 4112 don't Wait for child done. 4113 Process continue 4113 child will Running: /bin/ls -a . . Makefile pctl pctl.c pctl.h pctl.o $ 以上程序的輸出說明父進程 4112 創(chuàng)建了一個子進程 4113,子進程執(zhí)行被暫停。父進程向子進程發(fā)出鍵盤中斷信號喚醒子進程并與子進程并發(fā)執(zhí)行。父進程并沒有等待子進程的結(jié)束繼續(xù)

18、執(zhí)行先行結(jié)束了(此時的子進程成為了孤兒進程,不會有父進程為它清理退出狀態(tài)了)。而子進程繼續(xù)執(zhí)行,它變成了列出當(dāng)前目錄所有文件名的命令 ls -a。在完成了列出文件名命令之后,子進程的執(zhí)行也結(jié)束了。此時子進程的退出狀態(tài)將有初始化進程為它清理。 6) 再次執(zhí)行帶有子進程指定執(zhí)行命令的 pctl程序: $ ./pctl /bin/ls -l I am Child process 4223 My father is 4222 I am Parent process 4222 4222 Waiting for child done. 可以看到這一次子進程仍然被掛起,而父進程則在等待子進程的完成。為了檢測

19、父子進程是否都在并發(fā)執(zhí)行,請輸入ctrl+z將當(dāng)前進程放入后臺并輸入 ps命令查看當(dāng)前系統(tǒng)進程信息,顯示如下: 1+ Stopped ./pctl /bin/ls -l $ ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 0 4085 4083 0 76 0 - 1413 wait pts/1 00:00:00 bash 0 T 0 4222 4085 0 76 0 - 360 finish pts/1 00:00:00 pctl 1 T 0 4223 4222 0 76 0 - 360 finish pts/1 00:00:00 pctl 0 R 0 4231 4085 0 78 0 - 1302 - pts/1 00:00:00 ps 可以看到當(dāng)前系統(tǒng)中同時有兩個叫 pctl的進程,它們的進程號分別是 4222和 4223。它們的狀態(tài)都為¡° T¡± ,說明當(dāng)前都被掛起。4223 的父進程是 4222,而 4222 的父進程是4085,也就是 bash-shell。為了讓 pctl父子進程繼續(xù)執(zhí)行,請輸入 fg 命令讓pctl再

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論