select和pslect的man手册
SELECT(2) Linux Programmer's Manual SELECT(2)
NAME
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing
SYNOPSIS
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
#include <sys/select.h>
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
最大的区别在于pselect的最后一个参数const sigset_t *sigmask,看名字应该是信号屏蔽,现在分别写一个select和一个pselect对于信号的反应。
测试一:select测试代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define _DEBUG_PRINT
#ifdef _DEBUG_PRINT
#define DEBUG_PRINT(format,...) printf(format,##__VA_ARGS__)
#else
#define DEBUG_PRINT(format,...)
#endif
void sig_func(int sig){
DEBUG_INFO(" sig = %d", sig);
}
int main(int argc, char *argv[])
{
fd_set rfds;
int retval;
char buf[100];
signal(SIGINT, sig_func);
FD_ZERO(&rfds);
FD_SET(0,&rfds);
select_pos:
retval = select(1,&rfds,NULL,NULL,NULL);
if(retval == -1){
if(errno == EINTR){
DEBUG_INFO("get a signal");
exit(0);
}
}
read(0,buf,sizeof(buf));
goto select_pos;
DEBUG_INFO("bye bye.");
return 0;
}
测试:
实验解析:
当按下CTRL+C时,select返回-1,此时errno的值是EINTR,表示select被信号打断。
测试二:pselect的最后一个参数设置为NULL
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define _DEBUG_PRINT
#ifdef _DEBUG_PRINT
#define DEBUG_PRINT(format,...) printf(format,##__VA_ARGS__)
#else
#define DEBUG_PRINT(format,...)
#endif
void sig_func(int sig){
DEBUG_INFO(" sig = %d", sig);
}
int main(int argc, char *argv[])
{
fd_set rfds;
int retval;
char buf[100];
signal(SIGINT, sig_func);
FD_ZERO(&rfds);
FD_SET(0,&rfds);
select_pos:
retval = pselect(1,&rfds,NULL,NULL,NULL,NULL);
if(retval == -1){
if(errno == EINTR){
DEBUG_INFO("get a signal");
exit(0);
}
}
read(0,buf,sizeof(buf));
goto select_pos;
DEBUG_INFO("bye bye.");
return 0;
}
实验解析:
此时的pselect和测试一的select效果等价。
实验三: pselect的最后一个参数设置为有效值
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define _DEBUG_PRINT
#ifdef _DEBUG_PRINT
#define DEBUG_PRINT(format,...) printf(format,##__VA_ARGS__)
#else
#define DEBUG_PRINT(format,...)
#endif
void sig_func(int sig){
DEBUG_INFO(" sig = %d", sig);
}
int main(int argc, char *argv[])
{
fd_set rfds;
int retval;
char buf[100];
sigset_t blockset;
signal(SIGINT, sig_func);
FD_ZERO(&rfds);
FD_SET(0,&rfds);
sigemptyset(&blockset);
sigaddset(&blockset,SIGINT);
select_pos:
retval = pselect(1,&rfds,NULL,NULL,NULL,&blockset);
if(retval == -1){
if(errno == EINTR){
DEBUG_INFO("get a signal");
exit(0);
}
perror("pselect");
return -1;
}
int len = read(0,buf,sizeof(buf));
DEBUG_INFO("len = %d",len);
for(int i = 0;i < len;i++){
printf("%d,",buf[i]);
}
sigemptyset(&blockset);
printf("\n");
goto select_pos;
DEBUG_INFO("bye bye.");
return 0;
}
测试过程:
实验解析
因为SIGINT被屏蔽,第一次按下CTRL+C时,pselect并不会被打断,输入一些字符,让pselect执行一次,通过sigemptyset(&blockset);解除屏蔽,第二次按下CTRL+C时,pselect被打断,并返回-1,errno返回值为EINTR。
小结