【发布时间】:2016-07-29 05:09:47
【问题描述】:
关于我为什么要问这个问题的一些背景知识。几个小时前我问了这个问题
When a goroutine blocks on I/O how does the scheduler identify that it has stopped blocking?
有答案
所有的 I/O 都必须通过系统调用完成,而在 Go 中实现系统调用的方式,总是通过运行时控制的代码调用。这意味着当您调用系统调用时,而不是直接调用它(从而将线程的控制权交给内核),运行时会收到您想要进行的系统调用的通知,并代表 goroutine 执行此操作。例如,这允许它执行非阻塞系统调用而不是阻塞系统调用(本质上是告诉内核,“请执行此操作,但不要在完成之前阻塞,而是立即返回,并在结果后通知我准备好了”)。这允许它在此期间继续做其他工作。
所以据我了解,golang 调度程序所做的是确保不会在等待 I/O 操作的线程上花费时间。相反,它以某种方式将这一责任推给了内核。
但是,我想更深入地了解这个过程,因为有很多事情我不清楚。
目前这是我的理解,可能完全错误。
- 向 goroutine 中的远程服务器发出 I/O 请求,例如 GET 请求
- Golang 进行系统调用以读取 TCP 流,这是一个阻塞操作,但它不是等待,而是要求内核在获得信息时得到通知。调度器从它的队列中移除那个阻塞的 goroutine
- 内核获得所有信息后,会将其转发给 go 进程,并让调度程序知道将 goroutine 添加回其队列。
我很难理解的是如何在不创建另一个线程的情况下完成 I/O 操作,以及内核如何真正“知道” I/O 操作是如何完成的。是通过轮询还是有某种中断系统?
我希望这有点道理。我对这么低级别的概念很陌生。
【问题讨论】:
标签: multithreading asynchronous go io kernel