Что такое подробный процесс помощников карты API bps, таких как "bpf_map_update_elem"? - PullRequest
0 голосов
/ 17 января 2020

В моем понимании, когда пользовательское пространство сначала использует bpf_map_update_elem(int fd, void *key, void *value, __u64 flags),

, пользовательское пространство находит карту через fd;

секунду, пользовательское пространство создает память в пользовательском пространстве;

и ....

Я немного знаю, но конкретный c процесс все еще неясен.

Так что я хочу знать, каковы детали при запуске пространства пользователя Помощники API-карт.

1 Ответ

1 голос
/ 17 января 2020

Поскольку вы упоминаете «пространство пользователя», я не уверен, о чем именно вы говорите. Итак, давайте начнем с некоторого пояснения.

Карты BPF (или, по крайней мере, большинство существующих типов, включая карты и массивы ha sh) могут быть доступны двумя способами:

  • Из пространства пользователя, из любого приложения, работающего в системе и имеющего достаточные права доступа
  • Из пространства ядра, из программ BPF

Из пространства пользователя нет функции «помощника». Взаимодействие с картами полностью (*) осуществляется с помощью системного вызова bpf() (команды BPF_MAP_LOOKUP_ELEM, BPF_MAP_UPDATE_ELEM, BPF_MAP_DELETE_ELEM передаются системному вызову в качестве первого аргумента). См. Справочную страницу bpf(2) для более подробной информации. Это то, что вы используете в приложении пользовательского пространства, которое загружает и управляет программами и картами BPF, например, bpftool.

Из пространства ядра, т.е. из программы BPF, все работает по-другому, и доступ осуществляется с одним из «помощников» БНФ, таким как bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags). См. Справочную страницу bpf-helpers(7) для получения подробной информации о существующих помощниках. Вы можете найти подробную информацию об этих вспомогательных вызовах в руководстве Cilium или, очевидно, читая код ядра (например, для карт массивов ). Они выглядят как низкоуровневые вызовы функций C, при этом регистры BPF используются для передачи необходимых аргументов, а затем он вызывает из программных инструкций BPF помощник, который компилируется как часть двоичного файла ядра.

Итак, вы упомянули bpf_map_update_elem() и пространство пользователя. Хотя это имя помощника на стороне ядра, я подозреваю, что вы можете говорить о функции с тем же именем, которое предлагается библиотекой libbpf, чтобы обеспечить оболочку для системного вызова bpf() . То, что происходит с этой функцией, довольно просто.

  • Нет необходимости искать карту из файлового дескриптора в пространстве пользователя: на самом деле происходит обратное, файловый дескриптор открыт из карты у пользователя пространство (например, из его идентификатора карты или из закрепленного пути в виртуальной файловой системе / sys / fs / bpf). Таким образом, fd передается системному вызову bpf() и используется ядром как ссылка на карту.
  • Я не уверен, что вы имеете в виду, но «пользовательское пространство создает память в пользовательском пространстве». Здесь нет необходимости выделять какую-либо память: key и value уже должны быть заполнены на этом этапе, и они передаются ядру через системный вызов bpf(), чтобы сообщить, какую запись обновить и с какой ценность. То же самое для флагов.
  • После вызова bpf() то, что происходит на стороне ядра, довольно просто. В основном ядро ​​ проверяет права доступа , проверяет аргументы (чтобы убедиться, что они безопасны и соответствуют карте), затем обновляет фактические данные. Для карт массива в конечном итоге вызывается array_map_update_elem() (используется с помощником BPF на стороне ядра, см. Ссылку выше).

(*) Некоторые взаимодействия могут фактически выполняться без системы bpf() Я полагаю, что с «глобальными данными», хранящимися в картах BPF, используйте приложения mmap() для памяти ядра. Но это выходит за рамки базового c использования массивов и карт.

...