Socket套接字编程(I/O模型)


阻塞I/O

当上层应用调用recv系统调用时,如果对方没有发送数据(缓冲区没有数据),上层应用将被Linux内核阻塞(默认行为)。当对方发送了数据,linux内核套接字缓冲区有数据后,内核会把数据copy给用户空间。然后上层应用解除阻塞,执行下一步操作。

非阻塞I/O

上层应用程序将套接字设置成非阻塞模式。轮询调用recv函数来接收数据。若缓冲区没有数据,上层应用程序不会阻塞,recv返回值为-1,错误码是EWOULDBLOCK。

但在不断轮询的过程中,会造成上层应用程序忙等待,大量消耗CPU。应用范围小,该模型一般与I/O复用配合使用

I/O复用

上层应用程序调用select机制,该机制有linux内核的支持,避免了忙等待,通过轮询文件描述符来观察状态的变化。当select管理的文件描述符没有数据或者状态没有变化时,上层应用程序也会阻塞。

好处:select机制可以管理多个文件描述符,类似于进程池。将select看成一个管理者,用其来管理多个I/O。 一旦检测到的一个I/O或多个IO有事件发生,select函数将返回,返回值为检测到的事件个数。进而利用select相关api函数,操作具体事件。同时select函数还可以设置等待时间,避免了上层应用程序长期僵死。与阻塞I/O模型相比,I/O复用模型相当于提前阻塞了。等到有数据到来时,再调用recv就不会发生阻塞。

信号驱动I/O


上层应用程序建立SIGIO信号处理程序。当缓冲区有数据到来,内核会发送信号告诉上层应用程序。当上层应用程序接收到信号后,调用recv函数,因为缓冲区有数据,recv函数一般不会阻塞。

属于典型的“拉模式”。即上层应用需要调用recv函数把数据拉进来。

异步I/O  

上层应用程序调用aio_read函数,同时提交一个应用层的缓冲区buf;调用完毕后,不会阻塞。上层应用程序可以继续其他任务。当tcpip协议缓冲区有数据时,linux内核主动的把数据copy到用户空间。然后再给上层应用发送信号。

属于典型的“推模式”,是效率最高的一种,上层应用程序具有异步处理的能力(处理其他任务的同时,也可支持I/O通讯)。


猜你喜欢

转载自blog.csdn.net/qq_33506160/article/details/80406567