屏蔽信號的多路選擇I/O
阿新 • • 發佈:2017-05-08
一個 set sigma 第一個程序 運行 信號處理 文件描述符 spa sig
前邊提到了多路I/O的方法,這一章屏蔽信號的多路選擇與之前的多路I/O一致,只是增加了屏蔽信號的作用。多路選擇I/O中我們使用的是select函數,屏蔽信號的多路選擇I/O使用的是pselect函數,與之前的函數相比,增加了一個參數可以用來屏蔽信號。具體函數如下所示:
int pselect(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timespec *timeout, const sigset_t *sigmask);
頭文件: #include <sys/select.h>
參數說明:前4個參數與select函數的參數相同,分別表示最大的文件描述符和關心的文件中狀態。
第5個參數表示等待時間,所不同的是timespec結構所能表示的最小精度是納秒,舊的結構體中所能表示的最小精度是微妙數。
pselect函數最後一個參數可以用來屏蔽信號,在pselect函數返回後,再將屏蔽的信號恢復,並且所有的操作都是原子的。
返回值:超時返回0,出錯返回-1,成功返回描述字的個數。
下面用兩個程序的對比來說明select函數與pselect函數的區別。
第一個程序使用select函數,程序中人為的制造了一個造成函數阻塞的條件。該程序在阻塞的時候會被信號中斷。
#include <stdio.h> #include<sys/select.h> #include <stdlib.h> #include <signal.h> /* SIGUSR1的信號處理函數 */ void sigusr1_handler(int signo) { printf("catch SIGUSR1\n"); /* 接收SIGUSR1信號,打印接收信息 */ } int main() { int rdy; /* 準備好的設備數 */ /* 註冊信號處理函數,如果捕捉到信號則輸出提示信息 */ if(signal(SIGUSR1, sigusr1_handler) == SIG_ERR){ perror("can’t set handler for SIGUSR1"); exit(1); } /* 不關心所有的設備準備狀態,所以檢查設備的最大文件描述符的值也不再有意義。 * 等待時間結構為NULL,表示將等待時間設置為無限等待 */ rdy = select(1, NULL, NULL, NULL, NULL); /* 因為是無限等待,所以絕對不應該執行到這裏,輸出提示信息 */ printf("should never be here\n"); return 0; }
第二個程序使用pselect函數,程序中人為的制造了一個造成函數阻塞的條件。該程序在阻塞的時候不會被信號中斷。
#include <stdio.h> #include <sys/select.h> #include <stdlib.h> #include <signal.h> /* SIGUSR1的信號處理函數 */ void sigusr1_handler(int signo) { printf("catch SIGUSR1\n"); /* 接收SIGUSR1信號,打印接收信息 */ } int main() { int rdy; /* 準備好的設備數 */ sigset_t set; /* 信號集 */ /* 註冊信號處理函數,如果捕捉到信號則輸出提示信息 */ if(signal(SIGUSR1, sigusr1_handler) == SIG_ERR){ perror("can’t set handler for SIGUSR1"); exit(1); } sigfillset(&set); /* 設置信號集,屏蔽所有的信號,包括SIGKILL和SIGSTOP */ /* 不關心所有的設備準備狀態,所以檢查設備的最大文件描述符的值也不再有意義。 * 等待時間結構為NULL,表示將等待時間設置為無限等待 */ rdy = pselect(1, NULL, NULL, NULL, NULL, &set); /* 因為是無限等待,所以絕對不應該執行到這裏,輸出提示信息 */ printf("should never be here\n"); return 0; }
在調試的時候用kill命令向進程發送SIGUSR1信號,觀察輸出結果,通過兩個程序運行的對比可以清楚的理解pselect函數和select函數的區別。
屏蔽信號的多路選擇I/O