2015-08-05 2 views
3

Golangs goroutines представляют собой интерфейс блокировки ввода-вывода для goroutine (-programmer). За кулисами во время выполнения естественно используется какой-то неблокирующий ввод-вывод, чтобы предотвратить приостановку OS-потока ОС, так что среда выполнения может запускать другой goroutine поверх потока ОС при выполнении ввода-вывода.Планирование ввода/вывода Goroutine

Когда выполняется время выполнения ввода-вывода, чтобы он мог перенести goroutine?

Чтобы было ясно, если у меня есть net.TCPConn, на который я звоню Write, когда я могу ожидать, что горутин будет перенесен?

conn, err := net.Dial("tcp", serverAddr) 
conn.Write(buffer) 
timestamp = time.Now() 

То есть, когда я могу ожидать отметки времени?

  • Когда буфер был скопирован во время выполнения golang?
  • Когда буфер был скопирован во время выполнения и в пространство ядра ОС?
  • Когда буфер был скопирован во время выполнения, пространство ядра и дополнительно к буферу отправки NIC?
  • Когда буфер отправлен по сети/из сетевого адаптера?
  • Когда буфер был подтвержден полученным концом TCP-стека?
+1

Эта статья [https://morsmachine.dk/go-scheduler) может быть немного устаревшим, но дает хорошее представление о том, как работает планировщик. – thwd

+1

Perfect !, отведите меня до https://morsmachine.dk/netpoller, который дал мне ответ. – Fredrik

ответ

3

Вы можете посмотреть в файле https://github.com/golang/go/blob/master/src/net/fd_unix.go (Функция записи).

В принципе, зависит от того, имеет ли буфер сокета достаточное пространство или нет.

Если в буфере сокета достаточно места для размещения размера вашей операции записи, данные будут немедленно записаны в буфер сокета. Думаю, это соответствует вашему второму ответу. Кроме того, ядро ​​может фактически отправить пакет (или добавить его в очереди NIC), но он не зависит от времени выполнения Go.

Если в буфере сокетов недостаточно места для размещения всей операции записи, только часть данных будет немедленно записана в буфер сокета. Затем вызов блокирует (через механизм опроса времени выполнения), пока ядро ​​не сделало некоторое пространство в буфере сокета (отправив некоторые пакеты). Как только некоторое пространство будет доступно, и все данные будут скопированы, вызов будет разблокирован.

Следует учитывать, что временная метка берется, когда сетевой пакет записал весь буфер в буфере сокета с помощью системного вызова.

2

following article описывает, как netpoller работы:

Всякий раз, когда goroutine пытается прочитать или записать в связи с этим, сетевой код будет делать операцию до тех пор, пока не получит такую ​​ошибку, а затем вызвать в netpoller, сообщая ему, чтобы уведомить goroutine, когда он готов снова выполнить операции ввода-вывода. Затем goroutine назначается из потока, в котором он работает, и вместо него запускается другой goroutine.

Когда netpoller получает уведомление от ОС о том, что он может выполнять ввод/вывод в файловом дескрипторе, он будет просматривать свою внутреннюю структуру данных, посмотреть, есть ли какие-либо goroutines, которые заблокированы в этом файле, и уведомить их, если любые. Затем goroutine может повторить операцию ввода-вывода, которая заставила его заблокировать и преуспеть в этом."

Таким образом, мы приходим к выводу, что goroutine может быть перенесен, когда основной системный вызов завершает написание для всего буфера. В случае Linux, кажется, пчел, когда сообщение было скопировано в пространство ядра отправить буфер : Blocking sockets: when, exactly, does "send()" return?. Это, в свою очередь, мой второй оригинальный вариант «Когда буфер скопирован во время выполнения и в пространство ядра ОС», также соответствует Didier Spezia's.

Смежные вопросы