IO同步与异步

 公众号:I/O异步与同步

        我们的程序,如果要对I/O设备进行操作,比如通过一个socket发送数据,文件的读写,是怎么实现的呢? 要知道,为了保证系统安全以及抽象化(避免每个进程都需要对IO设备进行编码),进程是无法直接操作I/O设备的,必须通过系统调用请求Kernal来协助完成I/O操作。
        而在冯诺依曼架构下,I/O操作往往特别慢,为了降低延迟,提高吞吐量以及数据处理速率,内核就会为在内核空间每个I/O设备维护一个buffer。这样,进程对内核请求时,数据都通过内核buffer来交互,而内核与I/O交互过程中,I/O设备响应可能很慢,所以内核必须等待IO设备将数据复制到内核空间中。

        这样,数据从I/O设备复制到内核空间,内核需要进行一次等待,进程从内核buffer中获取数据,在内核缓冲区准备好之前,进程也需要一次等待。根据等待模式的不同,I/O模式分为五种:

  • 阻塞I/O (blocking I/O)

  • 非阻塞I/O (nonblockong I/O)        

  • I/O复用 I/O (multiplexing)       

  • 信号驱动I/O (signal driven I/O)

  •  异步I/O (Asynchronous I/O) 

  1. 阻塞I/O

      阻塞I/O执行的系统调用可能因为无法立刻完成,导致被请求的进程被系统挂起,直到I/O完成为止。比如,connect发起连接时,connect首先发送同步报文给服务器,等待服务器返回确认报文。如果服务器的确认报文没有立即到达,connect调用被系统挂起,直到客户端收到确认报文并唤醒connect调用。

  2. 非阻塞I/O

      非阻塞I/O允许进程在请求 I/O 操作后,如果数据未准备好,立即得到一个错误返回,根据errno,通常是EWOULDBLOCK 或 EAGAIN,对connect来说,errno被设置为EINPROGRESS。这样,进程可以继续执行其他任务,不必阻塞等待 I/O 操作完成。

  3. I/O复用
     I/O复用允许单个进程同时等待多个I/O操作中的任何一个完成。通常通过 select(), poll(), 或 epoll() 系统调用实现。进程阻塞在这些调用上,直到一个或多个 I/O 操作完成,从而有效地监听多路 I/O 资源而不是只关注单一资源。

  4. 信号驱动 I/O(Signal-driven I/O)
      信号驱动 I/O 模式中,进程可以继续执行,直到内核某个时刻准备好数据并通过发送信号通知进程。这种模式下,进程不需要在调用期间阻塞,也无需频繁检查数据是否可用。比较适合事件驱动模式,减少轮询开销。

  5. 异步I/O(noblocking all the way(signal when I/O is completed)

      异步 I/O 模式下,进程发起 I/O 操作后可以立即执行后续指令,不需等待 I/O 操作的完成。内核会在整个 I/O 操作完成后通知进程,这包括数据从 I/O 设备复制到内核缓冲区,以及从内核缓冲区复制到进程缓冲区的过程。如windows的IOCP模式。

总结
        可以看出,IO操作的时候,进程可以等待IO操作完成(同步),也可以不等待IO完成直到内核完成后通知进程(异步),这就是同步和异步的区别。同步模型中,进程可以阻塞等待IO完成,也可以不阻塞而是通过轮询(如select)或者事件监听(如epoll)的方式来判断IO是否完成。
        当然,也可以通过数据从内核空间到用户空间的拷贝,是操作系统自己完成的,还是进程来操作,来判断是同步还是异步。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值