В целом вы можете думать о сокетах ввода / вывода как о двухуровневой системе буферизации.В вашем приложении есть буфер, а затем - буферы ядра.Поэтому, когда вы вызываете read (), ядро копирует данные из буфера (ов) ядра в буфер вашего приложения.Соответственно, когда вы вызываете write (), вы копируете данные из буфера приложения в буфер (ы) ядра.
Затем ядро говорит NIC записывать входящие данные в буферы ядра и считывать исходящие данные.из буферов ядра.Этот ввод-вывод выполняется AFAIK, как правило, на основе DMA. Это означает, что ядру просто нужно сообщить NIC, что делать, и NIC отвечает за фактическую передачу данных.И когда NIC завершается, он вызывает прерывание (или для высоких скоростей ввода-вывода, прерывания отключаются, а ядро вместо этого опрашивает), в результате чего ядро ЦП, получившее прерывание, перестает выполнять все, что оно выполняло (код пользователя, код ядра(если прерывания отключены, в этом случае прерывание будет поставлено в очередь)) и выполнить обработчик прерываний, который затем позаботится о других шагах, которые необходимо выполнить.
Итак, чтобы ответить на ваш дополнительный вопрос, в общемэто не отдельный ввод / вывод сокета обработки потока ядра на стороне ядра, работа выполняется оборудованием NIC и в контексте прерывания.
Для асинхронного ввода-вывода или, скорее, неблокирующего ввода-вывода,единственное отличие состоит в том, как выполняется копирование из буфера пользовательского приложения и буфера (ов) ядра.Для неблокирующего чтения в пользовательское пространство копируются только те данные, которые готовы и ожидают в буферах ядра (что может привести к короткому чтению), или, если данные не готовы, вызов read () немедленно возвращается с EAGAIN.Точно так же для неблокирующей записи () он копирует только столько данных, сколько имеется доступного пространства в буферах ядра, что может вызвать короткую запись или, если пространство вообще не доступно, при возврате с EAGAIN.Для блокировки read (), если нет доступных данных, вызов будет блокироваться, пока не будет, тогда как для блокирующей write (), если буфер (ы) ядра заполнен, он будет блокироваться, пока не будет доступно некоторое пространство.