前邊提到了多路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); spa
頭文件: #include <sys/select.h> 調試
參數說明:前4個參數與select函數的參數相同,分別表示最大的文件描述符和關心的文件中狀態。code
第5個參數表示等待時間,所不一樣的是timespec結構所能表示的最小精度是納秒,舊的結構體中所能表示的最小精度是微妙數。blog
pselect函數最後一個參數能夠用來屏蔽信號,在pselect函數返回後,再將屏蔽的信號恢復,而且全部的操做都是原子的。進程
返回值:超時返回0,出錯返回-1,成功返回描述字的個數。it
下面用兩個程序的對比來講明select函數與pselect函數的區別。io
第一個程序使用select函數,程序中人爲的製造了一個形成函數阻塞的條件。該程序在阻塞的時候會被信號中斷。class
#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函數,程序中人爲的製造了一個形成函數阻塞的條件。該程序在阻塞的時候不會被信號中斷。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; /* 準備好的設備數 */ 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函數的區別。