网络IO模型

目录

网络IO过程

5种网络IO模型

Linux下3种IO复用模型


网络IO过程

在网络通信中,数据最先抵达底层的网卡中,由于安全性考虑,只有内核能直接与底层硬件通信,所以数据会先从网卡复制到内核缓冲区,再复制到用户空间供用户进程使用,

缓冲区是为了避免频繁硬件IO(得中断),可积累一定数据再批量处理

所以网络IO可以分为两个阶段:

  • 数据准备阶段: 用户发送的数据经过网络传输到达网络,然后内核将它们复制到缓冲区里
  • 数据复制阶段:应用从缓冲区里把数据复制到用户空间

5种网络IO模型

阻塞IO:数据准备、数据复制阶段全部阻塞,如下图所示

非阻塞IO:数据准备阶段不阻塞,而是不断轮询数据是否准备完毕,然后数据复制阶段阻塞,如下图所示

 

IO多路复用:通过一个系统调用,让内核监视多个网络IO事件(文件描述符),一旦就绪(数据抵达内核缓冲区),就通知进程进行系统调用来读写(内核->用户进程)

  • 让一个线程同时负责多个socket fd的IO操作
  • 数据准备、数据复制阶段全部阻塞

信号驱动式IO:数据准备阶段通过信号机制实现异步,数据复制阶段阻塞

异步IO:数据准备、数据复制阶段都不阻塞,相当于等内核把事都干完自己再去处理数据

对比

 阻塞IO非阻塞IOIO复用信号驱动式IO异步IO
数据准备阶段阻塞不阻塞,轮询阻塞不阻塞,异步不阻塞,异步
数据复制阶段阻塞阻塞阻塞阻塞不阻塞,异步
优点不占CPU时间实时性好,当数据准备完成后立刻开始复制一个线程负责监控多个网络IO事件 非阻塞
缺点一个线程对应一个socket连接占CPU,不断轮询同步、阻塞 需要底层内核提供支持

 

Linux下3种IO复用模型

IO复用让一个进程阻塞在select, poll, epoll系统调用上,让内核监视多个文件描述符,一旦就绪(数据抵达内核缓冲区),就通知进程进行读写(内核->用户进程)

select

#define FD_SETSIZE 1024
struct fd_set{
	//每一位表示一个文件描述符,
	//容量数目由FD_SETSIZE确定,所以处理的文件描述符数目受到了限制
	long int fds_bits[FD_SETSIZE/sizeof(long int)];//所以可以监测FD_SETSIZE个
};

int select(int nfds,fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeout);
	nfds: select监听的最大文件描述符值+1
	timeout: select的超时时间,-1表示阻塞
	返回值: 就绪的文件描述符的总数

为什么默认监控大小是1024?  因为进程拥有的文件描述符上限是1024(ulimit -n 数目,修改) 

poll

struct poll_fd{
	int fd; 
	short events; //注册的事件,监听该文件描述符上的哪些事件
	short revents; //实际发生的事件
};

int poll(poll_fd *fds, int nfds, int timeout);	

 select和poll区别:

  • select能处理的文件描述符数受限,定长数组,默认1024,可修改;poll基于链表存储,不受限制
  • select用数组位置表示fd编号,poll直接存储fd值

epoll

    用一组函数完成任务,将用户关心的文件描述符的事件放在内核中的事件表(得额外一个文件描述符来标识),
        不像select,poll每次调用都要传入描述符集合、事件集合(复制到内核)

struct epoll_event{
	uint32 events;
	data; //union类型,可作为fd
};


//内核创建事件表:一个红黑树(存储注册事件),返回其描述符
//还创建一个就绪事件的双向链表
int epoll_create(int size);

//操作内核事件表
//向红黑树中插入事件、向内核注册回调函数,中断时向双向链表插入数据(事件发生时加入链表)
int epoll_ctl(int op,int fd, epoll_event *event);
	op操作类型:注册、修改、删除fd上的事件
	fd: 要操作的文件描述符
	event: 指定事件

//等待事件就绪并返回,查看就绪链表
int epoll_wait(int epfd, epoll_event *events, int maxevents, int timeout);
	events: 就绪的事件会被复制到该值中
	maxevents: 最多监测多少个事件

水平触发、边缘触发
        水平触发允许 暂时不对就绪事件处理,下次会继续提醒;
        而边缘触发则要求必须处理就绪事件,下次不会提醒,不会重复触发事件,效率高

创建一个epoll时

  • 在epoll文件系统中创建一个文件
  • 创建一个红黑树,存所有注册事件的文件描述符socket
  • 创建一个list链表,存放就绪事件

epoll的优势

  1. epoll将事件表放在内核,减少了描述符列表、事件列表在内核空间、用户空间的频繁复制,且只需要注册一次,不像它俩每次调用都得移动一次
  2. epoll返回就绪的事件,不需要遍历所有监测描述符
  3. 没有连接数目限制

同步和异步:调用函数后是否得等待调用结果才返回,指通信方式

阻塞、非阻塞:指等待调用结果时程序的状态,是挂起还是不挂起

 

 

 

学习自       

Linux高性能服务器编程

UNIX网络编程 卷1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值