Я смотрел этот разговор о внедрении Async IO в Rust, и Карл упоминал две потенциальные модели. Готовность и Завершение.
Модель готовности:
- вы говорите ядру, что хотите прочитать из сокета
- делать другие вещи на некоторое время ...
- ядро говорит вам, когда сокет готов
- ты читаешь (заполняешь буфер)
- делай что хочешь
- освободить буфер (происходит автоматически с Rust)
Модель завершения:
- Вы выделяете буфер для ядра, чтобы заполнить
- делать другие вещи на некоторое время ...
- ядро говорит вам, когда буфер был заполнен
- делать с данными все, что нужно
- освободить буфер
В примере Карла с использованием модели готовности вы можете перебирать готовые сокеты, заполняя и освобождая глобальный буфер, из-за которого кажется, что он будет использовать гораздо меньше памяти.
Теперь мои предположения:
Под капотом (в пространстве ядра), когда сокет называется «готовым», данные уже существуют. Он вошел в сокет по сети (или откуда-либо), и ОС хранит данные.
Это не так, как будто это волшебное распределение не происходит в модели готовности. Просто ОС абстрагируется от вас. В модели Завершения ОС просит вас выделить память до того, как данные действительно поступят, и станет ясно, что происходит.
Вот моя исправленная версия модели готовности:
- вы говорите ядру, что хотите прочитать из сокета
- делать другие вещи на некоторое время ...
- ПОПРАВКА: данные поступают в ОС (некоторое место в памяти ядра)
- ядро говорит вам, что сокет готов
- вы читаете (заполняете другой буфер отдельно от буфера ядра abover (или вы получаете указатель на него?))
- делай что хочешь
- освободить буфер (происходит автоматически с Rust)
/ Мои предположения
Мне нравится держать программу пользовательского пространства маленькой, но я просто хотел кое-что прояснить, что на самом деле происходит здесь. Я не вижу, чтобы одна модель по своей природе использовала меньше памяти или поддерживала более высокий уровень параллельного ввода-вывода. Я хотел бы услышать мысли и более глубокое объяснение этого.