Wątek przeniesiony 2023-02-23 20:45 z Off-Topic przez Riddle.

Funkcja "update element" usługi BPF kończy się błędem "operation not supported"

0

Piszę program w C i makrodefinicjach „assemblerowych” BPF. Wykorzystuję funkcję bpf systemu Linux, wywołując ją przez syscall. Tworzę sobie mapę typu tablicy zdarzeń perf, by móc przesyłać dane do userspac-u. Nadaję jeden element maksymalnie dla tej tablicy. Następnie tworzę deskryptor pliku w perf, z konfiguracją wyjścia bpf. Mój program BPF się ładuje, bo jest wywoływany. Problem jednak w tym, że gdy użyję funkcji update element, usługi BPF, podając wskaźnik do deskryptora plików zwróconego przez perf_event_open, jako wartość i wskaźnik do zmiennej zawierającej 0, to otrzymuję operation not supported. Szukałem w internecie, kiedy funkcja BPF zwraca ten rodzaj błędu (zmienna/makrodefinicja errno), ale nic nie znalazłem.

0

@ksh: To nie jest closed source. Po prostu za wcześnie, by wypychać to do zobaczenia. Kod ma być scalony z projektem Plasma. Ma odpowiadać za sprawdzenie, czy aplikacja jest konsolowa, czy graficzna. Poprzednio używałem sposobu, który nie zawsze działał,. więc postanowiłem użyć tracingu, by przechwytywać funkcje open/read. Owijanie funkcji przez GCC/LLVM nie wchodzi w grę, bo biblioteki mają odniesienia do różnych wersji innych bibliotek, a za jeden symbol (nawet w C) może odpowiadać wiele symboli wywołań systemowych, np. read może być read, read64, itd. Nowy kod ma działać nawet, gdy proces się rozwidla, więc gdy skrypt bash-a będzie wywoływać kdialog/zenity, to elegancko powinien zostać rozpoznany jako graficzny.

Kod umieściłem tutaj: https://invent.kde.org/slawomirlach/kio/commit/4c3065d054362cd2cc8a7a783f496cd6faa331d6 . Problem jest tak, że to śmietnik, bo kiepski ze mnie programista. Głównym powodem nie umieszczenia kodu wcześniej było, że gdy wcześniej wklejałem swój kod w publicznym miejscu, z pytaniem o pomoc, to mi kazali wyodrębniać fragment, który może powodować nieprawidłowe działanie.

0

Problem jednak w tym, że gdy użyję funkcji update element, usługi BPF, podając wskaźnik do deskryptora plików zwróconego przez perf_event_open

Tak jak patrzę na przykład użycia w repo to występuje tutaj komunikacja przez pamięć współdzieloną a nie deskryptor https://github.com/torvalds/linux/blob/master/samples/bpf/trace_output_user.c
https://github.com/torvalds/linux/blob/master/samples/bpf/trace_output.bpf.c

0
several napisał(a):

Problem jednak w tym, że gdy użyję funkcji update element, usługi BPF, podając wskaźnik do deskryptora plików zwróconego przez perf_event_open

Tak jak patrzę na przykład użycia w repo to występuje tutaj komunikacja przez pamięć współdzieloną a nie deskryptor https://github.com/torvalds/linux/blob/master/samples/bpf/trace_output_user.c
https://github.com/torvalds/linux/blob/master/samples/bpf/trace_output.bpf.c

Dzięki. Problem w tym, że ten przykład jest oparty na libbpf, a ja nie chcę z niej korzystać. Wszystko z tego względu, że nie chcę dokładać zależności do KIO (elementu KDE Frameworks, takiego projektu tworzonego przez zespół KDE, który to jest skupiony w okół własnego środowiska graficznego). W moim kodzie mapuje deskryptor plików na obszar pamięci. Czytałem, że utworzenie zdarzenia perf z odpowiednim parametrem config (coś w stylu PERF_EVENT_BPF_OUTPUT), a następnie przypisanie rezultatu perf_event_open do odpowiedniego elementu mapy, pozwala na wysyłanie danych do przestrzeni użytkownika. Trzeba tylko wykorzystać ten sam indeks, co przy uaktualnieniu elementu mapy. To, co mnie nurtuje, to pojawianie się w dokumentacji odniesień do procesorów. Jest wspomniane, że indeksy mogą reprezentować rdzenie procesora, a więc podczas tworzenia mapy, max_elements odpowiada ilości procesorów w komputerze. Występuje nawet specjalny indeks, reprezentujący obecny procesor. Natomiast pojawia się wzmianka, że wykorzystanie elementów mapy jako odpowiedników procesorów jest tylko przykładem. Z jednej strony jest specjalny indeks, a z drugiem wzmianka, że taki przykład zastosowania to tylko przykład, więc trochę się pogubiłem.

0

Mam pytania. W wielu przykładach, jak tutaj: https://android.googlesource.com/kernel/common/+/4764810c4544/samples/bpf/trace_output_kern.c , pojawia się definicja mapy w elfie wygenerowanym do załadowania przez libbpf. Pojawia się tam sekcja MAPS. Natomiast w innym miejscu znalazłem informację, że obecność definicji mapy w tej sekcji jest zbędna, bo loader/verfiver sprawdza tylko, czy definicja mapy jest stała (mieści się w pamięci tylko do odczytu).
Stąd pytania:

  1. Jak zdefiniować dane stałe, nie korzystając z libbpf i elf-a (czyli, jak to robię teraz - wstawić instrukcje bpf - ARM? - w kodzie C, wraz z definicją mapy)
  2. Czy konieczna jest definicja mapy po stronie programu bpf, czy wystarczy zdefiniować mapę w programie w userspace i użyć BPF_LD_MAP_FD?

Jak ustalić, jak błąd jest podczas wywołania BPF_FUNC_perf_event_output? W dokumentacji nie jest podane, więc raczej nie ma metody, ale wolę się spytać. Wg. dokumentacji, funkcja tylko informuje czy zakończyła się sukcesem, czy był błąd. To ta funkcja zwraca błąd, gdy spróbuję nie przypisywać deskryptora perf_event do mapy. Dodatkowo, to bez tej operacji (przypisania fd do mapy), program działa, ale wiesza się na poll, czyli userspace myśli, że deskryptor pliku jest w porządku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1