1. 程式人生 > >軟中斷通訊

軟中斷通訊

一、內容:
編寫一段C語言程式,使其實現程序的軟中斷通訊。
二、要求:
使用系統呼叫fork()創造二個程序,父程序睡眠2秒後,用系統呼叫Kill() 向兩個子程序發出訊號,子程序捕捉到資訊後分別輸出下列資訊終止:
Child Processl1 is Killed by Parent!
Child Processl2 is Killed by Parent!
父程序等待兩個子程序終止後,輸出如下的資訊後終止:
Parent Process is Killed!
Parent Process is Killed!
三、思考題:
(1) 在父程序中使用兩個wait(0),它們起什麼作用?
(2) 該程式段每個程序退出時都用了語句exit
(0),為什麼? 四、實驗報告要求: (1) 列出除錯通過程式的清單,分析執行結果。 (2) 回答思考題; (3) 總結上機除錯過程中所遇到的問題和解決方法及感想。 五、實驗預備知識: 附錄: 一、訊號 1、訊號的基本概念 每個訊號都對應一個正整數常量(稱為signal number,即訊號編號。定義在系統標頭檔案<signal.h>中),代表同一使用者的諸程序之間傳送事先約定的資訊的型別,用於通知某程序發生了某異常事件。每個程序在執行時,都要通過訊號機制來檢查是否有訊號到達。若有,便中斷正在執行的程式,轉向與該訊號相對應的處理程式,以完成對該事件的處理;處理結束後再返回到原來的斷點繼續執行。實質上,訊號機制是對中斷機制的一種模擬,故在早期的UNIX版本中又把它稱為軟中斷。 訊號與中斷的相似點: (1
)採用了相同的非同步通訊方式; (2)當檢測出有訊號或中斷請求時,都暫停正在執行的程式而轉去執行相應的處理程式; (3)都在處理完畢後返回到原來的斷點; (4)對訊號或中斷都可進行遮蔽。 訊號與中斷的區別: (1)中斷有優先順序,而訊號沒有優先順序,所有的訊號都是平等的; (2)訊號處理程式是在使用者態下執行的,而中斷處理程式是在核心態下執行; (3)中斷響應是及時的,而訊號響應通常都有較大的時間延遲。 訊號機制具有以下三方面的功能: (1)傳送訊號。傳送訊號的程式用系統呼叫kill( )實現; (2)預置對訊號的處理方式。接收訊號的程式用signal( )來實現對處理方式的預置; (3)收受訊號的程序按事先的規定完成對相應事件的處理。 2
、訊號的傳送 訊號的傳送,是指由傳送程序把訊號送到指定程序的訊號域的某一位上。如果目標程序正在一個可被中斷的優先順序上睡眠,核心便將它喚醒,傳送程序就此結束。一個程序可能在其訊號域中有多個位被置位,代表有多種型別的訊號到達,但對於一類訊號,程序卻只能記住其中的某一個。 程序用kill( )向一個程序或一組程序傳送一個訊號。 3、對訊號的處理 當一個程序要進入或退出一個低優先順序睡眠狀態時,或一個程序即將從核心態返回使用者態時,核心都要檢查該程序是否已收到軟中斷。當程序處於核心態時,即使收到軟中斷也不予理睬;只有當它返回到使用者態後,才處理軟中斷訊號。對軟中斷訊號的處理分三種情況進行: (1)如果程序收到的軟中斷是一個已決定要忽略的訊號(function=1),程序不做任何處理便立即返回; (2)程序收到軟中斷後便退出(function=0); (3)執行使用者設定的軟中斷處理程式。 二、所涉及的中斷呼叫 1kill( ) 功能描述: 用於向任何程序組或程序傳送訊號。 系統呼叫格式 #include <sys/types.h> #include <signal.h> int kill(pid,sig) 引數定義 int pid,sig; 其中,pid是一個或一組程序的識別符號,引數sig是要傳送的軟中斷訊號。 (1)pid>0時,核心將訊號傳送給程序pid。 (2)pid=0時,核心將訊號傳送給與傳送程序同組的所有程序。 (3)pid=-1時,核心將訊號傳送給所有使用者識別符號真正等於傳送程序的有效使用者標識號的程序。 2、signal( ) 預置對訊號的處理方式,允許呼叫程序控制軟中斷訊號。 系統呼叫格式 #include <signal.h> signal(sig,function) 引數定義 int sig; void (*func) ( ) 其中sig用於指出要設定處理方法的訊號,sig為0則表示沒有收到任何訊號,餘者如下表: 值 名字 說明 01 SIGHUP 掛起(hangup) 02 SIGINT 中斷,當用戶從鍵盤按^c鍵或^break鍵時 03 SIGQUIT 退出,當用戶從鍵盤按quit鍵時 04 SIGILL 非法指令 05 SIGTRAP 跟蹤陷阱(trace trap),啟動程序,跟蹤程式碼的執行 06 SIGIOT IOT指令 07 SIGEMT EMT指令 08 SIGFPE 浮點運算溢位 09 SIGKILL 殺死、終止程序 10 SIGBUS 匯流排錯誤 11 SIGSEGV 段違例(segmentation violation),程序試圖去訪問其虛地址空間以外的位置 12 SIGSYS 系統呼叫中引數錯,如系統呼叫號非法 13 SIGPIPE 向某個非讀管道中寫入資料 14 SIGALRM 鬧鐘。當某程序希望在某時間後接收訊號時發此訊號 15 SIGTERM 軟體終止(software termination) 16 SIGUSR1 使用者自定義訊號1 17 SIGUSR2 使用者自定義訊號2 18 SIGCHLD 某個子程序死 19 SIGPWR 電源故障 function:是一個處理函式,或者是: SIG_IGN:忽略引數sig所指的訊號 SIG_DFL:恢復引數sig所指訊號的處理方法為預設值 3wait( )函式 wait()函式常用來控制父程序與子程序的同步。在父程序中呼叫wait()函式,則父程序被阻塞,進入等待佇列,等待子程序結束。當子程序結束時,會產生一個終止狀態字,系統會向父程序發出SIGCHLD訊號。當接到訊號後,父程序提取子程序的終止狀態字,從wait()函式返回繼續執行原程式。 其呼叫格式為: (pid_t) wait(int *statloc); 正確返回:大於0:子程序的程序ID值; 等於0:其它。 錯誤返回:等於-1:呼叫失敗。 4exit()函式 exit()函式是程序結束最常呼叫的函式,在main()函式中呼叫return,最終也是呼叫exit()函式。這些都是程序的正常終止。在正常終止時,exit()函式返回程序結束狀態。 其呼叫格式為: #include <stdio.h> void exit(int status); 其中status為程序結束狀態。 請同學們先試一下這個示例程式,然後再考慮實驗內容。 #include<signal.h> #include<unistd.h> #include<sys/types.h> #include<sys/msg.h> #include<sys/ipc.h> Void sss( ) {printf (“\t bbb \n”); } Main () { int i; Signal (SIGINT , sss); for (i=0;i<=100;i++) {printf(“%d,aaa\n”,i+1); sleep(1); } printf(“process finished\n”); } ] 程式框架示例: #include<signal.h> #include<unistd.h> #include<sys/types.h> #include<sys/msg.h> #include<sys/ipc.h> void waiting(),stop(); int wait_mark; main() { 。。。。 sleep(2); kill(p1,16); kill(p2,17); wait(0); wait(0); printf("parent process is killed!\n"); exit(0); } {。。。。 signal(17,stop); 。。。 void waiting() { while(wait_mark==1); } void stop() { wait_mark=0; } 思考題、討論題、作業 教學後記