V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
josephxrays
V2EX  ›  Go 编程语言

Go 的网络轮询器疑惑?

  •  
  •   josephxrays ·
    josexy · 2022-04-03 22:06:00 +08:00 · 2080 次点击
    这是一个创建于 752 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近我在看 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")
    		}
    	}
    }
    
    
    3 条回复    2022-04-05 09:54:52 +08:00
    lesismal
        1
    lesismal  
       2022-04-03 23:01:58 +08:00
    我不敢说这就是原因,只作为猜测:
    1. pipe 和 event 都可以实现功能
    2. pipe 每次只需要 write 1 字节,而 eventfd 每次必须写入大于等于 8 字节、相比之下浪费
    nuk
        2
    nuk  
       2022-04-04 01:21:48 +08:00
    内核版本要求吧,不然 eventfd 应该是更好的选择
    mengzhuo
        3
    mengzhuo  
       2022-04-05 09:54:52 +08:00
    主要考虑是 netpollBreak

    https://github.com/golang/go/issues/27707
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3253 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:43 · PVG 20:43 · LAX 05:43 · JFK 08:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.