屏蔽信號的多路選擇I/O

 

前邊提到了多路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函數的區別。

相關文章
相關標籤/搜索