您的位置: 网站首页> 大家问> 当前文章

Linux 内核 IO 模型的概念

老董2024-03-28186围观,145赞

  1、阻塞 IO:最传统的一种 IO 模型,在读写数据过程中会发生阻塞。当用户线程发出 IO 请求后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,当数据就绪之后,内核会将数据拷贝到用户线程,并返回 IO 执行结果给用户线程,用户线程解除阻塞状态并开始处理数据。

  2、非阻塞 IO:当用户线程发起 IO 请求后并不需要等待,即使内核数据还没有准备好也会马上得到内核返回的一个结果,用户线程可以之后再次询问内核。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么内核就将数据拷贝到用户线程并通知用户线程。在非阻塞 IO 中,用户线程需要不断询问内核数据是否准备就绪,在数据未就绪时可以处理其他任务。

  3、多路复用 IO:在多路复用 IO 模型中会有一个 Selector 线程不断轮询多个 Socket 的状态,只有当 Socket 真正有读写事件时才通知用户线程进行实际的 IO 读写操作。阻塞 IO 和 非阻塞 IO 模型需要为每个 Socket 建立一个单独的线程处理数据,而多路复用 IO 只需要一个线程管理多个 Socket,并且只在真正有读写事件时才会使用操作系统的 IO 资源,大大节约了系统资源。在非阻塞 IO 中不断询问 Socket 状态是通过用户线程进行的,而在多路复用 IO 中轮询每个 Socket 状态是内核在进行的,效率要比用户线程高。对于多路复用 IO 模型来说在事件响应体很大时,Selector 线程会成为性能瓶颈,导致后续事件无法及时处理,影响下一轮事件轮询,因此实际应用中方法体内不做复杂逻辑处理,只做数据的接收和转发,而将具体业务操作转发给业务线程处理。对应于 Java 中的 NIO,在 NIO 中通过 selector.select() 去查询每个 Channel 是否有事件到达,如果没有事件到达用户线程会一直阻塞,因此 NIO 也会导致用户线程的阻塞。

  4、信号驱动 IO:当用户线程发起一个 IO 请求操作,会给对应的 Socket 注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用 IO 读写操作来进行实际的 IO 请求操作。一般用于 UDP 中。

  5、异步 IO:当用户线程发起异步 read 操作后,立刻就可以开始去做其它事。另一方面,从内核的角度,当它收到一个异步 read 之后会立刻返回一个状态,说明请求是否成功发起,用户线程不会任何阻塞。然后内核会等待数据准备完成并将数据拷贝到用户线程,完成后内核会给用户线程发送一个信号通知 read 操作已完成。用户线程完全不需要关心实际的整个 IO 操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,就可以直接去使用数据了。在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成,用户线程不需要再次调用 IO 函数进行具体的读写。在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作。

很赞哦!

python编程网提示:转载请注明来源www.python66.com。
有宝贵意见可添加站长微信(底部),获取技术资料请到公众号(底部)。同行交流请加群 python学习会

文章评论

    Linux 内核 IO 模型的概念文章写得不错,值得赞赏

站点信息

  • 网站程序:Laravel
  • 客服微信:a772483200