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

Linux-MySleep函數實現與竟態條件

(一) 函數實現的整體框架

1>需要用到的函數接口 2>實現的整體過程思路 3>程序運行遇到可能情況的分析 4>優化結果與解決方案

(二)三個主要的函數接口

根據系統內部的sleep函數為基礎,通過了解其運行過程,可以使用alarm()函數,pause()函數以及sigaction()函數進行實現。

函數參數及返回值

Markdown Extra 表格語法:

函數名稱 參數 返回值 alarm() unsigned int seconds 返回0或信號響應後剩余時間 pause() void 只有出錯返回值 sigaction() (int signo,const struct sigaction *restrict act,struct sigaction *restrict oact) 這裡不做研究

sigaction結構體

struct sigaction {
void (*sa_handler)(int);
void (sa_sigaction)(int, siginfo_t , void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
信號處理函數可以采用void (sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t , void )。到底采用哪個要看sa_flags中是否設置了SA_SIGINFO位,如果設置了就采用void (*sa_sigaction)(int, siginfo_t , void *),此時可以向處理函數發送附加信息;默認情況下采用void (*sa_handler)(int),此時只能向處理函數發送信號的數值。
sa_handler此參數和signal()的參數handler相同,代表新的信號處理函數,其他意義請參考signal()。
sa_mask 用來設置在處理該信號時暫時將sa_mask 指定的信號集擱置。
sa_restorer 此參數沒有使用。
sa_flags 用來設置信號處理的其他相關操作,下列的數值可用。
sa_flags還可以設置其他標志:
SA_RESETHAND:當調用信號處理函數時,將信號的處理函數重置為缺省值SIG_DFL
SA_RESTART:如果信號中斷了進程的某個系統調用,則系統自動啟動該系統調用
SA_NODEFER :一般情況下, 當信號處理函數運行時,內核將阻塞該給定信號。但是如果設置了 SA_NODEFER標記, 那麼在該信號處理函數運行時,內核將不會阻塞該信號

mysleep實現代碼

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include<stdio.h> #include<signal.h>   void myhandler(int sig) {}   int mysleep(int timeout) {     struct sigaction act,oact;     act.sa_handler = myhandler;     sigemptyset(&act.sa_mask);     act.sa_flags = 0;     sigaction(SIGALRM,&act,&oact);       alarm(timeout);     pause();     int ret = alarm(0);     sigaction(SIGALRM,&oact,NULL);     return ret;   }   int main() {     while(1)     {         printf("mysleep start...\n");         mysleep(3);         printf("mysleep success\n");     }     return 0;   }</signal.h></stdio.h>

執行過程

1)main函數調用mysleep函數。mysleep函數調用sigaction注冊了SIGALRM信號的處理函數myhandler。這裡的myhandler函數並沒有做什麼工作,但不能少,因為SIGALRM信號的默認處理是終止進程。
2)調用alarm(timeout)設定鬧鐘。
3)調用pause等待,內核切換到別的進程運行。
4)timeout秒之後,鬧鐘超時,內核發SIGALRM給這個進程。
5)從內核態返回這個進程的用戶態之前處理未決信號,發現有SIGALRM信號,其處理函數是myhandler。
6)於是切換到用戶態執行myhandler函數,進入myhandler函數時SIGALRM信號被自動屏蔽, 從myhandler函數返回時SIGALRM信號自動解除屏蔽。然後自動執行系統調用sigreturn再次進入內核,再返回用戶態繼續執行進程的主控制流程,即為main函數調用mysleep函數處。

Copyright © Linux教程網 All Rights Reserved