歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux技術

Linux中的信號(2)

在上篇博客中,主要介紹了信號的基本概念,這次我主要介紹一下與信號相關的函數以及對它們的應用。

sigaction函數

#include <signal.h>

int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

sigaction函數可以讀取和修改與指定信號相關聯的處理動作。

調用成功則返回0,出錯則返回- 1。

signo是指定信號的編號。

若act指針非空,則根據act修改該信號的處理動作。

若oact指針非空,則通過oact傳出該信號原來的處理動作。

act和oact指向sigaction結 構體:

pause函數

#include <unistd.h>

int pause(void);

pause函數使調用進程掛起直到有信號遞達。如果信號的處理動作是終止進程,則進程終止,pause函數沒有機會返回;如果信號的處理動作是忽略,則進程繼續處於掛起狀態,pause 不返回;如果信號的處理動作是捕捉,則調用了信號處理函數之後pause返回-1,errno設置為 EINTR, 所以pause只有出錯的返回值(想想以前還學過什麼函數只有出錯返回值?)。錯誤碼 EINTR表示“被信號中斷”。

{exec函數、pause函數只會出錯返回。。。}

競態條件與sigsuspend函數

由於異步事件在任何時候都有可能發生(這裡的異步事件指出現更高優先級的進程),如果我們寫程序時考慮不周密,就可能由於時序問題 而導致錯誤,這叫做競態條件 (Race Condition)。

和pause一樣,sigsuspend沒有成功返回值,只有執行了一個信號處理函數之後 sigsuspend才返回,返回值為-1,errno設置為EINTR。

調用sigsuspend時,進程的信號屏蔽字由sigmask參數指定,可以通過指定sigmask來臨時解除對某個信號的屏蔽,然後掛起等待,當sigsuspend返回時,進程的信號屏蔽字恢復為原來的值,如果原來對該信號是屏蔽的,從sigsuspend返回後仍然是屏蔽的。

首先,我們來對31個信號進行捕捉,查看有那個信號不能被捕捉:

代碼如下:

我們在另外一個終端中給這個進程發送信號,看那個信號可以是程序結束:

9號信號(SIGKILL):

19號信號(SIGSTOP):

結論:這兩個信號並不能捕捉

實現自己的my_sleep函數:

代碼:

這是我們自己實現的my_sleep函數,看下有沒有什麼問題?

系統運行的時序(Timing)並不像我們寫程序時所設想的那樣。 雖然alarm(timeout)緊接著的下一行就是pause(),但是無法保證pause()一定會在調用alarm(timeout)之後的timeout秒之內被調用。由於異步事件在任何時候都有可能發生,這時由於時序問題就會出現錯誤。

怎樣改進呢?

這時我們就要使用sigsuspend函數,而不是pause函數。

看下面的代碼:

運行結果:

Copyright © Linux教程網 All Rights Reserved