2 回答
TA贡献1895条经验 获得超3个赞
您可以查看文件https://github.com/golang/go/blob/master/src/net/fd_unix.go(写入函数)。
基本上,这取决于套接字缓冲区是否有足够的空间。
如果套接字缓冲区中有足够的空间来容纳您的写操作的大小,数据将立即写入套接字缓冲区。我想这对应于您的第二个答案。此外,内核实际上可能会发送数据包(或将其添加到 NIC 队列),但它独立于 Go 运行时。
如果套接字缓冲区中没有足够的空间来容纳整个写入操作,则只会立即将部分数据写入套接字缓冲区。然后,调用将阻塞(通过运行时轮询引擎),直到内核在套接字缓冲区中留出一些空间(通过发送一些数据包)。只要有一些空间可用,并且所有数据都已复制,呼叫就会解除阻塞。
您应该考虑在 net 包通过系统调用将整个缓冲区写入套接字缓冲区时采用的时间戳。
TA贡献1852条经验 获得超7个赞
在下面的文章介绍了netpoller是如何工作的:
每当 goroutine 尝试读取或写入连接时,网络代码将执行操作,直到收到此类错误,然后调用 netpoller,告诉它在准备再次执行 I/O 时通知 goroutine。然后 goroutine 被调度到它正在运行的线程之外,另一个 goroutine 在它的位置运行。
当 netpoller 收到来自 OS 的通知,它可以对文件描述符执行 I/O 时,它会查看其内部数据结构,查看是否有任何 goroutine 在该文件上被阻塞,如果有,则通知它们。然后 goroutine 可以重试导致它阻塞的 I/O 操作并成功执行此操作。”
因此我们得出结论,只要底层系统调用完成对整个缓冲区的写入,就可以重新调度 goroutine。在 Linux 的情况下,当消息被复制到内核空间发送缓冲区时似乎是蜜蜂:阻塞套接字:确切地说,“send()”何时返回?. 这又是我的第二个原始选项“当缓冲区被复制到运行时和操作系统的内核空间时”。
- 2 回答
- 0 关注
- 224 浏览
添加回答
举报