Интервью исследует, как переводить знания из книг в собственное понимание
Я также прошел около 20 собеседований до и после.В целом, я чувствую, что процесс собеседования на самом деле не так сложен, как я себе представлял.Много знаний - это проблемы, с которыми я обычно сталкиваюсь, либо я не понимаю это тщательно, либо Я понимаю это, я знаю, что это значит в моем сердце, но я не могу ясно выразить это, и я не могу уловить ключевые моменты.
Так что я планирую получить знания в будущем, сначала прочитать и понять их внимательно, а затем записать своими словами и обобщить в блог, не читая книгу.
Обзор знаний
- разъем
розеткаIP:端口号
, является конечной точкой TCP-соединения
- Модель ввода/вывода
Операция ввода грубо делится на два этапа: приложение запрашивает и ожидает поступления данных, а затем данные копируются из ядра в процесс. Для операций ввода на сокетах первый шаг аналогичен ожиданию поступления данных из сети.После поступления данных, во избежание потери данных, они будут скопированы в буфер в ядре, второй шаг - буферизация ядро, данные в этой области копируются в буфер приложения.
В Unix существует пять моделей ввода/вывода:
- Блокировка ввода/вывода
- Неблокирующий ввод-вывод
- Мультиплексирование ввода-вывода (выберите опрос)
- Управляемый сигналами ввод-вывод (SIGIO)
- Асинхронный ввод-вывод (AIO)
Блокировка ввода/вывода
Конкретный процесс заключается в том, что сначала процесс приложения инициирует системный вызов и будет ждать, пока дейтаграмма не будет готова.В это время данные все еще находятся в буфере ядра, и дейтаграмма должна быть возвращена в буфер процесса приложения.
Следует отметить, что блокировка ввода-вывода не означает, что блокируется система, а только блокируется текущее приложение.Другие приложения могут продолжать работать, поэтому это не потребляет процессорное время и имеет высокую эффективность выполнения.
Неблокирующий ввод-вывод
После того, как процесс приложения выполнит системный вызов, он отличается от процесса блокировки, непосредственно входящего в блокировку, но если данные не готовы, будет возвращен код ошибки, и процесс приложения может продолжать выполняться, но ему необходимо непрерывно делать системные вызовы, чтобы узнать, завершен ли ввод-вывод. , этот метод называется опросом
Насколько я понимаю, неблокирующий ввод-вывод и блокирующий ввод-вывод на самом деле одинаковы, оба должны ждать данных, но один пассивно входит в блокировку, а другой активно запрашивает, чтобы проверить, хороши ли данные, например как это обучение в старшей школе.Один ждет, пока учитель будет учить в процессе желания освоить новые знания, ждет, пока учитель не будет учить в классе, в то время как другой ученик продолжает ходить в офис, чтобы спросить, если учитель в классе и когда.
Мультиплексирование ввода/вывода
По сути, процесс мультиплексирования ввода-вывода очень похож на блокирующий тип, за исключением того, что при мультиплексировании ввода-вывода сначала вызывается select.В это время система будет отслеживать все дейтаграммы, отвечающие за select.Как только определенные данные будут готовы , он будет возвращен, и будет выполнен системный вызов recvfrom, выполняющий ту же обработку, что и для блокировки ввода-вывода. По сравнению с блокирующим вводом-выводом, здесь необходимо вызывать два системных вызова, поэтому эффективность определенно не так хороша, как в первом случае, но самая большая особенность заключается в том, что несколько соединений могут обрабатываться одновременно.
Еще одно слово. Следовательно, если количество обработанных соединений не очень велико, веб-сервер, использующий select/epoll, не обязательно лучше, чем веб-сервер, использующий многопоточность + блокирующий ввод-вывод, и задержка может быть больше. Преимущество select/epoll не в том, что он может быстрее обрабатывать одно соединение, а в том, что он может обрабатывать больше соединений.
Управляемый сигналами ввод-вывод
Обычно не используется, в основном не задействован
Асинхронный ввод-вывод
Системный вызов aio_read вернется немедленно, процесс приложения продолжит выполнение без блокировки, и ядро отправит сигнал процессу приложения после завершения всех операций.
Разница между асинхронным вводом-выводом и вводом-выводом, управляемым сигналом, заключается в том, что сигнал асинхронного ввода-вывода должен уведомить процесс приложения о завершении ввода-вывода, а сигнал ввода-вывода, управляемого сигналом, должен уведомить прикладной процесс, с которого может быть запущен ввод-вывод.
Проще говоря, когда процесс пользовательского приложения запрашивает данные, он не войдет в блок, а продолжит выполнение других задач.Когда данные процесса приложения будут обработаны, соответствующая система отправит обратно пользовательскому процессу сигнал, указывающий, что приложение процесс выполнен. Завершен, это самое большое отличие от управляемого сигналом. Возвращенный сигнал должен уведомить процесс о том, что выполнение было завершено, а сигнальный возвратный сигнал должен уведомить процесс о том, что выполнение может начаться.
сравнивать
В чем разница между блокировкой и не блокировкой? Синхронная асинхронная разница?
Проще говоря, самая большая разница между блокирующим типом и неблокирующим типом заключается в том, что блокирующий тип войдет в блок во время ожидания данных, а неблокирующий тип — нет, а неблокирующий — после данные хранятся в буфере ядра, буфере ядра Эта фаза копирования данных в области в буфер приложения блокируется.
Прежде чем говорить о разнице между синхронным и асинхронным, мы должны сначала понять, что такое синхронизация и что такое асинхронность? Разница в том, что процесс будет заблокирован при выполнении операций ввода/вывода.Согласно этому определению, блокировка, неблокировка, управление сигналом и мультиплексирование ввода/вывода являются синхронными.Почему неблокировка тоже? Это включает в себя то, что мы сказали ранее, хотя в начале нет блокировки, но данные блокируются от ядра к приложению позже.
Цитируя хороший пример от блоггера, чтобы понять:
Наконец, вот еще несколько неуместных примеров, иллюстрирующих эти четыре модели ввода-вывода: Четыре человека A, B, C и D ловят рыбу:
А использует самую старомодную удочку, поэтому он должен охранять ее, пока рыба не попадется на крючок, а затем тянуть удочку;
У удочки B есть функция, которая может отображать, поймана ли рыба на крючок, поэтому B болтает с ММ рядом с ним, а затем проверяет, не попалась ли рыба на крючок, и, если есть, быстро дергает удочку;
Удочки, используемые С, аналогичны удочкам Б, но он придумал хороший способ поставить несколько удочек одновременно, а затем держать их рядом с ними. подтяните соответствующие удочки;
D — богатый человек, он просто нанял кого-то, чтобы тот ловил для него рыбу, и как только этот человек поймал рыбу, отправьте D текстовое сообщение.
Интервью нужно спросить
select/poll/epoll — все это конкретные реализации мультиплексирования ввода-вывода, Select появляется первым, а затем poll. Тогда эпол.
select
Существует три типа типов дескрипторов: readset, writeset, exceptionset, соответствующие чтению, записи, исключению соответственно. Коллекция дескрипторов условия. fd_set реализован с использованием массива, а размер массива определяется с помощью FD_SETSIZE.
timeout — параметр тайм-аута, вызов select будет заблокирован до тех пор, пока не прибудет событие с дескриптором или не будет ожидать Время превышено тайм-аут.
Успешный вызов возвращает результат больше 0, ошибка возвращает результат -1, а тайм-аут возвращает результат 0.
Код ключа следующий:
fd_set fd_in, fd_out;
struct timeval tv;
// Reset the sets
FD_ZERO( &fd_in );
FD_ZERO( &fd_out );
// Monitor sock1 for input events
FD_SET( sock1, &fd_in );
// Monitor sock2 for output events
FD_SET( sock2, &fd_out );
// Find out which socket has the largest numeric value as select requires it
int largest_sock = sock1 > sock2 ? sock1 : sock2;
// Wait up to 10 seconds
tv.tv_sec = 10;
tv.tv_usec = 0;
// Call the select
int ret = select( largest_sock + 1, &fd_in, &fd_out, NULL, &tv );
// Check if select actually succeed
if ( ret == -1 )
// report error and abort
else if ( ret == 0 )
// timeout; no event detected
else
{
if ( FD_ISSET( sock1, &fd_in ) )
// input event on sock1
if ( FD_ISSET( sock2, &fd_out ) )
// output event on sock2
}
выберите подробный процесс:
Когда пользовательский процесс вызывает select, select копирует набор readfds, который необходимо отслеживать, в пространство ядра (при условии, что только сокет доступен для чтения), затем проходит через сокет sk, который он отслеживает, и вызывает логику опроса sk по одному один, чтобы проверить, доступен ли sk для чтения или нет.Есть событие для чтения.После обхода всех sk, если ни один sk не доступен для чтения, select вызовет schedule_timeout, чтобы войти в цикл расписания, заставляя процесс перейти в спящий режим. Если есть данные для чтения на определенном sk в течение периода тайм-аута или ожидания тайм-аута, процесс, который вызывает select, будет пробужден. Пользователь.
На данный момент нам нужно решить три задачи:
(1) Отслеживаемый набор fds ограничен 1024, 1024 слишком мало, мы надеемся иметь относительно большой отслеживаемый набор fds
(2) Проблема в том, что набор fds нужно копировать из пространства пользователя в пространство ядра, надеемся, что копирование не требуется
(3) Когда некоторые из отслеживаемых fds имеют читаемые данные, мы хотим, чтобы уведомление было более точным, то есть мы надеемся получить список fds с читаемыми событиями из уведомления, вместо того, чтобы проходить все fds для сбора.
poll
Механизм опроса аналогичен механизму выбора, который по сути мало чем отличается от выбора.Управление несколькими дескрипторами также опрашивается и обрабатывается в соответствии со статусом дескрипторов, но у опроса нет ограничения на максимальное количество. файловых дескрипторов. Poll изменяет описание набора fds, используя структуру pollfd вместо структуры select fd_set, так что предел набора fds, поддерживаемый poll, намного больше, чем 1024 для select. Где pollfd реализован с использованием связанного списка
int poll(struct pollfd *fds, unsigned int nfds, int timeout);
выбрать опрос сравнить
- Функции
Реализация примерно такая же, но некоторые детали отличаются:
- Тип дескриптора select реализован с помощью массива, размер FD_SETSIZE по умолчанию равен 1024, но это значение можно изменить, если его нужно изменить, его нужно перекомпилировать, а poll реализован с помощью связанного списка, есть нет ограничений на размер дескриптора.
- poll предоставляет больше типов событий и имеет более высокий уровень повторного использования дескрипторов, чем selec.
- Если один поток вызывает selec или poll для дескриптора, а другой поток закрывает дескриптор, результат вызова будет неопределенным.
- скорость
очень медленно
- Общим является то, что все дескрипторы нужно копировать из буфера процесса приложения в буфер ядра при вызове
- Возвращаемые результаты обоих не объявляют, какие дескрипторы готовы, поэтому, если возвращаемое значение больше 0, процесс приложения должен использовать метод опроса, чтобы найти дескриптор для завершения ввода-вывода.
- портативность
select появился раньше, поэтому его поддерживают в основном все системы, и только более новые системы поддерживают poll
эполл (слишком сильный)
epoll_ctl() используется для регистрации нового дескриптора в ядре или изменения состояния файлового дескриптора. Зарегистрированные дескрипторы будут поддерживаться в красно-черном дереве в ядре Ядро добавит дескрипторы, готовые к вводу-выводу, в связанный список для управления через функцию обратного вызова, а процесс может вызвать epoll_wait() для получения события завершение.дескриптор.
Как видно из вышеприведенного описания, epoll достаточно один раз скопировать дескриптор из буфера процесса в буфер ядра, и процессу не нужно проводить опрос для получения дескриптора завершения события.
epoll доступен только для ОС Linux.
epoll является более гибким, чем select и poll, и не имеет ограничений по количеству дескрипторов.
epoll более удобен для многопоточного программирования: один поток вызывает epoll_wait(), а другой поток закрывает тот же дескриптор, не создавая неопределенные ситуации, такие как выбор и опрос.
режим работы epoll
Событие дескриптора epoll имеет два режима срабатывания: LT (триггер уровня) и ET (триггер края).
- LT-режим
Когда epoll_wait() обнаруживает приход события дескриптора, он уведомляет процесс об этом времени, и процессМогуЕсли событие не обрабатывается немедленно, процесс будет снова уведомлен при следующем вызове epoll_wait(), который является режимом по умолчанию и поддерживает как блокировку, так и неблокировку.
- Инопланетный режим
В отличие от режима LT, событие должно быть обработано сразу после уведомления, и следующий вызов epoll_wait() не будет уведомлен о наступлении времени.
Он уменьшает количество повторных запусков события epoll, поэтому он более эффективен, чем LT, и поддерживает только неблокировку, чтобы избежать голодания задачи обработки нескольких файловых дескрипторов из-за блокирующей операции чтения/записи дескриптора файла. .
Сценарии применения
Из приведенного выше сравнения легко понять, что, поскольку epoll настолько мощен, разве недостаточно использовать epoll? На самом деле это не так, на самом деле у каждого свой вариант использования
- выбрать сценарии использования
- Точность тайм-аута select составляет 1 нс, а двух других — 1 мс, поэтому select больше подходит для сценариев с высокими требованиями к реальному времени, таких как управление ядерными реакторами.
- select обладает хорошей переносимостью и поддерживается почти всеми основными платформами.
- сценарии использования опроса
- По сравнению с select, опрос не имеет ограничения на максимальное количество дескрипторов, и если платформа не требует очень высокой производительности в реальном времени, обычно используется опрос.
- Необходимо отслеживать менее 1000 дескрипторов одновременно, нет необходимости использовать epoll, поскольку этот сценарий приложения не отражает преимущества epoll.
- Есть много изменений в состоянии дескрипторов, которые нужно отслеживать, и все они очень кратковременны, и нет необходимости использовать epoll, потому что все дескрипторы в epoll хранятся в ядре, поэтому каждое изменение в состояние дескриптора требует системного вызова, частые системные вызовы определенно снижают эффективность, а дескрипторы epoll хранятся в ядре и их нелегко отладить
- сценарии использования epoll
Его нужно только запустить на платформе Linux, и есть очень большое количество дескрипторов, которые необходимо опрашивать одновременно, и эти соединения предпочтительно являются долгосрочными соединениями.
Ссылаться на
IO - синхронный, асинхронный, блокирующий, неблокирующий
Расскажите о Select, Poll, Epoll
Введение в системные вызовы мультиплексирования ввода-вывода (выбор, опрос, epoll) в Linux