Почему программный пакет работает нормально, даже когда он обновляется?

29

Скажем, у меня запущено программное обеспечение, а затем я запускаю диспетчер пакетов для обновления программного обеспечения и замечаю, что Linux не останавливает запущенный процесс обновления пакета - он все еще работает нормально. Как Linux делает это?

Говард
источник

Ответы:

35

Причина в том, что Unix не блокирует исполняемый файл во время его выполнения или даже если он работает как Linux, эта блокировка применяется к inode, а не к имени файла. Это означает, что процесс, сохраняющий его открытым, получает доступ к одним и тем же (старым) данным даже после того, как файл был удален (фактически не связан) и заменен новым с тем же именем, что по сути и делает обновление пакета.

Это одно из главных отличий Unix от Windows. Последний не может обновить заблокированный файл, так как ему не хватает слоя между именами файлов и inode, что создает большие трудности для обновления или даже установки некоторых пакетов, поскольку обычно требуется полная перезагрузка.

jlliagre
источник
10
Чтобы уточнить, в Linux вы не можете изменять исполняемый файл во время его работы. Но вы можете отсоединить файл и заменить его новым файлом с тем же именем.
CJM
В Linux вы можете изменить исполняемый файл во время его работы. Результат, скорее всего, будет непредсказуемым, если только вы действительно не знаете, что делаете. Добавлен пункт «То же имя», который не был явно указан.
Jlliagre
4
@jlliagre Если я не понимаю, вы не можете, насколько я знаю: sprunge.us/egiR
Крис Даун,
2
Однако есть одна замечательная особенность NFTS - если вы выполняете переименование из командной строки или другой программы, вы можете поместить туда файл с таким же именем, и это не повлияет на программы, у которых открыт исходный файл. (команда переименования в проводнике не работает для этого)
Стеффан Донал
1
@cjm Вы правы в отношении защиты "file text busy" в Linux, ответ обновлен. Под Solaris нет такого ограничения, с которым я лучше знаком. Вы все еще можете изменять общие библиотеки с обеими операционными системами.
Jlliagre
18

Исполняемые файлы обычно открываются один раз, прикрепляются к файловому дескриптору и не имеют файлового дескриптора для их двоичного файла, открытого заново в течение одного периода выполнения. Например, если вы выполняете bash, exec()обычно создает только файловый дескриптор для inode, на который указывает /bin/bashоднократный вызов.

Это часто означает, что для простых двоичных файлов, которые не пытаются перечитать себя во время выполнения (используя путь, по которому они были вызваны), содержимое, которое кэшируется, остается действительным как висячий инод. Это означает, что по существу существует копия предыдущей версии исполняемого файла.

В более сложных случаях это может вызвать проблемы. Например, файл конфигурации может быть обновлен и впоследствии перечитан, или программа может повторно выполнить себя через путь, из которого он был выполнен. Также могут быть проблемы, если программы связаны между собой, и одна из них выполняется до обновления, а другая - после (возможно, первой программой). Это также верно для некоторых библиотек.

Однако для простых случаев использования обновление безопасно, без перезапуска процесса.

Крис Даун
источник
1
Другая опасность, даже в простых случаях, заключается в том, что поскольку запущенное приложение использует кэшированную копию двоичного файла, то до тех пор, пока вы не перезапустите приложение вручную, оно по-прежнему будет использовать старую версию кода. Хотя это не должно иметь значения большую часть времени; если обновление включало исправления безопасности, несмотря на то, что патч был установлен, ваша система все еще уязвима, потому что старая версия все еще работает.
Дэн Нили
1
Боюсь, ваш первый абзац неточный. Ядра Unix / Linux не загружают исполняемые программы сразу, а отображают их в памяти. Это означает, что только страницы, которые фактически используются, в конечном итоге попадают в ОЗУ. В этом весь смысл защиты «Текстовый файл занят» в Linux. Нет никаких гарантий, что какая-то часть исполняемого файла не будет прочитана после запуска. Более того, некоторые страницы никогда не будут загружаться для достаточно больших программ, и это еще более верно для динамически загружаемых библиотек. Например, bashдвоичный файл составляет около 200 страниц по 4K, не уверен, что они все используются в среднем сеансе.
Jlliagre
@jlliagre Я говорил о ialloc()структуре ядра для чтения, а не о отображении памяти самих страниц. Разве я не прав, думая, что в современных файловых системах ext * inode в конечном итоге будет согласован в ядре (и внутри подсистемы VM)?
Крис Даун
Нет никакой гарантии, что части исполняемого содержимого не будут прочитаны долгое время после его запуска, и нет никакой гарантии, что те же самые страницы не будут прочитаны снова через некоторое время во время выполнения.
июля 13 июля
@jlliagre Правильно, но я не это имел в виду. Возможно, я немного смягчу свои слова в своем ответе, постараюсь прояснить то, что имел в виду.
Крис Даун