【网络】多路复用方法

用来做常用的多路复用的函数:

select 函数:

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

-nfds: 委托内核检测的最大文件描述符的值+1-readfds:  检测文件描述符的读的集合,委托内核检测那些文件描述符的读的属性
-writefds: 检测文件描述符写的集合;
-exceptfds: 检测发生异常的文件描述符的集合
-timeout:设置的超时时间
	struct timeval{
			long tv_sec;
			long tv_usec;
	}
	- null: 永久阻塞,直到检测到文件描述符有变化
	- tv_sec = 0 tv_usec = 0,不阻塞
	- tv_sec > 0 tv_usec > 0,阻塞对应的时间
- 返回值
    - -1: 失败
    - n: 检测集合中有n个文件描述符发生了变化

void FD_CLR(int fd, fd_set* set);
//将参数文件fd对应的set中的地方置为0;
int FD_ISSET(int fd, fd_set* set);
void set(int fd, fd_set* set);
void FD_ZERO(fd_set * set);

缺点:

  • 每次调用select 都要把fd 集合从用户态拷贝到内核态;
  • 每次调用select 都需要在内核遍历传递进来的所有fd,开销很大;
  • select 支持的文件描述符数量太小了;
  • fds集合不能复用,每次都需要重置;

poll:

struct pollfd{
 int fd; // 委托检测的文件描述符
 short events; // 委托内核检测什么事件
 short revents; // 文件描述符实际发生的事件
};
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- fds 是一个struct pollfd的结构体数组,需要检测的集合;
- nfds 这是第一个参数数组中最后一个有效元素的下标
- timeout
- 返回值:
- 	-1 失败
-   > 0(n) 检测到集合中有n个发生变化;

epoll:

// 需要检测的文件描述符(红黑树),还有就绪链表,存放检测到的文件信息(双链表)
int epoll_create(int size);
- 返回值:
- 	-1 失败
-  >0 文件描述符

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *even);
- epfd: epoll 实例对应的文件描述符
- op: 需要什么操作:
- 		EPOLL_CTL_ADD
- 		EPOLL_CTL_MOD
- 		EPOLL_CTL_DEL
- fd:
- event : 检测文件描述符的什么动作

struct epoll_event{
	uint32_t events;
	epoll_data_t data;	
};
常见的epoll 检测事件:
 -EPOLLIN
 -EPOLLOUT
 -EPOLLERR
 
typedef union epoll_data{
	void *ptr;
	int fd;
	uint32_t u32;
	uint32_t u64;
}epoll_data_t;

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
- epfd: 对应的文件描述符
- events: 传出参数,保存变化了的文件描述符的信息;
- maxevents: 第二参数的大小
- timeout: 阻塞时间
- 返回值:
- 	-1 是失败
-   >0 是改变的个数

两种模式:
LT(水平触发):支持非阻塞和阻塞。内核会告诉文件描述符是否就绪,如果不做操作,还是会继续通知。

假设委托内核检测读事件 -> 检测fd 的读缓冲区
	读缓冲区有数据 -> epoll 检测到了会给用户通知
		a. 用户不读,数据一直在缓存区,epoll会一直通知
		b. 用户读一部分,epoll会一直通知
		c. 缓冲区数据读完,不通知

ET(边沿触发):只能支持非阻塞,只会发送一场通知。描述符从未就绪到就绪时,会通知,但是如果不对fd做IO 内核不会再次发送通知。

假设委托内核检测读事件 -> 检测fd 的读缓冲区
	读缓冲区有数据 -> epoll 检测到了会给用户通知
		a. 用户不读,数据一直在缓存区,epoll下次检测就不通知
		b. 用户读一部分,epoll下次检测就不通知
		c. 缓冲区数据读完,epoll下次检测就不通知

ET很大程度上减少了epoll 事件被触发的次数,效率比LT 要高。但是必须要使用非阻塞的套接口,以防止文件描述符饿死。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值