多路转接<select>和<poll>使用手册

select

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

参数说明

返回值

  • 返回值>0        表示成功返回可访问的文件描述符个数,
  • 返回值==0      表示标识等待时间到期
  • 返回值<0        表示出现错误

int nfds

        当前最大文件描述符值+1:(2,3,5,6,10)那么nfds=10+1,这个是在select系统函数内需要遍历的最大值。

fd_set *readfds,fd_set *writefds,fd_set *exceptfds

读文件描述符集,写文件描述符集,异常文件描述符集

  • fd_set类型本质是一个位图,位图的位置 表示 相对应的文件描述符,内容表示该文件描述符是否有效,1代表该位置的文件描述符有效,0则表示该位置的文件描述符无效。
  • 如果将文件描述符2,3设置位图当中,则位图表示的是为1100。
  • fd_set的上限是1024个文件描述符。

设置函数有:

FD_SET(fd,fdset);  //设置一个fd到fdset中进行等待
FD_ZERO(fdset);    //取消一个fd到fdset中的等待
FD_CLR(fd,fdset);  //清除该fdset中的所有fd
FD_ISSET(fd,fdset) //判定该文件描述符是否存在于fdset集

但是在这个select函数中,这3个参数包括后面的timeout都属于,输入输出型参数。在select类型的服务器中,我们必须要每次在执行select函数前需要从头开始设置每个fdset类型,因为每次函数返回后都会修改传入的fdset参数。

struct timeval *timeout

  • NULL/nullptr:select调用后进行阻塞等待,直到被监视的某个文件描述符上的某个事件就绪。
  • 0(这个0可不是NULL而是 timeval{0,0}):selec调用后进行非阻塞等待,无论被监视的文件描述符上的事件是否就绪,select执行后都会立即返回,不会阻塞等待。
  • 特定的时间值:select调用后在指定的时间内进行阻塞等待,如果被监视的文件描述符上一直没有事件就绪,则在该时间后select进行超时返回。

struct timeval
{
    __time_t tv_sec;		/* Seconds.  */ 秒
    __suseconds_t tv_usec;	/* Microseconds.  */微秒
};
#define __time_t long
#define __suseconds_t long

函数说明

调用函数,他会管理设置在3个fds中的所有文件描述符,只要其中文件描述符中允许写入或者有数据可读取,返回并且设置这3个fds,以输出型参数方式返回给上层。在函数返回后,拿着这3个参数使用FD_ISSET判定那些fd允许访问。

select的优点与缺陷

优点:

  1. 效率高    一个执行流同时等待多个fd等待。
  2. 应用场景:存在大量的链接,但是只有少量的是活跃的!节省资源    如果是多线程/进程需要pcb等内存资源

缺点:

  1. 为了维护第三方数组,select服务器会充满大量的遍历,OS底层帮我们关心fd的时候,也要遍历
  2. 每一次都要对select输出参数进行重新设定
  3. 能够同时管理的fd的个数是有上 限
  4. 因为几乎每一个参数都是输入输出型的,select一定会频繁的进行用户到内核,内核到用户的参数数据拷贝
  5. 编码比较复杂

poll

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数说明

返回值

  • 返回值小于0, 表示出错;
  • 返回值等于0, 表示poll函数等待超时;
  • 返回值大于0, 表示fds数组有多少事件可以访问;

struct pollfd *fds

fds是一个结构体数组

struct pollfd
{
    int fd;			   //需要观察的文件描述符
    short int events;  //输入时的参数	
    short int revents; //输出时的参数
};

注意,这里的指针并不意味是只有一个pollfd,这里的指针是可以看成pollfd[NUM]的一个数组的,这个数组大小并不受约束,并且我们在堆创建,允许扩容realloc,每一个元素都是对应着一个文件描述符,管理着一个文件描述符。

int nfds

标识*fds指向的数组有多少个元素,用于poll函数轮询使用

int timeout

最后一个参数timeout:是一个用毫秒表示的时间,是指定poll在返回前没有接收事件时应该等待的时间。

  • timeout > 0 : 等待timeout毫秒
  • timeout==0 :不会阻塞
  • timeout  < 0 :阻塞等待

函数说明

poll与select相比,poll的编写较为简单。因为poll它有一个结构体,去管理关心事件,不需要像select还得自己去写第三方数组。其次poll它没有数量限制,select是数量限制的,但是数量大了必然会影响效率,poll和select在底层都是采用轮询检测的方式去查看要关心的fd的事件是否就绪。

poll的优缺点

优点

  1. 效率高
  2. 有大量的连接,但是只有少量的是活跃的。节省资源
  3. 输入输出参数分离的,不需要进行大量的重置
  4. poll参数级别,没有可以管理的fd的上限

缺点

  1. poll依旧需要不少的遍历,在用户层检测时间就绪,与内核检测fd就绪,都是一样->epoll出现
  2. poll需要内核到用户的拷贝
  3. poll的代码也比较复杂 -- 比select容易

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云的小站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值