Допустим, я запускаю программное обеспечение, а затем запускаю менеджер пакетов для обновления программного обеспечения, я замечаю, что Linux не останавливает запущенный процесс обновления пакета — он по-прежнему работает нормально. Как Linux это делает?
решение1
Причина в том, что Unix не блокирует исполняемый файл во время его выполнения, или даже если он это делает, как Linux, эта блокировка применяется к inode, а не к имени файла. Это означает, что процесс, который держит его открытым, получает доступ к тем же (старым) данным даже после того, как файл был удален (фактически отсоединен) и заменен новым с тем же именем, что по сути и делает обновление пакета.
Это одно из главных различий между Unix и Windows. Последняя не может обновить заблокированный файл, поскольку в ней отсутствует слой между именами файлов и инодами, что создает серьезные проблемы при обновлении или даже установке некоторых пакетов, поскольку обычно для этого требуется полная перезагрузка.
решение2
Исполняемые файлы обычно открываются один раз, прикрепляются к файловому дескриптору и не имеют файлового дескриптора для своего двоичного файла, повторно открытого в течение одного периода выполнения. Например, если вы выполняете bash
, exec()
обычно создается только файловый дескриптор для inode, на который указывает /bin/bash
once -- при вызове.
Это часто означает, что для простых двоичных файлов, которые не пытаются перечитать себя во время выполнения (используя путь, по которому они были вызваны), кэшированное содержимое остается действительным как висячий inode. Это означает, что по сути существует реплика предыдущей версии исполняемого файла.
В более сложных случаях это может вызвать проблемы. Например, файл конфигурации может быть обновлен и впоследствии перечитан, или программа может повторно выполнить себя через путь, из которого она была запущена. Также могут возникнуть проблемы, если программы взаимосвязаны, и одна выполняется до обновления, а другая после (возможно, первой программой). Это также верно для некоторых библиотек.
Однако в простых случаях можно безопасно выполнить обновление без перезапуска процесса.