linux 模擬實現sleep函式

2021-08-03 22:25:44 字數 2829 閱讀 2016

功能:將程序掛起一段時間

函式原型:

#include

unsigned

int sleep (unsigned

int seconds);//n秒

來舉乙個很簡單的栗子:

執行以上**後,輸出結果如下:

每隔一秒列印一次,這就是sleep函式的作用。

那麼如何自己模擬實現sleep呢?

先介紹一些我們會用到的函式:

作用:可以讀取和修改與指定訊號相關聯的處理動作,

引數:signum為指定訊號的編號,若act指標為null,或者傳出原來的處理動作,oldact也可以為null。act和oldact都指向下面的結構體:

sa_handler的原型是乙個引數為int,返回型別為void的函式指標。引數即為訊號值,所以訊號不能傳遞除訊號值之外的任何資訊;

sa_sigaction是實時訊號處理函式,它的原型是乙個帶三個引數,型別分別為int,struct siginfo ,void ,返回型別為void的函式指標。第乙個引數為訊號值;第二個引數是乙個指向struct siginfo結構的指標,此結構中包含訊號攜帶的資料值;第三個引數沒有使用。

sa_mask指定在訊號處理程式執行過程中,哪些訊號應當被阻塞。預設當前訊號本身被阻塞。

sa_flags包含了許多標誌位,比較重要的乙個是sa_siginfo,當設定了該標誌位時,表示訊號附帶的引數可以傳遞到訊號處理函式中。即使sa_sigaction指定訊號處理函式,如果不設定sa_siginfo,訊號處理函式同樣不能得到訊號傳遞過來的資料,在訊號處理函式中對這些資訊的訪問都將導致段錯誤。

sa_restorer已過時,posix不支援它,不應再使用。

因此,當你的訊號需要接收附加資訊的時候,你必須給sa_sigaction賦訊號處理函式指標,同時還要給sa_flags賦sa_siginfo,

當某個訊號的處理函式被呼叫時,核心自動將當前訊號加入程序的訊號遮蔽字,當訊號處理函式返回時,自動恢復原來的訊號遮蔽字。保證在處理某個訊號時,如果這個訊號再次產生,那麼它會被阻塞到當前的處理結束為止。如果在調動訊號處理函式時,還需要遮蔽別的訊號,則可以通過sa_mask指定。

(2)pause函式

作用:掛起呼叫程序直到有訊號遞達。

如果訊號的處理動作是終止程序,則程序終止。如果訊號的處理動作是忽略,則程序繼續處於掛起狀態。只有當訊號的處理動作是捕捉,pause函式才會返回。

接下來我們開始實現mysleep.

上述**中的實現步驟為:

(1)呼叫sigaction()捕捉訊號sigalrm

(2)呼叫alarm()設定鬧鐘

(3)呼叫pause()掛起等待

(4)取消鬧鐘

(5)恢復捕捉動作

基於以上**,提出幾個問題。

(1)訊號處理函式handler函式什麼都不做,為什麼還要定義它作為sigalrm的處理函式?不定義訊號處理函式可以嗎?

不可以。因為pause()函式使程序掛起等待,直到有訊號遞達,並且要執行自定義的訊號處理函式才會有機會返回。

(2)為什麼在mysleep函式返回之前要恢復sigalam訊號原來的sigaction?

main函式作為呼叫者只是休息片刻,並不需要改變,因此要恢復原來的sigaction

(3)mysleep的返回值表示什麼含義?什麼情況下返回非0值?

mysleep返回值表示鬧鐘剩餘時間,在取消鬧鐘時,上乙個鬧鐘返回0。

我們再看上面的**,試想,如果有大量優先順序較高的程序需要執行時,測試該程序就有可能被切出,即cpu資源分配給了別的程序,那麼就有可能等待時間過長,導致該程序再次獲得cpu資源時,鬧鐘時間已過,而pause就永遠不會返回。

出現這個問題時由於系統執行**時的時序不確定。如果在寫程式時考慮不周密,可能由於時序問題導致錯誤,這就叫做競態條件。

那麼如何解決競態條件的問題呢?

我們可以在設定鬧鐘之前,遮蔽訊號sigalrm,在讓程序掛起時,解除對該程序的遮蔽,然後再讓子程序掛起等待訊號遞達。我們可以用到sigsuspend函式。

sigsuspend用於在接收到某個訊號之前,臨時用mask替換程序的訊號掩碼,並暫停程序執行,直到收到訊號為止。sigsuspend返回後將恢復呼叫之前的的訊號掩碼。訊號處理函式完成後,程序將繼續執行。該系統呼叫始終返回-1,並將errno設定為eintr.

**修改如下:

Linux 訊號 模擬實現sleep

1 產生訊號 產生訊號的3種方式 1 呼叫系統函式 kill raise abort 2 軟體異常行為 3 組合鍵 ctrl c ctrl d ctrl 等 處理訊號的3種方式 1 忽略。2 預設 很多情況下是終止 3 自定義 訊號捕捉 訊號在核心中的表示 1 遞達 執行訊號的處理動作稱為訊號遞達 ...

模擬實現Spring IOC

通過在類上標註 registration 註冊進容器,injection從容器注入物件 容器類 public class springcontainer else bean.setbeanclass c mappropsmap new hashmap 處理注入屬性 field props c.get...

模擬實現strcmp

函式簡介 原型 int strcmp const char s1,const char s2 所在標頭檔案 string.h 功能 比較字串s1和s2。一般形式 strcmp 字串1,字串2 說明 當s1注意不是 1 當s1 s2時,返回值 0 當s1 s2時,返回正數 注意不是1 如下 int m...