Pliki mapowane w pamięci mogą być używane do zastępowania dostępu do odczytu / zapisu lub do obsługi współbieżnego udostępniania. Kiedy używasz ich do jednego mechanizmu, otrzymujesz także drugi.
Zamiast szukać, pisać i czytać w pliku, mapujesz go do pamięci i po prostu uzyskujesz dostęp do bitów tam, gdzie się spodziewasz.
Może to być bardzo przydatne iw zależności od interfejsu pamięci wirtualnej może poprawić wydajność. Poprawa wydajności może nastąpić, ponieważ system operacyjny może teraz zarządzać tym byłym „operacją we / wy” wraz z całym innym dostępem do pamięci programowej i może (teoretycznie) wykorzystać algorytmy stronicowania i tak dalej, które już wykorzystuje do obsługi pamięć wirtualna dla pozostałej części programu. Zależy to jednak od jakości podstawowego systemu pamięci wirtualnej. Słyszałem anegdoty, które mówią, że systemy pamięci wirtualnej Solaris i * BSD mogą wykazywać lepszą wydajność niż system VM w systemie Linux - ale nie mam danych empirycznych, które mogłyby to potwierdzić. YMMV.
Współbieżność pojawia się, gdy weźmie się pod uwagę możliwość korzystania przez wiele procesów z tego samego „pliku” w pamięci mapowanej. W modelu odczytu / zapisu, jeśli dwa procesy zapisałyby w tym samym obszarze pliku, można było być prawie pewnym, że jeden z danych procesu dotrze do pliku, nadpisując dane drugiego procesu. Dostaniesz jedną lub drugą - ale nie jakieś dziwne mieszanie się. Muszę przyznać, że nie jestem pewien, czy jest to zachowanie nakazane przez jakikolwiek standard, ale jest to coś, na czym można w zasadzie polegać. (Właściwie to dobre pytanie uzupełniające!)
Dla kontrastu, wyobraź sobie dwa procesy „pisania” na mapie. Robią to, robiąc „magazyny pamięci”, co skutkuje stronicowaniem danych przez system operacyjny na dysk - ostatecznie. Ale w międzyczasie można się spodziewać nakładania się zapisów.
Oto przykład. Powiedzmy, że mam dwa procesy, oba zapisują 8 bajtów z przesunięciem 1024. Proces 1 zapisuje „11111111”, a proces 2 zapisuje „22222222”. Jeśli używają wejścia / wyjścia pliku, możesz sobie wyobrazić, że głęboko w systemie operacyjnym znajduje się bufor pełen 1s i bufor pełny 2s, oba kierowane w to samo miejsce na dysku. Jeden z nich dotrze tam pierwszy, a drugi sekundę. W tym przypadku wygrywa ten drugi. Jeśli jednak używam podejścia opartego na plikach mapowanych w pamięci, proces 1 przejdzie do magazynu pamięci o wielkości 4 bajtów, a następnie do innego magazynu pamięci o wielkości 4 bajtów (załóżmy, że nie jest to maksymalny rozmiar magazynu pamięci). Proces 2 będzie robił to samo. W zależności od tego, kiedy procesy są uruchomione, możesz spodziewać się następujących informacji:
11111111
22222222
11112222
22221111
Rozwiązaniem tego problemu jest zastosowanie jawnego wzajemnego wykluczenia - co jest prawdopodobnie dobrym pomysłem w każdym przypadku. W każdym razie polegałeś na systemie operacyjnym, który zrobi „właściwą rzecz” w przypadku odczytu / zapisu pliku we / wy.
Prymitywem klasyfikacji wzajemnego wykluczania jest muteks. W przypadku plików mapowanych w pamięci sugerowałbym przyjrzenie się muteksowi mapowanemu w pamięci, dostępnemu za pomocą (np.) Pthread_mutex_init ().
Edytuj za pomocą jednej gotcha: Kiedy używasz zmapowanych plików, istnieje pokusa, aby osadzić wskaźniki do danych w pliku, w samym pliku (myślę, że połączona lista przechowywana w zmapowanym pliku). Nie chcesz tego robić, ponieważ plik może być mapowany pod różnymi adresami bezwzględnymi w różnym czasie lub w różnych procesach. Zamiast tego użyj przesunięć w mapowanym pliku.