【I/O多路复用】poll系统调用

【1】前言

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它再次遍历fd。

【2】poll系统调用函数原型

# include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

fds参数:一个pollfd结构类型的数组,指定所有我们希望监听的所有文件描述符上发生的可读、可写和异常等事件。

nfds参数:指定指定被监听事件集合fds的大小

timeout参数:指定poll的超时值,单位是毫秒。
timeout 为-1时: poll调用将永远阻塞,直到某个事件发生
timeout为0时:poll调用将立即返回

 typedef  unsigned  long int  nfds_t;

pollfd结构体定义如下:

struct pollfd 
{
   
	int fd;         	/* 文件描述符 */
	short events;       /* 注册的事件 */
	short revents;      /* 实际发生了的事件,由内核填充*/
}; 

其中fd成员指定文件描述符;
events成员告诉poll监听fd上那些事件,他是一系列事件的按位或;
revents成员由内核修改,用来通知应用程序fd上哪些事件真实发生了。
如果events上的事件发生了,revents就会将自己与events的对应位置为1

poll支持的时间类型如下:

事件 描述
POLLIN 有数据可读
POLLRDNORM 有普通数据可读
POLLRDBAND 有优先数据可读
POLLPRI 有紧迫数据可读
POLLOUT 写数据不会导致阻塞
POLLWRNORM 写普通数据不会导致阻塞
POLLWRBAND 写优先数据不会导致阻塞
POLLMSGSIGPOLL 消息可用

revents域中可能返回下列事件:

事件 描述
POLLER 指定的文件描述符发生错误
POLLHUP 指定的文件描述符挂起事件
POLLNVAL 指定的文件描述符非法

返回值

  • 大于0:表示数组fds中有socket描述符的状态发生变化,或可以读取、或可以写入、或出错。并且返回的值表示这些状态有变化的socket描述符的总数量;此时可以对fds数组进行遍历,以寻找那些revents不空的socket描述符,然后判断这个里面有哪些事件以读取数据。
  • 等于0:表示没有socket描述符有状态变化,并且调用超时。
  • 小于0:此时表示有错误发生,此时全局变量errno保存错误码。

【3】程序示例

下面是一个基于TCP的多客户端服务器交互的程序:

【1】建立三次连接后若client客户端不发送数据,则服务器端会在超时时间5秒内轮询遍历fds数组等待client客户端发送数据,超时时间timeout设置为5秒,若5秒内没有数据发送到服务器则会打印出"time out"。
【2】直到client发送数据,内核会将该事件的fds[i].revevts修改,poll则会进行遍历fds数组找到fds[i].revents异或有数据可读POLLIN为真的事件进行处理。
【3】这时有两种情况,若fds[i].fd == sockfd说明监听队列中有连接待处理,则使用accept拿出一个连接。否则,没有新连接产生,是有客端发来了数据,我们直接使用recv接收客端数据,并打印收到的数据。

server.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<poll.h>

#define MAXFD 10
int create_sockfd();

//向fds数组中添加文件描述符fd,指定关注的事件
void fds_add(struct pollfd fds[],int fd)
{
   
	int i=0;
	for(;i<MAXFD;++i)
	{
   
		if(fds[i].fd==-1)
		{
   
			fds[i].fd=fd;
			fds[i
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值