Ответы:
Как упоминает @Kusalananda, обычно обновления выполняются путем удаления старого файла и создания нового с тем же именем. Это фактически создаст новый файл с новым индексом, оставляя систему свободной, чтобы использовать старый, пока он открыт.
В качестве упрощенного примера, такие вещи, как
rm /bin/cat
cp /new/version/of/cat /bin/cat
создаст логически новый файл и работает, даже если cat
может быть запущен. То же самое касается библиотек. (Выше приведен пример, а не надежный способ обновления файла в реальном мире.)
Кто-то может попытаться изменить двоичный файл вместо создания нового с тем же именем. В этом случае, по крайней мере, Linux фактически предотвращает внесение изменений в исполняемый файл, который используется:
window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
Тем не менее, это не похоже на работу с динамически загружаемыми библиотеками ...
Я сделал копию libc.so.6
для тестирования и заполнил ее нулями, пока она использовалась:
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
(Между тем в другом окне, после foo
, до сегфоута)
window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
На самом деле сама программа ничего не могла с этим поделать, поскольку я эффективно редактировал ее код в Интернете.
(Вероятно, это будет зависеть от системы, я тестировал на Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. В частности, системы Windows IIRC еще более агрессивны в отношении предотвращения изменения используемых файлов.)
Поэтому я полагаю, что ответ заключается в том, что обновления обычно выполняются таким образом, чтобы избежать каких-либо проблем, и этому помогают внутренние компоненты файловой системы. Но (в Linux), похоже, нет никаких гарантий против фактического повреждения динамических библиотек.
install
Утилита обычно используется для вещей , как это. Вам не нужно явно rm
указывать файл назначения. Кроме того, он сохраняет права доступа к существующему файлу, может сделать резервную копию, установить новый режим и т. Д. Пример использования:install /new/version/of/cat /bin/cat
rm
+ cp
Предназначались в качестве примера. Также может быть разумно поместить новый файл атомарно с переименованием, избегая короткого окна, в котором ни одна версия не доступна. (Хотя GNU install
, похоже, даже этого не делает, hmpf.)
rm
), он еще не удален. Он будет существовать на диске и все еще может быть прочитан всеми открытыми процессами. Он будет удален только тогда, когда количество жестких ссылок достигнет нуля, а число прецессов с открытым файлом достигнет нуля.
install
Утилита специально небезопасна! Он перезаписывает целевой файл на месте, а не заменяет его атомарно. mv
(с источником и папкой в одном каталоге, источником обычно является временный файл) - это единственный безопасный способ установки файлов.
strace
, install
в GNU coreutils отсоединяет целевой файл, а затем копирует новый на его место. Это означает, что есть короткое окно, в течение которого файл является частичным. Это не устанавливает файл атомарно на месте с переименованием.
Файлы не будут "правильно удалены", если они не связаны, пока они все еще открыты. Когда они закрыты, используемое ими дисковое пространство снова будет считаться «свободным». Это относится и к текущим приложениям и их общим библиотекам.
Единственное, что я мог увидеть сбой, - это если программа использовала dlopen()
для загрузки разделяемую библиотеку по требованию или если программе приходилось обращаться к другим файлам по требованию, таким как словари, файлы тем или другие файлы, которые внезапно исчезали.
Для иллюстрации: запуск vim
в одном сеансе оболочки при удалении установки vim
в другом сеансе оболочки не «повредит» и не завершит текущий запущенный vim
сеанс. Но некоторые вещи начнут давать сбой, например, проверка орфографии, которая требует vim
открытия файлов при установке.
ln -sf
при замене через библиотеку, потому что-f
позволил вам «перезаписи» существующему назначение символической ссылки с новым, без него когда - либо «сломан» ( в отличие , если ты сrm
последующим аln -s
) Поэтому перед командой library.so указал на старую версию, например. library.so.4 ... после команды, он просто указал на library.so.5 (или любой другой ) , вместо этого - никогда не не указывая на действительной библиотеке.