go语言网络轮询器

go语言网络轮询器

网络轮询器不仅用于监控网络 I/O,还能用于监控文件的 I/O,它利用了操作系统提供的 I/O 多路复用模型来提升 I/O 设备的利用率以及程序的性能。

go语言在网络轮询器中使用I/O多路复用模型处理I/O操作,但是他没有选择常见的系统调用select。虽然select也可以提供I/O多路复用的能力,但是使用它有比较多的限制:

  • 监听能力有限——最多只能监听1024个文件描述符;
  • 内存拷贝开销大——需要维护一个较大的数据结构存储文件描述符,该结构需要拷贝到内核中;
  • 时间复杂度O(n)——返回准备就绪的事件个数后,需要遍历所有的文件描述符;

为了提高 I/O 多路复用的性能,不同的操作系统也都实现了自己的 I/O 多路复用函数,例如:epoll、kqueue 和 evport 等。Go 语言为了提高在不同操作系统上的 I/O 操作性能,使用平台特定的函数实现了多个版本的网络轮询模块:

如果目标平台是 Linux,那么就会根据文件中的 // +build linux 编译指令选择 src/runtime/netpoll_epoll.go 并使用 epoll 函数处理用户的 I/O 操作。

接口

epoll、kqueue、solaries 等多路复用模块都要实现以下五个函数,这五个函数构成一个虚拟的接口:

func netpollinit()
func netpollopen(fd uintptr, pd *pollDesc) int32
func netpoll(delta int64) gList
func netpollBreak()
func netpollIsPollDescriptor(fd uintptr) bool

上述函数在网络轮询器中分别扮演了不同的作用:

  • runtime.netpollinit — 初始化网络轮询器,通过 sync.Once 和 netpollInited 变量保证函数只会调用一次
  • runtime.netpollopen — 监听文件描述符上的边缘触发事件,创建事件并加入监听;
  • runtime.netpoll — 轮询网络并返回一组已经准备就绪的 Goroutine,传入的参数会决定它的行为;
    • 如果参数小于 0,无限期等待文件描述符就绪;
    • 如果参数等于 0,非阻塞地轮询网络,直接返回glist;
    • 如果参数等于 0,非阻塞地轮询网络;
  • runtime.netpollBreak — 唤醒网络轮询器,例如:计时器向前修改时间时会通过该函数中断网络轮询器;
  • runtime.netpollIsPollDescriptor — 判断文件描述符是否被轮询器使用;

数据结构

操作系统中 I/O 多路复用函数会监控文件描述符的可读或者可写,而 Go 语言网络轮询器会监听 runtime.pollDesc 结构体的状态,该结构会封装操作系统的文件描述符:

posted @   每天提醒自己要学习  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示