2017-02-16 27 views
5

Насколько независима обработка UDP отправки и приема в одном и том же сокете в ядре Linux? В моем случае используется рабочий поток, отправляющий тестовый трафик UDP на (до) 1000 сокетов и получающий ответы UDP в другом рабочем потоке. Приемником будет цикл epoll, который также получает аппаратную отправку и получение временных меток в очереди ошибок сокета.UDP отправлять и получать в разных потоках

Чтобы уточнить, при выполнении syscall sendmsg() это временно заблокирует (или сгенерирует EAGAIN/EWOULDBLOCK) в потоке приемника, принимающем в том же сокете? (то есть, если передача и прием происходят с перекрытием во времени). Все сокеты устанавливаются в неблокирующий режим.

Еще один вопрос - гранулярность блокировки в ядре - если я отправляю и получаю с помощью sendmmsg/recvmmsg, является ли блокировка для этого сокета заблокирована один раз на sendmmsg или один раз в UDP-датаграмме в sendmmsg?

ОБНОВЛЕНИЕ: я взглянул на исходный патч для sendmmsg в ядре Linux, кажется, что основное преимущество - избегать многопользовательского пространства переходов. Если какая-либо блокировка выполнена, это, вероятно, выполняется внутри индивидуальных вызовов __sys_sendmsg: https://lwn.net/Articles/441169/

+0

Я должен сказать, что я не ожидал такого прекрасного вопроса, читая название. –

+0

Учитывая, насколько предельно тривиальным UDP, я был бы очень удивлен, если UDP-передача будет мешать UDP-приему. Для TCP скрытая передача ACK и прием, но UDP - это немного больше, чем IP плюс номер порта. – MSalters

+0

@MSalters: Я согласен, отправка и получение довольно независимы. Если у меня есть время, я расскажу о своем обновленном резервном ядре и посмотрю, узнаю ли я больше ничего . –

ответ

0

Каждый системный вызов является независимым от потока. Итак, насколько вы не используете данные ядра процесса, оба будут работать независимо друг от друга, не нарушая друг друга.

Другое дело в том, что ядро ​​делает с системными вызовами, связанными с одним и тем же inode (в данном случае, виртуальным узлом, назначенным для сокета, который вы используете для связи). Чтобы сериализовать и сделать атомарные вызовы в файловой системе, ядро ​​обычно делает блокировку inode во время всего системного вызова (это системный вызов read, write или ioctl), который обозначает весь системный вызов (даже если вы выполняете уникальный вызов записи для записи zillion байтов, inode блокируется во время выполнения всего системного вызова)

В стеке tcp-ip это делается на уровне сокета и управляется в вашем случае конкретным программным обеспечением класса сокетов AF_INET. Как и udp, отправка пакета или приема не влияет на разделяемые ресурсы, которые необходимо заблокировать, но вам придется посмотреть на вашу реализацию udp (или уровень сокета), чтобы увидеть, выполнена ли какая-либо блокировка, и что такое степень детализации , Обычно блокировку следует использовать только во время загрузки/выгрузки буферов udp (обычно нет буферов в udp, так как драйвера сокета и сетевой карты достаточно для обеспечения достаточного количества буферных ресурсов.

+0

'inode' - это структура в файловой системе Unix. Сокет не является 'inode'. Термин, который вы ищете, это «файловый дескриптор». – EJP

+0

@ Luis Colorado, что вы имеете в виду, «как правило, в UDP нет буферов, у вас есть буферизатор в ядре (необходимо настроить, например, для высокоскоростных сокетов (setsockopt SO_SNDBUF)), и у вас есть целое система очередей, которая поступает до кольцевых буферов NIC. –

+0

@ ErikAlapää, да ... но в модуле UDP буферизация не выполняется ... буферизация выполняется в модуле сокета для входящих пакетов и в буфере драйвера для исходящих пакетов. Модуль udp не имеет ресурсов буферизации, поскольку пакеты поступают непосредственно из пользовательского пространства в драйвер. UDP только выбирает, какой драйвер будет хранить пакет, пока драйвер не будет готов к передаче пакета.UDP передает пакеты непосредственно в модуль IP (и IP к драйверу) без буферизации. –