阻塞 & 非阻塞 | 同步 & 异步
这里讲的都是基于IO的
阻塞、非阻塞、同步、异步
一个典型的IO操作包括了两个阶段,==数据准备和数据读写==。比如说现在要使用 recv 执行一个读操作,数据就绪就是远端是否有数据可读。
当IO工作在阻塞状态下的时候,如果数据没有就绪,recv就会阻塞当前线程;如果说IO工作在非阻塞状态下,会立即返回。返回值-1的话,就说明连接出现问题,连接异常;如果返回值是0,且errno是EAGIN的话,就说明这是一个正常的非阻塞,返回数据未就绪状态。如果数据就绪,recv会继续把数据从内核TCP缓冲区拷贝到传入recv的buf应用程序缓冲区中。在拷贝过程中,应用程序会一直等待这个过程结束才返回。
如果是异步,在传入sockfd和buf之外,还要传入通知方式,告诉操作系统的异步IO负责监听这个sockfd是否有数据可读,如果有,有操作系统将数据拷贝到buf中,并通知应用程序。
一个==同步IO==接口的示例:
char buf[1024];
int sz = recv(sockfd,buf,1024,0);
//阻塞:一直在这儿死等
//非阻塞:时不时的回来问一下
if(sz>0){
//在上面的数据没有读取完成之前,是不会进入到这里的
}
如果说异步,就是同步的反面,那也能说得通。
异步操作会告诉内核,我对这个事件感兴趣,事件发生的时候你通知我一声儿就好了,我还忙着呢,没空搁这儿等你。
==通知,通知,通知==,重要的事说三遍!!!
这是异步最大的标识。
比如说信号,比如说回调。
异步IO接口:
#include <aio.h>
int aio_read(struct aiocb *aiocbp);
int aio_write(struct aiocb *aiocbp);
#include <aiocb.h>
struct aiocb {
/* 下面所有字段依赖于具体实现 */
int aio_fildes; /* 文件描述符 */
off_t aio_offset; /* 文件偏移 */
volatile void *aio_buf; /* 缓冲区地址 */
size_t aio_nbytes; /* 传输的数据长度 */
int aio_reqprio; /* 请求优先级 */
struct sigevent aio_sigevent; /* 通知方法 */
int aio_lio_opcode; /* 仅被 lio_listio() 函数使用 */
/* Various implementation-internal fields not shown */
};
陈硕大神说:==在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO==。
epoll也属于同步IO。
五种IO模型
阻塞:
非阻塞:
多路IO复用
信号驱动:
这里就完全放飞自我了
异步:
Reactor反应堆模型
One loop per thread is usually useful。 – libev作者
reactor中的重要组件:Event事件、Reactor反应堆、Demultlplex事件分发器、Evanthandler事件处理器。
图片来自网络,看图说话。
本次不足
对于异步IO操作,始终还是停留在了解的层面,还没真正去写过代码。
- 点赞
- 收藏
- 关注作者
评论(0)