进程控制3--signal
signal信號是一種比較古老的進程控制手段,可以在進程內和進程間傳遞事件,通常被用來通知進程產生了異常事件
信號全稱為軟中斷信號,也有人稱作軟中斷。從它的命名可以看出,它的實質和使用很象中斷。所以,信號可以說是進程控制的一部分。
首先回憶硬中斷:有單片機或者做過微機原理的都對硬中斷比較熟悉了,中斷有外部中斷和內部中斷,是一些異常事件發生,然后計算機停止當前執行任務轉而去處理中斷任務 。
?
1.信號的概念
軟中斷信號(signal,又簡稱為信號)用來通知進程發生了異步事件。進程之間可以互相通過系統調用kill發送軟中斷信號。內核也可以因為內部事件而給進程發送信號,通知進程發生了某個事件。注意,信號只是用來通知某進程發生了什么事件,并不給該進程傳遞任何數據。?
系統收到信號的進程對各種信號有不同的處理方法。處理方法可以分為三類:
???? A.類似中斷的處理程序,對于需要處理的信號,進程可以指定處理函數,由該函數來處理。
???? B.忽略某個信號,對該信號不做任何處理,就象未發生過一樣。
???? C.對該信號的處理保留系統的默認值,這種缺省操作,對大部分的信號的缺省操作是使得進程終止。進程通過系統調用signal來指定進程對某個信號的處理行為。?
在進程表的表項中有一個軟中斷信號域,該域中每一位對應一個信號,當有信號發送給進程時,對應位置位。由此可以看出,進程對不同的信號可以同時保留,但對于同一個信號,進程并不知道在處理之前來過多少個。
?
2.信號的分類
一般分為以下幾類 :
(1) 與進程終止相關的信號。當進程退出,或者子進程終止時,發出這類信號。?
(2) 與進程例外事件相關的信號。如進程越界,或企圖寫一個只讀的內存區域(如程序正文區),或執行一個特權指令及其他各種硬件錯誤。?
(3) 與在系統調用期間遇到不可恢復條件相關的信號。如執行系統調用exec時,原有資源已經釋放,而目前系統資源又已經耗盡。?
(4) 與執行系統調用時遇到非預測錯誤條件相關的信號。如執行一個并不存在的系統調用。?
(5) 在用戶態下的進程發出的信號。如進程調用系統調用kill向其他進程發送信號。?
(6) 與終端交互相關的信號。如用戶關閉一個終端,或按下break鍵等情況。?
(7) 跟蹤進程執行的信號。?
具體的信號可以找有關資料
?
3.信號的系統調用
統調用signal是進程用來設定某個信號的處理方法,系統調用kill是用來發送信號給指定進程的。這兩個調用可以形成信號的基本操作。后兩個調用pause和alarm是通過信號實現的進程暫停和定時器,調用alarm是通過信號通知進程定時器到時。
A.signal 系統調用?
signal原型如下 :
signal(設置信號處理方式)
相關函數 sigaction,kill,raise
表頭文件 #include<signal.h>
定義函數 void (*signal(int signum,void(* handler)(int)))(int);
函數說明 signal()會依參數signum 指定的信號編號來設置該信號的處理函數。當指定的信號到達時就會跳轉到參數handler指定的函數執行。如果參數handler不是函數指針,則必須是下列兩個常數之一:
SIG_IGN 忽略參數signum指定的信號。
SIG_DFL 將參數signum 指定的信號重設為核心預設的信號處理方式。
返回值返回先前的信號處理函數指針,如果有錯誤則返回SIG_ERR(-1)。
附加說明在信號發生跳轉到自定的handler處理函數執行后,系統會自動將此處理函數換回原來系統預設的處理方式,如果要改變此操作請改用sigaction()。
然后做下面例子 :
[cpp]?view plaincopy
?
B.kill 系統調用?
kill(傳送信號給指定的進程)
相關函數 raise,signal
表頭文件 #include<sys/types.h>
#include<signal.h>
定義函數 int kill(pid_t pid,int sig);
函數說明 kill()可以用來送參數sig指定的信號給參數pid指定的進程。參數pid有幾種情況:
pid>0 將信號傳給進程識別碼為pid 的進程。
pid=0 將信號傳給和目前進程相同進程組的所有進程
pid=-1 將信號廣播傳送給系統內所有的進程
pid<0 將信號傳給進程組識別碼為pid絕對值的所有進程
參數sig代表的信號編號可參考附錄D
返回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤代碼 EINVAL 參數sig 不合法
ESRCH 參數pid 所指定的進程或進程組不存在
EPERM 權限不夠無法傳送信號給指定進程
?
[cpp]?view plaincopy
?
C.pause系統調用?
pause(讓進程暫停直到信號出現)
相關函數 kill,signal,sleep
表頭文件 #include<unistd.h>
定義函數 int pause(void);
函數說明 pause()會令目前的進程暫停(進入睡眠狀態),直到被信號(signal)所中斷。
返回值 只返回-1。
錯誤代碼 EINTR 有信號到達中斷了此函數。
[cpp]?view plaincopy
?
D.alarm系統調用
alarm(設置信號傳送鬧鐘)
相關函數 signal,sleep
表頭文件 #include<unistd.h>
定義函數 unsigned int alarm(unsigned int seconds);
函數說明 alarm()用來設置信號SIGALRM在經過參數seconds指定的秒數后傳送給目前的進程。如果參數seconds 為0,則之前設置的鬧鐘會被取消,并將剩下的時間返回。
返回值返回之前鬧鐘的剩余秒數,如果之前未設鬧鐘則返回0。
[cpp]?view plaincopy
E.setitimer系統調用
int getitimer(int which, struct itimerval *value);?
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);?
在使用這兩個調用的進程中加入以下頭文件:?
#include <sys/time.h>?
該系統調用給進程提供了三個定時器,它們各自有其獨有的計時域,當其中任何一個到達,就發送一個相應的信號給進程,并使得計時器重新開始。三個計時器由參數which指定,如下所示:?
TIMER_REAL:按實際時間計時,計時到達將給進程發送SIGALRM信號。?
ITIMER_VIRTUAL:僅當進程執行時才進行計時。計時到達將發送SIGVTALRM信號給進程。?
ITIMER_PROF:當進程執行時和系統為該進程執行動作時都計時。與ITIMER_VIR-TUAL是一對,該定時器經常用來統計進程在用戶態和內核態花費的時間。計時到達將發送SIGPROF信號給進程。?
定時器中的參數value用來指明定時器的時間,其結構如下:?
struct itimerval {?
struct timeval it_interval; /* 下一次的取值 */?
struct timeval it_value; /* 本次的設定值 */?
};?
該結構中timeval結構定義如下:?
struct timeval {?
long tv_sec; /* 秒 */?
long tv_usec; /* 微秒,1秒 = 1000000 微秒*/?
};?
在setitimer 調用中,參數ovalue如果不為空,則其中保留的是上次調用設定的值。定時器將it_value遞減到0時,產生一個信號,并將it_value的值設 定為it_interval的值,然后重新開始計時,如此往復。當it_value設定為0時,計時器停止,或者當它計時到期,而it_interval 為0時停止。調用成功時,返回0;錯誤時,返回-1,并設置相應的錯誤代碼errno:?
EFAULT:參數value或ovalue是無效的指針。?
EINVAL:參數which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一個。?
總結
以上是生活随笔為你收集整理的进程控制3--signal的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 招行白金卡申请进度怎么查询
- 下一篇: 北上资金是什么意思??北上资金和外资的区