1. 程式人生 > >Linux環境程式設計之訊號處理(三、利用alarm()和pause()函式實現sleep()函式)

Linux環境程式設計之訊號處理(三、利用alarm()和pause()函式實現sleep()函式)

        sleep()是執行掛起一段時間,而alarm()函式是定時器,pause()函式則是掛起程序,當出現訊號打斷時,才會繼續往前執行;

        先來分享下alarm()函式,alarm()函式用來設定一個定時器,當時間超時時,會產生SIGALRM訊號,該訊號預設是終止該程序;

        #include<unistd.h>

        unsigned int alarm(unsigned int seconds);

        引數:unsigned int seconds表示經過seconds秒後會產生訊號SIGALRM;

        返回值:0或者以前設定的鬧鐘時間的餘留秒數;

        1、每個程序只能有一個鬧鐘時鐘;

        2、呼叫alarm()時,假如以前呼叫過alarm()函式,並且指定的時間還沒到(即:還沒超時,沒有傳送SIGALRM訊號)。那麼此次呼叫的alarm()函式會替代掉上一次的alarm()函式,並且返回值為上次呼叫alarm()函式中沒有用完的時間;

        3、本次呼叫alarm(0)函式會取消上一次未超時的定時器,返回剩餘的時間;

        下面也看看pause()函式:

        #include<unistd.h>

        int pause(void);

        pause()會把程序掛起來,直到一個訊號處理程式執行完後,才會繼續執行;

        最後看看sleep()函式:

        #include<unistd.h>

        unsigned int sleep(unsigned int seconds);

        該函式使呼叫程序被掛起了,直到seconds後(超時後),或者捕捉到一個訊號並且從訊號處理函式返回後,該程序才能繼續往下執行;返回值和alarm()函式的一樣。

        下面是利用alarm()函式和pause()函式來實現下sleep()函式:

#include<stdio.h>
#include<signal.h>
#include<setjmp.h>
#include<unistd.h>
 
static jmp_buf envAlarm;
 
static void myAlarm(int signo)// 自定義的SIGALRM定時器訊號的處理函式
 {
     longjmp(envAlarm, 1);// 區域性跳轉
 }
 
 unsigned int mySleep(unsigned int sec)
 {
     unsigned int minSec, ret, tmp = 0;
 
     if (signal(SIGALRM, myAlarm) == SIG_ERR)// 繫結SIGALRM和myAlarm()函式
         return sec;
 
     minSec = alarm(0);// 得到上一次未超時的定時器所剩的時間,防止沖刷掉上一次的真正的定時器(本函式的是實現sleep())
     ret = sec > minSec ? (sec-minSec):0;// 得到返回值
 
     if (setjmp(envAlarm) == 0){ // 區域性跳轉
         if (minSec) // 這裡考慮的是如果前面有設定定時器
             alarm(minSec < sec ? minSec:sec);// 利用時間短的去做定時器
         else // 如果前面沒有設定定時器,則直接利用引數去掛起程序
             alarm(sec);
 
         sleep(9);// 這裡是測試上一個alarm()函式到pause()之間延遲導致SIGALRM訊號處理完後,pause()還沒有觸犯,則程序一直掛起
         pause();
     }   
     tmp = alarm(0);// 計算在睡眠時 有可能被其他訊號打斷,而剩下一些未睡眠的時間
     if (minSec > sec){// 如果前面登記的定時器比睡眠時間長,則退出後還要把定時器復位為剩下時間的定時器
         alarm(minSec-sec);// 定時器還剩多少時間,重新設定定時器
     } 
    if (tmp)ret += tmp; // 統計所有剩餘時間
 
     return ret;
 }
 
 int main(int argc, char* argv[])
 {
     unsigned int otherSec;
     alarm(6);
     //sleep(4);
     otherSec = mySleep(3);
     printf("mySleep resturn:%u\n", otherSec);
     return 0;
 }

        上面是通過區域性跳轉來實現sleep()函式的,當然還有使用訊號遮蔽字來實現的,後面有時間會實現下。不知道上面的程式碼是否有漏洞,雖然這個程式碼量不多,但是要考慮的問題還是比較多的。如果有朋友發現了漏洞,歡迎指正!!謝謝!!

        若有不正確之處,望大家指正,共同學習!謝謝!!!