I/O复用:pselect

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)

pselect相对于通常的select有两个变化
(1)timeout支持纳秒。select只支持微妙
(2)最后一个参数sigmask提供指定阻塞信号功能。
不阻塞信号:信号捕获到然后调用信号处理函数。
阻塞信号:信号捕获后,内核记录发生该信号,阻塞信号,不调用信号处理函数。等到设置不阻塞信号时才调用信号处理函数。
UNP 书本举例子

问题是,在测试intr_flag和调用select之间如果有信号发生,那么若select永远阻塞,该信号将丢失。

这里的意思是,1-3行,和4行之间如果SIGINT发生了,并且调用了信号处理函数(该函数只负责把intr_flag设置为1),那么以后将没有机会进行if(intr_flag)的判断,该信号就被永远忽略了。所以我们在第1行前就要开始阻塞信号,从而信号要么在第一行处理,要么在第6行处理。

 1:if(intr_flag){
 2:   handle_intr();     
 3:}
 4:if ((nready = select(..., &zero)) < 0){  
 5if (errno = EINTR){  
 6if (intr_flag)  
 7:            handle_intr();  
 8:    }  
 9...  
10:} 
 1:sigset_t new, old, zero;  
 2:  
 3:sigemptyset(&zero);  //初始化
 4:sigemptyset(&new);  
 5:sigaddset(&new, SIGINT);  //在new中添加SIGINT信号
 6:sigprocmask(SIG_BLOCK, &new, &old);//new是新的包含sigint,old是旧的 
 7:if (intr_flag)  
 8:    handle_intr();//handle the signal
 9:if ((nready = pselect(..., &zero)) < 0){  
10if (errno = EINTR){  
11if (intr_flag)  
12:            handle_intr();  
13:    }  
14...  
15:} 

上面的第6行设置sigprocmask阻塞SIGINT,因此如果在第6行前发生SIGINT信号,则会在第7行处理这个信号。如果在第6行后发生的,由于信号被阻塞,只记录,不调用信号处理函数,那么则会在第9行pselect处理。zero为不阻塞任何信号,此时可以出现SIGINT信号,并且可以调用SIGINT信号处理函数。pselect跳出阻塞后,会恢复之前的new信号集,继续阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值