Jeden z opracowywanych przeze mnie sterowników jądra Linux używa komunikacji sieciowej w jądrze (sock_create()
, sock->ops->bind()
itd.).Symulacja efektu select() i poll() w programowaniu gniazda jądra
Problem polega na tym, że będzie wiele gniazd do odbioru danych. Potrzebuję więc czegoś, co zasymuluje przestrzeń select()
lub poll()
w przestrzeni jądra. Ponieważ te funkcje używają deskryptorów plików, nie mogę używać wywołań systemowych, chyba że używam wywołań systemowych do tworzenia gniazd, ale to wydaje się niepotrzebne, ponieważ pracuję w jądrze.
Tak więc myślałem o opakowaniu domyślnego handler'a sock->sk_data_ready
w mojej własnej ładowarce (custom_sk_data_ready()
), która odblokowałaby semafor. Następnie mogę napisać własną funkcję kernel_select()
, która próbuje zablokować semafor i blokuje oczekiwanie, aż zostanie otwarta. W ten sposób funkcja jądra przechodzi w stan uśpienia, aż semafor zostanie odblokowany przez custom_sk_data_ready()
. Po uzyskaniu blokady przez kernel_select()
odblokowuje się i wywołuje custom_sk_data_ready()
, aby ją ponownie zarchiwizować. Tak więc jedyną dodatkową inicjalizacją jest uruchomienie custom_sk_data_ready()
przed związaniem gniazda, więc pierwsze wywołanie do custom_select()
nie uruchamia się fałszywie.
Widzę jeden możliwy problem. Jeśli pojawi się wiele odbierających, wiele połączeń do custom_sk_data_ready()
spróbuje odblokować semafor. Aby nie zgubić wielu połączeń i śledzić używane urządzenie sock
, do używanych gniazd musi być tabela lub lista wskaźników. I custom_sk_data_ready()
będzie musiał oznaczać w tabeli/liście, które gniazdo zostało przekazane.
Czy ta metoda brzmi? Czy powinienem po prostu zmagać się z problemem przestrzeni użytkownika/jądra podczas korzystania ze standardowych wywołań systemowych?
Znalezienie początkowa:
Wszystkie funkcje wywołania zwrotnego w strukturze sock
są nazywane w kontekście przerwania. Oznacza to, że nie mogą spać. Aby główny wątek jądra mógł spać na liście gotowych gniazd, używane są muteksy, ale custom_sk_data_ready()
musi działać jak spinlock na muteksach (wywołanie mutex_trylock()
). Oznacza to również, że każda alokacja dynamiczna musi używać flagi GFP_ATOMIC
.
Dodatkowa możliwość:
Dla każdego otwartego gniazda, wymienić każde gniazdo na sk_data_ready()
ze zwyczajem jeden (custom_sk_data_ready()
) i stworzyć pracownikowi (struct work_struct
) i kolejkę pracy (struct workqueue_struct
). Dla każdego pracownika będzie używana wspólna funkcja process_msg()
. Utwórz globalną listę modułów na poziomie jądra, w której każdy element listy ma wskaźnik do gniazda i zawiera strukturę pracującą. Gdy dane są gotowe na gnieździe, custom_sk_data_ready()
wykona i znajdzie pasujący element listy z tym samym gniazdem, a następnie wywoła queue_work()
z kolejką roboczą elementu elementu i pracownikiem. Następnie zostanie wywołana funkcja process_msg()
i można albo znaleźć zgodny element listy poprzez zawartość parametru struct work_struct *
(adres), albo użyć makra container_of()
, aby uzyskać adres struktury listy, która przechowuje strukturę pracownika.
Która technika jest najbardziej brzmieniowa?
Nie możesz mieć programu pomocniczego przestrzeni użytkownika wykonującego 'poll'? Multipleksowanie danych wejściowych za pomocą 'poll' lub' select' jest związane z terminarzem (ponieważ proces wstrzymywania jest bezczynny, więc inne procesy mogą działać), więc nie zrobię tego wewnątrz jądra! –
@BasileStarynkevitch: Właśnie dlatego próbuję symulować blokowanie trybu uśpienia 'poll()' i 'select()'. Używanie tych dwóch wywołań systemowych z jądra jest ostatecznością. Podejrzewam, że są problemy z uruchomieniem 'poll()' i 'select()' w helperie przestrzeni użytkownika. Pomocnik musi mieć dostęp do deskryptora pliku (czego nie robi się w 'sock_create()') i ewentualnie do uzyskania dostępu do gniazda znajdującego się w przestrzeni jądra. Tak więc teraz tworzenie gniazd musi nastąpić w helperie przestrzeni użytkownika, a moduł musi znaleźć gniazdo na podstawie deskryptora pliku przestrzeni użytkownika. Teraz staje się bardziej skomplikowana. – Joshua
Nie powinieneś robić tego w jądrze. – mpe