unix select() 任务调度机制分析
2016-06-17 09:53
267 查看
参考资料:【1】Unix环境高级编程(第二版)P381 14.5.1 select和pselec函数;
【2】 selec函数详细用法解析 http://blog.chinaunix.net/uid-21411227-id-1826874.html
最近在学习live555,发现live555 server的任务调度主要是基于select()模型实现,所以决定对select()详细学习的。因为select函数真的很强大。
1、 首先给出select函数的原型:
#include <sys/select.h>
int select(int maxfdp1,fd_set *restrict readfds,fd_set * restrict writefds,fd_set *restrict exceptfds,struct timeval *restrict timeout);
注:select 函数依从POSIX平台。
2、参数说明:
restrict,C语言中的一种类型限定符(Type
Qualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。
1)、struct timeval {
long tv_sec; //单位是秒
long tv_usec; //单位是毫秒
}
该参数是指定程序调用该函数时获取返回值愿意等待时间,有三种情况:
timeout == NULL(注意:传入参数为NULL,而不是timeval参数都为0)
永远等待。阻塞直到有信号则中断此无限等待。当所指定描述符中的一个已经准备好或者捕捉到一个信号则返回。如果捕捉到一个信号,返回-1,errno设置为EINTR
timeout->tv_sec ==0 && timeout->tv_usec ==0
完全不等待。测试所有指定的描述符并立即返回。得到多个描述符的状态而不阻塞select函数的轮询方法。
timeout->tv_sec !=0 && timeout->tv_usec !=0
等待指定的时间 tv_sec+tv_usec S,当指定的描述符之一准备好,或者当指定的时间值已经超过时立即返回。
(注:posix.1 允许在实现中修改timeval结构中的值,所以在select后,你不能指望该结构仍旧保持调用select之前所包含的值。FreeBSD 5.2.1 Mac OS X 10.3和Solaris 9都保持高结构中的值不变,但是Linux 2.4.22,若在该时间尚未超过timeval时间就返回select时,那么将用余留时间值更新该结构)
2) fd_set*readfds
是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
3) fd_set*writefds
是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
4) fd_set *errorfds
同上面两个参数的意图,用来监视文件错误异常。
5) int maxfdp1:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符集中找出最大描述符编号值,然后加1,这就是第一个参数值,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
2)、3)、4)三个参数是指向描述符的指针。这三个描述符集说明了我们关系的可读、可写或处于异常条件的各个描述符,每个描述符存放在一个fd_set数据类型中。
例:
6)
返回值 整型
负值:select错误。当所指定的
dee0
描述符都没准备好时捕捉到一个信号中断select函数,返回-1.此时不修改其中任何描述符集。
正值:表示准备好的描述符数,该值是三个描述符集中已准备好的描述符数之和。三个描述符集中人就打开的位对应于已准备好的描述符。
0:描述符集没有准备好,等待超时,没有可读写或错误的文件。此时所有描述符集皆被清零。 3.错误代码
执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间,当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
4.举例
从网络上接受数据写入一个文件中。
main()
{
int sock;
FILE *fp;
struct fd_set fds;
struct timeval timeout={3,0}; //select等待3秒,3秒轮询,要非阻塞就置0
char buffer[256]={0}; //256字节的接收缓冲区
/* 假定已经建立UDP连接,具体过程不写,简单,当然TCP也同理,主机ip和port都已经给定,要写的文件已经打开
sock=socket(...);
bind(...);
fp=fopen(...); */
while(1)
{
FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sock,&fds); //添加描述符
FD_SET(fp,&fds); //同上
maxfdp=sock>fp?sock+1:fp+1; //描述符最大值加1
switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select使用
{
case -1: exit(-1);break; //select错误,退出程序
case 0:break; //再次轮询
default:
if(FD_ISSET(sock,&fds)) //测试sock是否可读,即是否网络上有数据
{
recvfrom(sock,buffer,256,.....);//接受网络数据
if(FD_ISSET(fp,&fds)) //测试文件是否可写
fwrite(fp,buffer...);//写入文件
buffer清空;
}// end if break;
}// end switch
}//end while
}//end main
【2】 selec函数详细用法解析 http://blog.chinaunix.net/uid-21411227-id-1826874.html
最近在学习live555,发现live555 server的任务调度主要是基于select()模型实现,所以决定对select()详细学习的。因为select函数真的很强大。
1、 首先给出select函数的原型:
#include <sys/select.h>
int select(int maxfdp1,fd_set *restrict readfds,fd_set * restrict writefds,fd_set *restrict exceptfds,struct timeval *restrict timeout);
注:select 函数依从POSIX平台。
2、参数说明:
restrict,C语言中的一种类型限定符(Type
Qualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。
1)、struct timeval {
long tv_sec; //单位是秒
long tv_usec; //单位是毫秒
}
该参数是指定程序调用该函数时获取返回值愿意等待时间,有三种情况:
timeout == NULL(注意:传入参数为NULL,而不是timeval参数都为0)
永远等待。阻塞直到有信号则中断此无限等待。当所指定描述符中的一个已经准备好或者捕捉到一个信号则返回。如果捕捉到一个信号,返回-1,errno设置为EINTR
timeout->tv_sec ==0 && timeout->tv_usec ==0
完全不等待。测试所有指定的描述符并立即返回。得到多个描述符的状态而不阻塞select函数的轮询方法。
timeout->tv_sec !=0 && timeout->tv_usec !=0
等待指定的时间 tv_sec+tv_usec S,当指定的描述符之一准备好,或者当指定的时间值已经超过时立即返回。
(注:posix.1 允许在实现中修改timeval结构中的值,所以在select后,你不能指望该结构仍旧保持调用select之前所包含的值。FreeBSD 5.2.1 Mac OS X 10.3和Solaris 9都保持高结构中的值不变,但是Linux 2.4.22,若在该时间尚未超过timeval时间就返回select时,那么将用余留时间值更新该结构)
2) fd_set*readfds
是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
3) fd_set*writefds
是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
4) fd_set *errorfds
同上面两个参数的意图,用来监视文件错误异常。
5) int maxfdp1:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符集中找出最大描述符编号值,然后加1,这就是第一个参数值,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
2)、3)、4)三个参数是指向描述符的指针。这三个描述符集说明了我们关系的可读、可写或处于异常条件的各个描述符,每个描述符存放在一个fd_set数据类型中。
例:
6)
返回值 整型
负值:select错误。当所指定的
dee0
描述符都没准备好时捕捉到一个信号中断select函数,返回-1.此时不修改其中任何描述符集。
正值:表示准备好的描述符数,该值是三个描述符集中已准备好的描述符数之和。三个描述符集中人就打开的位对应于已准备好的描述符。
0:描述符集没有准备好,等待超时,没有可读写或错误的文件。此时所有描述符集皆被清零。 3.错误代码
执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间,当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
4.举例
从网络上接受数据写入一个文件中。
main()
{
int sock;
FILE *fp;
struct fd_set fds;
struct timeval timeout={3,0}; //select等待3秒,3秒轮询,要非阻塞就置0
char buffer[256]={0}; //256字节的接收缓冲区
/* 假定已经建立UDP连接,具体过程不写,简单,当然TCP也同理,主机ip和port都已经给定,要写的文件已经打开
sock=socket(...);
bind(...);
fp=fopen(...); */
while(1)
{
FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化
FD_SET(sock,&fds); //添加描述符
FD_SET(fp,&fds); //同上
maxfdp=sock>fp?sock+1:fp+1; //描述符最大值加1
switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select使用
{
case -1: exit(-1);break; //select错误,退出程序
case 0:break; //再次轮询
default:
if(FD_ISSET(sock,&fds)) //测试sock是否可读,即是否网络上有数据
{
recvfrom(sock,buffer,256,.....);//接受网络数据
if(FD_ISSET(fp,&fds)) //测试文件是否可写
fwrite(fp,buffer...);//写入文件
buffer清空;
}// end if break;
}// end switch
}//end while
}//end main
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- Linux 下无损图片压缩小工具介绍