阻塞和非阻塞
同步阻塞IO
在应用调用recvfrom读取数据时,其系统调用直到数据包到达切被复制到应用缓冲区中或者发送错误时才返回,在此期间一直会等待,进程从调用到返回这段时间内都是被阻塞的成为阻塞IO;
步骤
- 应用进程向内核发起recfrom读取数据。
- 准备数据报(应用进程阻塞)。
- 将数据从内核复制到应用空间。
- 复制完成后,返回成功提示。
同步非阻塞IO
非阻塞IO是在应用调用recvfrom读取数据时,如果该缓冲区没有数据的话,就会直接返回一个EWOULDBLOCK错误,不会让应用一直等待中。在没有数据的时候会即刻返回错误标识,那也意味着如果应用要读取数据就需要不断的调用recvfrom请求,直到读取到它数据要的数据为止
步骤:
- 应用进程向内核发起recvfrom读取数据。
- 没有数据报准备好,即刻返回EWOULDBLOCK错误码。
- 应用进程向内核发起recvfrom读取数据。
- 已有数据包准备好就进行一下 步骤,否则还是返回错误码。
- 将数据从内核拷贝到用户空间。
- 完成后,返回成功提示。
IO复用模型
进程通过将一个或多个fd传递给select,阻塞在select操作上,select帮我们侦测多个fd是否准备就绪,当有fd准备就绪时,select返回数据可读状态,应用程序再调用recvfrom读取数据。
模型思想:
普通的IO模型每一个请求都需要一个线程处理,并且这个线程需要不断的询问cpu是否有数据可读。并发量高的情况下浪费资源。
IO复用模型由一个线程监控多个网络请求,这样就可以只需要一个或几个线程就可以完成数据状态询问的操作,当有数据准备就绪之后再分配对应的线程去读取数据,这么做就可以节省出大量的线程资源出来
信号量驱动IO模型
首先开启套接口信号驱动IO功能,并通过系统调用sigaction执行一个信号处理函数,此时请求即刻返回,当数据准备就绪时,就生成对应进程的SIGIO信号,通过信号回调通知应用线程调用recvfrom来读取数据。
模型思想
IO复用模型需要select线程不断询问,select线程会阻塞直到有fd就绪。
信号量驱动IO模型是当内核数据准备好之后,再通过SIGIO信号主动通知线程数据,当线程收到可读状态的信号后,此时再向内核发起recvfrom读取数据的请求。这样不需要select不断询问,节省资源,select线程也不会阻塞。
异步IO
应用告知内核启动某个操作,并让内核在整个操作完成之后,通知应用,这种模型与信号驱动模型的主要区别在于,信号驱动IO只是由内核通知我们合适可以开始下一个IO操作,而异步IO模型是由内核通知我们操作什么时候完成。
模型思想
同步io模型总是先询问,等fd就绪后然后去读取数据
异步io,当发出读取数据请求的时候,立即返回,等内核将数据复制好了在通知用户。这样数据复制和用户线程就同时进行,达到异步的效果,提高效率。
参考
【Networkk】一篇文章完全搞清楚 scoket read/write 返回码、阻塞与非阻塞、异常处理 等让你头疼已久的问题 - junneyang - 博客园