Odpowiedzi:
Jak wspomniano w @Kusalananda, zwykle aktualizacje są wykonywane przez usunięcie starego pliku i utworzenie nowego o tej samej nazwie. Spowoduje to utworzenie nowego pliku z nowym i-węzłem, pozostawiając systemowi możliwość korzystania ze starego, o ile jest on otwarty.
Jako uproszczony przykład, takie rzeczy
rm /bin/cat
cp /new/version/of/cat /bin/cat
utworzy logicznie nowy plik i działa, nawet jeśli cat
może być uruchomiony. To samo dotyczy bibliotek. (Powyższe jest przykładem, a nie solidnym sposobem uaktualnienia pliku w prawdziwym świecie).
Ktoś może spróbować zmienić plik binarny na miejscu zamiast tworzyć nowy o tej samej nazwie. W takim przypadku przynajmniej Linux faktycznie uniemożliwia dokonywanie zmian w używanym pliku wykonywalnym:
window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
Nie wydaje się to jednak działać z dynamicznie ładowanymi bibliotekami ...
Zrobiłem kopię libc.so.6
do testowania i wypełniłem ją zerami, gdy była w użyciu:
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ldd ./cat
linux-vdso.so.1 (0x00007ffcfaf30000)
libc.so.6 => /tmp/lib/libc.so.6 (0x00007f1145e67000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1146212000)
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ./cat
foo
foo
Segmentation fault
(Tymczasem w innym oknie, po foo
, przed segfault)
window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
Naprawdę nic nie może zrobić sam program, ponieważ skutecznie edytowałem jego kod online.
(Prawdopodobnie byłoby to zależne od systemu, przetestowałem na Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. W szczególności systemy Windows IIRC są jeszcze bardziej agresywne w zapobieganiu modyfikacji używanych plików.)
Wydaje mi się, że odpowiedzią jest, że aktualizacje są zwykle wykonywane w sposób pozwalający uniknąć problemów, a to pomaga wewnętrzne elementy systemu plików. Ale (w systemie Linux) wydaje się, że nie ma żadnych zabezpieczeń przed faktycznym uszkodzeniem bibliotek dynamicznych.
install
Narzędzie jest powszechnie stosowany do rzeczy jak ta. Nie musisz jawnie rm
pliku docelowego. Ponadto zachowuje uprawnienia do istniejącego pliku, może wykonać kopię zapasową, ustawić nowy tryb itp. Przykładowe użycie:install /new/version/of/cat /bin/cat
rm
+ cp
był pomyślany jako przykład. Rozsądne może być także umieszczenie nowego pliku atomowo za pomocą zmiany nazwy, unikając krótkiego okna, w którym żadna wersja nie jest dostępna. (Choć install
wydaje się, że GNU tego nie robi, hmpf.)
rm
), to nie jest jeszcze usunięty. Będzie istniał na dysku i nadal będzie mógł być odczytany przez wszystkie procesy, które go mają otwarte. Zostanie usunięty tylko wtedy, gdy liczba twardych linków osiągnie zero, a liczba precesji przy otwartym pliku osiągnie zero.
install
Narzędzie jest szczególnie niebezpieczne! Zastępuje on plik docelowy zamiast zastępować go atomowo. mv
(z kodem źródłowym i docelowym w tym samym katalogu, źródło zwykle plik tymczasowy) jest jedynym bezpiecznym sposobem instalowania plików.
strace
mówi, install
w GNU coreutils rozłącza plik docelowy, a następnie kopiuje nowy na swoje miejsce. Co oznacza, że jest krótkie okno, w którym plik jest częściowy. Nie ustawia pliku atomowo w miejscu przy zmianie nazwy.
Pliki nie zostaną „poprawnie usunięte”, jeśli zostaną rozłączone, gdy są jeszcze otwarte. Po ich zamknięciu wykorzystane miejsce na dysku zostanie ponownie uznane za „wolne”. Dotyczy to również obecnie działających aplikacji i ich bibliotek współdzielonych.
Jedyną rzeczą, która nie powiodła się, byłaby sytuacja, gdy program używałby dlopen()
do ładowania biblioteki współdzielonej na żądanie lub gdyby program miał dostęp do innych plików na żądanie, takich jak słowniki, pliki motywów lub inne pliki, które nagle zniknęły.
Dla zilustrowania: Uruchamianie vim
w jednej sesji powłoki podczas usuwania instalacji vim
w innej sesji powłoki nie „uszkodzi” ani nie zakończy bieżącej vim
sesji. Ale niektóre rzeczy zaczną się nie powieść, na przykład sprawdzanie pisowni, które wymaga vim
otwarcia plików podczas instalacji.
ln -sf
przy zamianie bibliotek, ponieważ-f
pozwoliło to na „zastąpienie” istniejącego miejsca docelowego dowiązania symbolicznego nowym, bez jego „łamania” (inaczej niż w przypadkurm
późniejszego aln -s
). Przed poleceniem biblioteka.so wskazała więc na starą wersję, np. biblioteka.so.4 ... po komendzie po prostu wskazywała na bibliotekę.so.5 (lub cokolwiek innego) - nigdy nie wskazując prawidłowej biblioteki.