Unix сетевой процесс - PullRequest
       12

Unix сетевой процесс

2 голосов
/ 09 октября 2009

Мне было интересно, как реализована связь tcp / ip в unix. Когда вы отправляете через сокет, выполняется ли работа tcp / level (сборка пакетов, crc и т. Д.) В том же контексте выполнения, что и вызывающий код?

Или, что кажется более вероятным, сообщение отправляется другому процессу-демону, отвечающему за tcp-связь? Затем этот процесс принимает сообщение и выполняет запрошенную работу: копирование буферов памяти, сборка пакетов и т. Д. Итак, вызывающий код сразу возобновляет выполнение, а работа tcp выполняется параллельно? Это правильно?

Подробности будут оценены. Спасибо!

Ответы [ 2 ]

1 голос
/ 09 октября 2009

Стек TCP / IP является частью вашего ядра . В результате вы вызываете вспомогательный метод, который подготавливает « ловушку ядра ». Это особый вид исключения, который переводит ЦП в режим с большими привилегиями («режим ядра»). Внутри ловушки ядро ​​проверяет параметры исключения. Одним из них является номер вызываемой функции.

Когда вызывается функция, она копирует данные в буфер ядра и подготавливает все для обработки данных. Затем он возвращается из ловушки, ЦП восстанавливает регистры, и его исходный режим и выполнение вашего кода возобновляются.

Некоторое ядро ​​ thread получит копию данных и использует сетевой драйвер для ее отправки, выполнит всю обработку ошибок и т. Д.

Итак, да, после копирования необходимых данных ваш код возобновляется, и фактическая передача данных происходит параллельно.

Обратите внимание, что это для пакетов TCP. Протокол TCP выполняет всю обработку ошибок и квитирование за вас, поэтому вы можете предоставить ему все данные, и он будет знать, что делать. Если есть проблема с соединением, вы заметите это только через некоторое время, так как протокол TCP может самостоятельно справиться с короткими перебоями в работе сети. Это означает, что вы уже «отправили» некоторые данные, прежде чем получите ошибку. Это означает, что вы получите код ошибки для первого пакета только после N-го вызова send() или при попытке закрыть соединение (close() будет зависать, пока получатель не подтвердит все пакеты).

Протокол UDP не буферизуется. Когда звонок возвращается, пакет в пути. Но это «огонь и забудь», так что вы знаете только, что водитель положил его на провод. Если вы хотите узнать, прибыло ли оно куда-нибудь, вы должны сами найти способ достичь этого. Обычный подход заключается в том, чтобы получатель отправлял обратно ack-пакет подтверждения (который также может быть потерян).

0 голосов
/ 09 октября 2009

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

Но нет никаких процессов-демонов, магически отправляющих ваш вызов. Остальная часть выполнения вашей программы должна ждать завершения системного вызова и возврата любых значений, которые она вернет. Вот почему вы можете рассчитывать на то, что возвращаемые значения будут доступны сразу после возврата из системного вызова - такие значения, как количество байтов, фактически прочитанных из сокета или записанных в файл.

Я попытался найти хорошее объяснение того, как работает переключение контекста на пространство ядра. Вот хороший подробный, который даже фокусируется на реализации для конкретной архитектуры:

http://www.ibm.com/developerworks/linux/library/l-system-calls/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...