1. 程式人生 > >屏蔽信號的多路選擇I/O

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

一個 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