Wiem, że gdy strona pamięci podręcznej jest modyfikowana, jest oznaczona jako brudna i wymaga zapisu zwrotnego, ale co się dzieje, gdy:
Scenariusz: plik / aplikacje / EXE, który jest plikiem wykonywalnym, jest całkowicie umieszczany w pamięci podręcznej stron (wszystkie strony znajdują się w pamięci podręcznej / pamięci) i jest wykonywany przez proces P
Wydanie ciągłe zastępuje następnie / apps / EXE nowym plikiem wykonywalnym.
Założenie 1: Zakładam, że proces P (i każdy inny posiadający deskryptor pliku odnoszący się do starego pliku wykonywalnego) będzie nadal używał starego, w pamięci / aplikacjach / EXE bez problemu, i każdy nowy proces, który próbuje wykonać tę ścieżkę, otrzyma nowy plik wykonywalny.
Założenie 2: Zakładam, że jeśli nie wszystkie strony pliku zostaną zmapowane w pamięci, wszystko będzie w porządku, dopóki nie wystąpi błąd strony wymagający stron z pliku, który został zastąpiony, i prawdopodobnie wystąpi awaria?
Pytanie 1: Jeśli zablokujesz wszystkie strony pliku za pomocą czegoś takiego jak vmtouch, czy w ogóle zmieni to scenariusz?
Pytanie 2: Jeśli / apps / EXE znajduje się na zdalnym NFS, czy to coś zmieni? (Zakładam, że nie)
Popraw lub zweryfikuj moje 2 założenia i odpowiedz na 2 moje pytania.
Załóżmy, że jest to okno CentOS 7.6 z jakimś rodzajem jądra 3.10.0-957.el7
Aktualizacja: Zastanawiając się nad tym, zastanawiam się, czy ten scenariusz nie różni się od żadnego innego scenariusza z brudną stroną.
Podejrzewam, że proces, który zapisuje nowy plik binarny, wykona odczyt i pobierze wszystkie strony pamięci podręcznej, ponieważ są one stronicowane, a następnie wszystkie te strony zostaną oznaczone jako brudne. Jeśli zostaną zablokowane, będą po prostu bezużytecznymi stronami zajmującymi pamięć podstawową, gdy liczba odniesień spadnie do zera.
Podejrzewam, że po zakończeniu aktualnie wykonywanych programów wszystko inne wykorzysta nowy plik binarny. Zakładając, że wszystko jest w porządku, myślę, że jest to interesujące tylko wtedy, gdy tylko część pliku jest stronicowana.
źródło
Odpowiedzi:
To jest ważna część.
Sposób, w jaki nowy plik jest wydawany, polega na utworzeniu nowego pliku (np.
/apps/EXE.tmp.20190907080000
), Zapisaniu zawartości, ustawieniu uprawnień i własności, a na końcu zmianie nazwy (2) na ostateczną nazwę/apps/EXE
, zastępując stary plik.W rezultacie nowy plik ma nowy numer i-węzła (co w efekcie oznacza, że jest to inny plik).
Stary plik miał swój własny numer i-węzła, który jest nadal obecny, mimo że nazwa pliku już go nie wskazuje (lub nie ma już nazw plików wskazujących na ten i-węzeł).
Kluczem jest tutaj to, że kiedy mówimy o „plikach” w Linuksie, najczęściej tak naprawdę mówimy o „i-węzłach”, ponieważ po otwarciu pliku i-węzeł jest odniesieniem do pliku.
Poprawny.
Błędny. Stary i-węzeł jest nadal obecny, więc błędy strony w procesie używającym starego pliku binarnego nadal będą w stanie znaleźć te strony na dysku.
Możesz zobaczyć niektóre z tego efektów, patrząc na
/proc/${pid}/exe
dowiązanie symboliczne (lub równoważnielsof
dane wyjściowe) dla procesu uruchamiającego stary plik binarny, który pokaże,/app/EXE (deleted)
aby wskazać, że nazwa już nie istnieje, ale i-węzeł jest nadal obecny.Możesz także zobaczyć, że przestrzeń dyskowa używana przez plik binarny zostanie zwolniona dopiero po śmierci procesu (zakładając, że jest to jedyny proces z otwartą i-węzłem). Sprawdź wyjście
df
przed i po zabiciu procesu, zobaczysz, że zmniejsza się o rozmiar tego starego pliku binarnego, o którym myślałeś, że już go nie ma.BTW, nie dotyczy to tylko plików binarnych, ale także dowolnych otwartych plików. Jeśli otworzysz plik w procesie i usuniesz plik, plik będzie przechowywany na dysku, dopóki ten proces nie zamknie pliku (lub nie zginie). Podobnie jak w przypadku twardych linków licznik liczby nazw wskazuje i-węzeł na dysku, Sterownik systemu plików (w jądrze Linuksa) przechowuje licznik liczby odwołań do tego i-węzła w pamięci i zwalnia i-węzeł z dysku dopiero po wydaniu wszystkich odwołań z działającego systemu.
To pytanie opiera się na niepoprawnym założeniu 2, że niezablokowanie stron spowoduje segfault. Nie będzie.
Ma to działać w ten sam sposób i przez większość czasu, ale jest kilka „problemów” z NFS.
Czasami można zobaczyć artefakty usuwania pliku, który jest nadal otwarty w NFS (pojawia się jako ukryty plik w tym katalogu).
Istnieje również sposób przypisania numerów urządzeń do eksportu NFS, aby upewnić się, że nie zostaną one „przetasowane” po ponownym uruchomieniu serwera NFS.
Ale główna idea jest taka sama. Sterownik klienta NFS nadal używa i-węzłów i będzie próbował utrzymywać pliki w pobliżu (na serwerze), podczas gdy i-węzeł będzie nadal przywoływany.
źródło
rename
jest dość dużo tylko plików i plików operacja, która jest gwarancją atomowy (zakładając, że nie przekraczają granice systemu plików lub urządzeń), więc „tworzenie pliku tymczasowego, a następnierename
” jest standardowy wzór do aktualizacji plików. Tego też używa na przykład każdy edytor tekstu w Uniksie.rename
jest częścią POSIX. To prawda, że jest uwzględniony przez odniesienie do ISO C (sekcja 7.21.4.2 w bieżącym projekcie), ale tam jest.Nie, tak się nie stanie, ponieważ jądro nie pozwoli ci otworzyć do napisania zamiany czegokolwiek w aktualnie wykonywanym pliku. Takie działanie zakończy się niepowodzeniem w przypadku
ETXTBSY
[1]:Kiedy dpkg itp. Aktualizuje plik binarny, nie zastępuje go, ale używa,
rename(2)
co po prostu wskazuje pozycję katalogu na zupełnie inny plik, a wszelkie procesy, które nadal mają mapowania lub otwarte uchwyty do starego pliku, będą go nadal używać bez problemów .[1] taka ochrona nie jest rozszerzona na inne pliki, które można również uznać za „tekst” (kod na żywo / plik wykonywalny): biblioteki współużytkowane, klasy java itp .; modyfikacji takiego pliku podczas odwzorowywane przez inny proces będzie spowodować jego awarię. W Linuksie dynamiczny linker słusznie przekazuje
MAP_DENYWRITE
flagęmmap(2)
, ale nie popełnij błędu - nie ma to żadnego wpływu.źródło
rename(2)
jest atomowy; jak tylko się zakończy, pozycja dir odnosi się do nowego pliku. Procesy, które w tym momencie nadal używały starego pliku, byłyby w stanie uzyskać do niego dostęp tylko za pomocą istniejących mapowań lub otwartych uchwytów (które mogą odnosić się do sierocej dentystyki, niedostępnej inaczej niż przez/proc/PID/fd
).odpowiedź filbranden jest poprawna, zakładając, że proces ciągłego wydawania dokonuje prawidłowej atomowej wymiany plików za pośrednictwem
rename
. Jeśli nie, ale modyfikuje plik w miejscu, sprawy wyglądają inaczej. Jednak twój model mentalny jest nadal w błędzie.Nie ma możliwości modyfikowania rzeczy na dysku i niespójności z pamięcią podręczną strony, ponieważ pamięć podręczna strony jest wersją kanoniczną i zmodyfikowaną. Wszelkie zapisy do pliku odbywają się przez pamięć podręczną strony. Jeśli już tam jest, istniejące strony są modyfikowane. Jeśli nie jest jeszcze obecny, próby modyfikacji częściowej strony spowodują buforowanie całej strony, a następnie modyfikację tak, jakby była już buforowana. Pisze, że obejmuje całą stronę lub więcej, może (i prawie na pewno tak) zoptymalizować krok odczytu stronicując je. W każdym razie istnieje tylko jedna kanoniczna modyfikowalna wersja pliku (*), jedna w pamięci podręcznej strony .
(*) Lekko skłamałem. W przypadku NFS i innych zdalnych systemów plików może być ich więcej niż jeden i zazwyczaj (w zależności od tego, który z nich jest używany i jakie opcje montowania i po stronie serwera są używane) niepoprawnie implementują atomowość i porządkowanie semantyki zapisu. Dlatego wielu z nas uważa, że są one zasadniczo zepsute i nie chcą ich używać w sytuacjach, w których będą pisane równolegle z użyciem.
źródło