当前位置: 技术问答>linux和unix
多路I/O中select机制的问题
来源: 互联网 发布时间:2015-11-28
本文导语: select返回的是某一个文件描述符是否读写,还是好几个呢? FD_ISSET宏是判断一个文件描述符是否在集合里,那它怎么判断一个描述符是否可读写呢?? select机制中,是不是不论从串口、网口、键盘输入的数据都先到...
select返回的是某一个文件描述符是否读写,还是好几个呢?
FD_ISSET宏是判断一个文件描述符是否在集合里,那它怎么判断一个描述符是否可读写呢??
select机制中,是不是不论从串口、网口、键盘输入的数据都先到系统内核中缓存,然后程序处理的时候,到系统内核中读取数据?
请高手指教!
FD_ISSET宏是判断一个文件描述符是否在集合里,那它怎么判断一个描述符是否可读写呢??
select机制中,是不是不论从串口、网口、键盘输入的数据都先到系统内核中缓存,然后程序处理的时候,到系统内核中读取数据?
请高手指教!
|
man select知道:
返回正值为发生数据传输的socket数目。0值为timeout。负值为有错误发生。
当然可以好几个文件描述符可读写。只要你当初用FD_SET将你想侦听的socket加入fds_serial中。然后用FD_ISSET来判断所有你加入的socket是否有数据传输,
简单架构就是:
int main()
{
fd_set rfds;
struct timeval tv;
int retval;
//Watch stdin(fd 0) and stderr(fd 2) to see when it has input
FD_ZERO(&rfds);
FD_ISSET(0, &rfds);
FD_ISSET(2, &rfds);
//Wait up to five seconds
tv.tv_sec = 5;
tv.tv_usec =0;
retval = select(2, &rfds, NULL, NULL, &tv);
if(retval 0
{
printf("Data is available now.n");
if(FD_ISSET(0, &rfds))
{
printf("stdin has data inn");
//read_stdin_data();
exit(0);
}
if(FD_ISSET(2, &rfds))
{
printf("stderr has data inn");
//read_stderr_data();
exit(0);
}
}
}
返回正值为发生数据传输的socket数目。0值为timeout。负值为有错误发生。
当然可以好几个文件描述符可读写。只要你当初用FD_SET将你想侦听的socket加入fds_serial中。然后用FD_ISSET来判断所有你加入的socket是否有数据传输,
简单架构就是:
int main()
{
fd_set rfds;
struct timeval tv;
int retval;
//Watch stdin(fd 0) and stderr(fd 2) to see when it has input
FD_ZERO(&rfds);
FD_ISSET(0, &rfds);
FD_ISSET(2, &rfds);
//Wait up to five seconds
tv.tv_sec = 5;
tv.tv_usec =0;
retval = select(2, &rfds, NULL, NULL, &tv);
if(retval 0
{
printf("Data is available now.n");
if(FD_ISSET(0, &rfds))
{
printf("stdin has data inn");
//read_stdin_data();
exit(0);
}
if(FD_ISSET(2, &rfds))
{
printf("stderr has data inn");
//read_stderr_data();
exit(0);
}
}
}
|
linux里的select自己就是一个循环,每次执行时检查是否有描述符就绪或出现异常,如果都没有就主动让出cpu,自己小睡一会儿,这个睡眠可能被I/O动作结束后的信号打断,也可能睡足一个时间后主动醒来,然后再次执行检查。如果有描述符就绪或者error发生,则置fd_set中相应位,全部检查完后,fdset不为空,于是select返回到程序中。
|
多路复用,我理解就象是几个描述符并行操作,既然是并行,当然是有可能几个同时到达可读写的条件的。
其实select中用了一个int,也就是32bit来保存你感兴趣的描述符的状态,初始状态32位都位0;当某个描述符变为可读写的时候,其对应的位就被设置位1。select本身是一个循环,当一个循环到来时,它来检测这32位中有几个1。从一次循环到下次循环总有一段时间,这段时间就有可能有几个描述符都变为了可读写了。
其实select中用了一个int,也就是32bit来保存你感兴趣的描述符的状态,初始状态32位都位0;当某个描述符变为可读写的时候,其对应的位就被设置位1。select本身是一个循环,当一个循环到来时,它来检测这32位中有几个1。从一次循环到下次循环总有一段时间,这段时间就有可能有几个描述符都变为了可读写了。
|
select返回后有几种不同含义
任何描述字准备好读或写,有异常等待处理,超时,
如果你在执行select之前,初始化了集合多个位,返回值表示跨所有描述字集的已准备好的总位数(不考虑异常和超时)
“数据都先到系统内核中缓存”,只知道是先读到套接口缓冲区
任何描述字准备好读或写,有异常等待处理,超时,
如果你在执行select之前,初始化了集合多个位,返回值表示跨所有描述字集的已准备好的总位数(不考虑异常和超时)
“数据都先到系统内核中缓存”,只知道是先读到套接口缓冲区
|
当select返回后,要用FD_ISSET判断每一个字集
存放在套接口缓冲区,要用接收函数去获取
存放在套接口缓冲区,要用接收函数去获取
|
select()函数可以一次返回多个活动的描述符,参数中输入的是你所关心的描述符的列表,返回后,里边保存的是活动的描述符的列表。
|
该函数允许进程指示内核等待多个时间中的任何一个发生,并且仅在一个或多个时间发生或者经过某指定时间后才唤醒进程。通过select()的产如参数,我们可以通知内核我们对哪些描述字感兴趣(读、写或者异常情况)以及等待多长时间,我们所关心的描述字不受限与套接字,任何描述字都可以用select()函数进行测试。
可以运用一下测试宏对描述符列表进行设置和测试:
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
可以运用一下测试宏对描述符列表进行设置和测试:
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);