Web服务器记录——前置知识(一)

本文介绍了IO在数据准备和读写阶段的阻塞与非阻塞、同步与异步概念,并详细讲解了IO多路复用技术中的select、poll和epoll。此外,探讨了Reactor和Proactor两种事件处理模式在服务器中的应用,阐述了它们在主线程与工作线程分工上的区别。
摘要由CSDN通过智能技术生成

IO相关概念

IO在处理数据的时候可以分为两个阶段:数据准备阶段,数据读写阶段。根据IO在数据准备阶段的行为可以分为阻塞,非阻塞两种。
根据IO在数据读写阶段的行为可以分为同步,异步两种。

阻塞:

在等待数据时数据没来,调用IO方法的线程将进入挂起状态,系统一般默认IO都是阻塞状态。如在调用read,send方法时系统在该语句处等待数据到来。

非阻塞:

在等待数据时数据没来,不会改变线程状态,会根据当前数据状况直接返回一个值。一般通过fcntl系统调用更改设置。

同步:

在数据读写时需要由用户层自己操作整个读写过程,用户进程会阻塞直到数据读写完毕。

异步:

数据的读写是由内核操作完成,内核在数据读写完毕之后通知用户进程即可。
可以看出异步IO是一个非阻塞IO,而同步IO可以设置为阻塞IO用户进程忙等,也可以设置为非阻塞IO不断去轮询查看数据来了没有。这样看上去同步IO模型不是轮询就是忙等,效率似乎很低下。这时候就要搭配IO多路复用技术一起使用,简单来说就是在一个进程了同时监听多个IO口,这样cpu资源浪费就不会那么严重。

IO多路复用技术

select

 思想:
 1.构建一个文件描述符表,将要监听的文件描述符添加进去
 2.调用系统函数,描述符进行了IO操作之后 ,函数返回【该函数阻塞】
 3.返回时,通知进程有多少描述符进行了IO操作
缺点:
1.构建的文件描述符表每次都要从用户态拷贝到内核里去【消耗资源】
2.大小有限制,而且每次检测是否发生了读写事件需要线性遍历这个表
3.不可重用,这个描述符表在内核会被重置,没有发生事件置0。

poll

poll与select基本一样,但大小没有限制,而且在相应的结构体中引进变量revents来表明发生事件,检测文件描述符数组不变,每次只需恢复revents即可可重用。

epoll

1.epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样只需拷贝一次。
2.内部由一棵红黑树管理所有监听文件描述符,效率提高
3.读写事件发生时会将相应的事件存放到一个结构体中,不用遍历所有描述符

事件处理模式

事件处理模式决定了整个代码的框架与运行逻辑

Reactor模式

主线程只负责监听文件描述符上是否有实际事件发生,有事件发生则立即通知工作线程,将可读可写事件放入请求队列【传入套接字描述符即可】,由工作线程处理【接收连接,读写数据,处理客户请求】。

流程:
	1.主线程往epoll内核事件表注册socket读就绪事件
    2.主线程调用epoll_wait等待socket上有数据可读
    3.有数据时,epoll_wait通知主线程。主线程将socket可读事件放入请求队列
    4.请求队列中的工作线程被唤醒,从socket读取数据,处理客户请求,往epoll注册写就绪事件
    5.主线程调用epoll_wait()等待socket可写
    6.socket可写时,epoll_wait通知主线程。主线程将可写事件放入请求队列
    7.工作线程被唤醒,往socket写入服务器处理结果

Proactor模式

将所有IO操作都交给主线程和内核处理,工作线程只负责业务逻辑

流程:
   1.主线程调用aio_read向内核注册读完成事件,用信号捕捉
   2.主线程处理其他逻辑
   3.数据被读入用户缓冲区后,选择工作线程处理客户请求
   4.请求处理完毕后,调用aio_write注册写完成事件,用信号捕捉
   5.主线程处理其他逻辑
   6.用户缓冲区数据写完毕之后,选择工作线程处理善后工作

Reactor与Proactor的区别主要在于 主线程与工作线程的分工
Reactor:主线程监听,工作线程处理IO以及业务逻辑
Proactor:将IO处理工作由主线程负责,IO操作完毕后,由工作线程处理业务逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值