muduo 01 阻塞非阻塞,同步异步

目录

阻塞非阻塞,同步异步

总结:什么是阻塞非阻塞、同步异步?


阻塞非阻塞,同步异步

        不管是磁盘IO还是网络IO都包含两个阶段,以网络I/O为例,分为数据准备数据读写。其中数据准备相当于服务器监听客户端有没有数据过来数据读写就是监听到有数据过来了该如何去读取数据?阻塞/非阻塞,同步/非同步分别就是这两种状态下的不同方式的体现。

举recv接口函数的例子说明:

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数说明:

  • sockfd:表示要接收数据的套接字(socket)描述符。
  • buf:指向接收数据的缓冲区的指针。
  • len:表示接收缓冲区的大小,即能够接收的最大字节数。
  • flags:用于指定接收操作的可选标志,例如设置非阻塞接收或处理特殊情况。

返回值说明:

  • 如果成功接收数据,返回接收到的字节数。
  • 如果连接关闭(对于TCP套接字),返回0。
  • 如果发生错误,返回-1,并设置全局变量 errno 表示具体的错误类型。

阶段一:阻塞&非阻塞

        该函数默认是阻塞的,当我调用它的时候如果我的sockfd上没有数据到来,没有数据可读,该函数就不会返回,当前线程就一直阻塞等待sockfd上有数据到来

        如果说在recv之前将我们的sockfd设置为nblock,非阻塞的,如果此时sockfd上没有数据到来,recv函数会直接返回,不会造成当前线程状态的转变,会通过返回值判断状态

 阶段二:同步&异步

        recv中的这个buf是我们自己创建的一块内存,作用就是从操作系统的TCP接收缓冲区将发过来的数据搬过来,recv没有把TCP接收缓冲区中内存搬完之前不会向下执行

        

        异步就不可以用recv介绍了,因为recv是一个同步IO接口。

        

        对于异步IO接口,调用时会向操作系统通知三个东西,一个是我们感兴趣的sockfd,一个是buf,一个是sigio信号,通知操作系统我们对该sockfd感兴趣,判断一下里面是否有数据,有数据放到buf中,放好了再通过sigio信号通知过来。比如linux中的aio_read和aio_write

在处理IO的时候,阻塞跟非阻塞都是同步IO。只有使用了特殊的API才是异步IO。

 业务层面上的一个逻辑处理是同步还是异步?

        同步相当于就是A操作等待B操作做完事情,得到返回值,继续处理。数据读写都是由请求A自己完成的

        异步就是a操作告诉b操作它感兴趣的事件以及通知方式,然后呢a操作继续执行自己的业务逻辑。当b监听到相应事件发生后,b会通知a开始a开始相应逻辑处理。

总结:什么是阻塞非阻塞、同步异步?

        阻塞非阻塞,同步异步啊,它描述的都是IO的一些状态。一个典型的IO分为两个阶段,分别是数据就绪数据读写,数据就绪就是判断远端的数据有没有来,是否准备好了,数据读写是指当这个数据准备好了,对其进行读操作还是写操作。

         数据就绪分为阻塞非阻塞两种状态,阻塞的表现形式就是当前线程会阻塞直到数据准备好,非阻塞的表现形式就是会立刻返回。

        举例说明接收数据的网络编程接口函数recv函数,它默认是一个阻塞同步接口,使用时我传入一个需要接收数据的sockfd、一个存放接收数据的buffer以及它的大小,当这个sockfd工作在默认阻塞状态下,在调用过程中会使当前线程阻塞,等待操作结束;

        当这个sockfd工作在非阻塞状态下调用recv函数会立刻返回,不会更改当前线程状态,可通过返回值进一步判断(大于0表示接收到了一部分数据,可以根据返回数据长度进一步处理和解析、返回值为0对于TCP套接字表示连接关闭对于UDP表示没有数据可接收、返回值为-1表示接收数据出错如果进一步判断errno==EAGAN说明是一个合理的非阻塞模式,需要再次轮询或者等待数据就绪)。   


       数据准备好了开始数据读写,分为同步和异步状态,同步表示A向B请求调用IO接口时,数据的读写都是由请求方A自己来完成的(不管是阻塞还是非阻塞)还以receive例子来说。应用层调用receive这个接口,相当于应用层自己把这个数据从这个内核的TCP接收缓冲区拷贝到我给receive传的buffer中。应用程序从TCP缓冲区当中拷贝数据到我们buffer中。应用程序是一直等待这个数据拷贝完成以后receive才返回的,才能继续向下执行,就是说他是一个顺序执行的过程

        如果是一个异步的接口,A向B请求一个网络IO时,A向B传入请求的时间及事件发生时通知的方式,A事件就可以去处理其他逻辑了,当B监听到事件处理完成后,会用事先约定好的通知方式(信号、回调函数),通知A处理结果。比如说我们调用时需要传一个socket fd,这个是对应的一个TCP缓冲区,从远端接收数据的,还有一个buffer就是我。我要最终如果有数据的话呢,我要把这个内核缓冲区的数据搬到应用程序的每一块儿缓冲区当中,还有一个就是通知方式。操作系统负责帮我监听这个socket fd上是否有数据可读,有的话你帮我把数据从内核的TCP缓冲区搬到我们传入的buffer里边,最后再通过咱俩事先约定好的通知方式来通知应用程序,应用程序就可以处理你这件事情了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值