socket阻塞与非阻塞、同步与异步概念

来源:互联网 发布:mac电脑如何新建文件夹 编辑:程序博客网 时间:2024/06/03 15:59

看了不少文章,发现socket阻塞、非阻塞、同步、异步概念讲的比较混乱,甚至混用比如非阻塞和异步。

看了Unix网络编程 五种I/O模型 感觉讲的比较清晰,现总结下,方便自己记忆理解。本人菜鸟一枚,如果哪里说得有误欢迎拍砖指正,在此谢过。

阻塞与非阻塞





阻塞与非阻塞IO区别在于应用进程的调用是否立即返回。

对于阻塞IO当应用进程调用IO函数,如果数据没有准备好,将一直等待(睡眠),直到数据准备好唤醒进程;

非阻塞IO:进程会反复调用(当然是进程根据是否返回EWOULDBLOCK while轮询)IO函数并马上返回,但数据从内核拷贝到用户进程空间进程是阻塞的。当请求的IO操作无法完成时,进程不会睡眠,而是IO操作函数返回一个错误,这样进程就可以据此不断测试数据是否准备好了,直到准备好为止。这个不断测试的过程中,会占用大量cpu时间,如图6.2所示。非阻塞IO类似于自旋锁,不断忙轮询

同步异步:


同步异步的区别在于:数据从内核拷贝到用户进程空间,进程是否阻塞。

真正的异步只有AIO,其他的都为同步,包括多路IO复用。数据拷贝到用户进程后会通知进程,进程在拷贝期间无需阻塞可以继续处理其他逻辑。


多路IO复用:

多路IO复用也是同步的,跟单个阻塞IO比并没有什么优越性,但当IO较多时就体现效果了,主要是它能同时对多个IO进行监听。

目前流行的服务器开发模式是one  thread per loop&non-blocking,之前一直有个疑问:既然select、poll等可以监测IO是否可读写、异常,

那IO还要设置为非阻塞干嘛? select 只能说明 socket 可读或者可写,不能说明能读入或者能写出多少数据。比如,socket 的写缓冲区有 10 个字节的空闲空间,这时监视的 select 返回,然后在该 socket 上进行写操作。但是如果要写入 100 字节,如果 socket 没有设置非阻塞,调用 write 就会阻塞在那里。而更为要紧的是,在多个 socket 的情况下,读写一个socket 时阻塞,会影响到其他的 socket 。题外话:现在的网络库Libevent、muduo对IO都是带读写缓冲区的,用户不会自己去read、write某个socket的,都交给网络库事件循环处理了。


多路IO复用:select、poll、epoll大致比较:

select模型是通过一种轮询机制来实现的。需要注意:

  • Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认32*32=1024. 
  • 操作限制:通过遍历FD_SETSIZE(1024)个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍,这样效率就会呈现线性下降,把FD_SETSIZE改大的后果就是,"大家都慢慢来,什么?都超时了?".
  • 内核/用户空间的信息交换-> 内存拷贝

poll模型与select类似,也是通过轮询来实现,但它与select模型的区别在于Socket数量没有限制。

epoll模型在poll模型的基础之上不使用轮询,而使用基于内核提供的反射模式。

  • 有“活跃Socket”时,内核访问该Socket的callback.
  • 内核/用户空间信息交换->通过共享内存

原创粉丝点击