Golang Go语言中的网络轮询器疑惑?

发布于 1周前 作者 wuwangju 来自 Go语言

最近我在看 Go 的网络轮询器相关文章时,从源码看到 netpollinit 是通过 nonblockingPipe() 创建读写管道 来中断 epollwait ,为什么同样是 Linux 下不使用 eventfd 唤醒事件?有什么原因吗?

https://github.com/golang/go/blob/master/src/runtime/netpoll.go

func netpollinit() {
	epfd = epollcreate1(_EPOLL_CLOEXEC)
	if epfd < 0 {
		epfd = epollcreate(1024)
		if epfd < 0 {
			println("runtime: epollcreate failed with", -epfd)
			throw("runtime: netpollinit failed")
		}
		closeonexec(epfd)
	}
	r, w, errno := nonblockingPipe()
	if errno != 0 {
		println("runtime: pipe failed with", -errno)
		throw("runtime: pipe failed")
	}
	ev := epollevent{
		events: _EPOLLIN,
	}
	*(**uintptr)(unsafe.Pointer(&ev.data)) = &netpollBreakRd
	errno = epollctl(epfd, _EPOLL_CTL_ADD, r, &ev)
	if errno != 0 {
		println("runtime: epollctl failed with", -errno)
		throw("runtime: epollctl failed")
	}
	netpollBreakRd = uintptr(r)
	netpollBreakWr = uintptr(w)
}

// netpollBreak interrupts an epollwait. func netpollBreak() { if atomic.Cas(&netpollWakeSig, 0, 1) { for { var b byte n := write(netpollBreakWr, unsafe.Pointer(&b), 1) if n == 1 { break } if n == -_EINTR { continue } if n == -_EAGAIN { return } println(“runtime: netpollBreak write failed with”, -n) throw(“runtime: netpollBreak write failed”) } } }


Golang Go语言中的网络轮询器疑惑?

更多关于Golang Go语言中的网络轮询器疑惑?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

我不敢说这就是原因,只作为猜测:
1. pipe 和 event 都可以实现功能
2. pipe 每次只需要 write 1 字节,而 eventfd 每次必须写入大于等于 8 字节、相比之下浪费

更多关于Golang Go语言中的网络轮询器疑惑?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


内核版本要求吧,不然 eventfd 应该是更好的选择

在Go语言中,网络轮询器(network poller)是实现高效I/O操作的关键组件之一,它基于操作系统的底层机制,用于监控文件描述符(如网络连接)的状态变化,从而避免传统的阻塞式I/O带来的性能瓶颈。

Go语言的运行时系统(runtime)内置了对网络轮询器的支持,它使用了epoll(在Linux上)和kqueue(在BSD系统上,包括macOS)等高效的系统调用。这些系统调用允许一个进程同时监控多个文件描述符,当其中任何一个描述符的状态发生变化(如可读、可写或有错误发生)时,系统通知进程进行处理。

在Go中,当你使用net包中的网络功能(如TCP/UDP套接字)时,底层会自动利用这些系统调用和轮询机制。例如,当你创建一个TCP连接并调用Read方法时,如果当前没有数据可读,Go的运行时会将该连接的文件描述符添加到轮询器中,并等待系统通知。一旦有数据可读,轮询器就会触发,Go的运行时再将控制权交回给你的Read方法,从而完成数据的读取。

这种机制使得Go语言能够高效地处理大量的并发网络连接,而不会导致单个线程或进程被阻塞。因此,对于需要处理大量I/O操作的服务器应用来说,Go语言是一个非常好的选择。

希望这能帮助你理解Go语言中的网络轮询器。如果你还有其他问题或疑惑,请随时提问。

回到顶部