Przeszukałem go i zauważyłem, że większość ludzi opowiada się za używaniem kmalloc
, ponieważ masz gwarancję, że otrzymasz ciągłe fizyczne bloki pamięci. Jednak wydaje się również, że kmalloc
może się nie powieść, jeśli nie można znaleźć ciągłego fizycznego bloku, którego chcesz.
Jakie są zalety posiadania ciągłego bloku pamięci? W szczególności, dlaczego miałbym mieć ciągły fizyczny blok pamięci w wywołaniu systemowym ? Czy jest jakiś powód, dla którego nie mogłem po prostu użyć vmalloc
?
Wreszcie, jeśli miałbym przydzielić pamięć podczas obsługi wywołania systemowego, czy powinienem określić GFP_ATOMIC
? Czy wywołanie systemowe jest wykonywane w kontekście atomowym?
GFP_ATOMIC
Alokacja ma wysoki priorytet i nie zasypia. Jest to flaga używana w obsłudze przerwań, dolnych połówkach i innych sytuacjach, w których nie możesz spać.
GFP_KERNEL
Jest to normalna alokacja i może blokować. To jest flaga używana w kodzie kontekstu procesu, gdy można bezpiecznie spać.
źródło
vmalloc
jest szybsze z Kernel 5.2 (Q2 2019)Odpowiedzi:
Musisz tylko martwić się o używanie fizycznie ciągłej pamięci, jeśli bufor będzie dostępny przez urządzenie DMA na fizycznie adresowanej magistrali (takiej jak PCI). Problem polega na tym, że wiele wywołań systemowych nie ma możliwości sprawdzenia, czy ich bufor zostanie ostatecznie przekazany do urządzenia DMA: kiedy przekażesz bufor do innego podsystemu jądra, naprawdę nie możesz wiedzieć, dokąd zmierza. Nawet jeśli jądro nie używa dziś bufora dla DMA , może to zrobić w przyszłości.
vmalloc jest często wolniejszy niż kmalloc, ponieważ może być zmuszony do ponownego odwzorowania przestrzeni bufora na praktycznie ciągły zakres. kmalloc nigdy nie zmienia mapowania, chociaż jeśli nie zostanie wywołany z GFP_ATOMIC, kmalloc może blokować.
kmalloc ma ograniczony rozmiar bufora, który może dostarczyć: 128 KB *) . Jeśli potrzebujesz naprawdę dużego bufora, musisz użyć vmalloc lub innego mechanizmu, takiego jak rezerwowanie dużej ilości pamięci podczas rozruchu.
W przypadku wywołania systemowego nie musisz przekazywać GFP_ATOMIC do kmalloc (), możesz użyć GFP_KERNEL. Nie jesteś operatorem przerwań: kod aplikacji wchodzi do kontekstu jądra za pomocą pułapki, nie jest przerwaniem.
źródło
Krótka odpowiedź: pobierz sterowniki urządzeń Linux i przeczytaj rozdział o zarządzaniu pamięcią.
Poważnie, jest wiele subtelnych problemów związanych z zarządzaniem pamięcią jądra, które musisz zrozumieć - spędzam dużo czasu na debugowaniu z nim problemów.
vmalloc () jest bardzo rzadko używana, ponieważ jądro rzadko używa pamięci wirtualnej. Zazwyczaj używana jest kmalloc (), ale musisz wiedzieć, jakie są konsekwencje różnych flag i potrzebujesz strategii radzenia sobie z tym, co się dzieje, gdy się nie powiedzie - szczególnie jeśli jesteś w obsłudze przerwań, jak sugerowałeś.
źródło
Linux Kernel Development Robert Love (Rozdział 12, strona 244 w 3. wydaniu) odpowiada na to bardzo jasno.
Tak, w wielu przypadkach pamięć fizycznie ciągła nie jest wymagana. Głównym powodem, dla którego kmalloc jest używany częściej niż vmalloc w jądrze, jest wydajność. Książka wyjaśnia, że kiedy duże fragmenty pamięci są przydzielane za pomocą vmalloc, jądro musi mapować fizycznie nieciągłe fragmenty (strony) w pojedynczy ciągły region pamięci wirtualnej. Ponieważ pamięć jest praktycznie ciągła i fizycznie nieciągłość, do tabeli stron trzeba będzie dodać kilka odwzorowań adresów wirtualnych na fizyczne. W najgorszym przypadku do tabeli stron zostanie dodana liczba mapowań (rozmiar bufora / rozmiar strony) .
Zwiększa to również presję na TLB (wpisy pamięci podręcznej przechowujące najnowsze mapowania adresów wirtualnych na fizyczne) podczas uzyskiwania dostępu do tego bufora. Może to prowadzić do bicia .
źródło
Funkcje
kmalloc()
&vmalloc()
to prosty interfejs do uzyskiwania pamięci jądra w porcjach wielkości bajtów.kmalloc()
Funkcja gwarantuje, że strony są fizycznie przyległe (i praktycznie przyległe).vmalloc()
Funkcja działa w sposób podobny dokmalloc()
, oprócz tego, że przydziela pamięć, która jest tylko wirtualnie przyległe niekoniecznie fizycznie przyległe.źródło
Jakie są zalety posiadania ciągłego bloku pamięci? W szczególności, dlaczego miałbym mieć ciągły fizyczny blok pamięci w wywołaniu systemowym? Czy jest jakiś powód, dla którego nie mogłem po prostu użyć vmalloc?
Z „Szczęśliwy traf” Google
vmalloc
:kmalloc jest preferowanym sposobem, o ile nie potrzebujesz bardzo dużych obszarów. Problem polega na tym, że jeśli chcesz wykonać DMA z / do jakiegoś urządzenia sprzętowego, musisz użyć kmalloc i prawdopodobnie będziesz potrzebować większego kawałka. Rozwiązaniem jest przydzielenie pamięci tak szybko, jak to możliwe, zanim pamięć zostanie pofragmentowana.
źródło
W systemie 32-bitowym kmalloc () zwraca adres logiczny jądra (chociaż jest to adres wirtualny), który ma bezpośrednie mapowanie (właściwie ze stałym przesunięciem) na adres fizyczny. To bezpośrednie mapowanie zapewnia, że otrzymamy ciągły fizyczny fragment pamięci RAM. Odpowiedni dla DMA, w którym podajemy tylko początkowy wskaźnik i oczekujemy ciągłego fizycznego mapowania dla naszej operacji.
vmalloc () zwraca wirtualny adres jądra, który z kolei może nie mieć ciągłego mapowania w fizycznej pamięci RAM. Przydatne do alokacji dużej ilości pamięci oraz w przypadkach, gdy nie obchodzi nas, że pamięć przydzielona naszemu procesowi jest ciągła również w fizycznej pamięci RAM.
źródło
Jedną z innych różnic jest to, że kmalloc zwróci adres logiczny (w przeciwnym razie określisz GPF_HIGHMEM). Adresy logiczne są umieszczane w „małej ilości pamięci” (w pierwszym gigabajcie pamięci fizycznej) i są odwzorowywane bezpośrednio na adresy fizyczne (do konwersji użyj makra __pa). Ta właściwość oznacza, że kmalloced memory jest pamięcią ciągłą.
Z drugiej strony, Vmalloc jest w stanie zwrócić adresy wirtualne z „dużej pamięci”. Adresów tych nie można przekształcić bezpośrednio w adresy fizyczne (należy użyć funkcji virt_to_page).
źródło