Подтвердить что ты не робот

Безопасно ли перекомпилировать исполняемый файл во время его работы?

Что произойдет, если я перекомпилирую исполняемый файл во время его работы? Записывает ли операционная система все исполняемое содержимое в память при запуске, поэтому никогда не будет читать новый исполняемый файл? Или он прочитает разделы нового исполняемого файла, думая, что он не изменился, что приведет к поведению undefined?

Что делать, если у меня работает script, который повторно вызывает исполняемый файл в цикле, и я перекомпилирую исполняемый файл, пока выполняется script. Гарантировано ли, что будущие итерации цикла вызовут новый исполняемый файл, и только результат вызова, который выполнялся при запуске коммутатора, может быть поврежден?

Моя ОС - это Linux, но мне также интересно, что происходит в Windows.

4b9b3361

Ответ 1

Так как это обычный компилятор, который записывает исполняемый файл, давайте его в Linux.

Первое, что нужно знать, это то, что имя файла Linux не относится напрямую к файлу, а относится к записи каталога, которая не зависит от имени файла. Файлу на самом деле не нужно иметь имя файла, но если это не так, будет сложно сослаться на него.

Если процесс использует файл, и вы его замените или удалите, процесс продолжит использование этого файла через его запись в каталоге. Любой новый процесс с использованием файла или его поиск получит новую версию (если вы ее замените) или не сможете ее найти (если вы ее удалили). Как только все процессы пройдут через старый файл, он будет удален из файловой системы.

Поэтому, если вы перекомпилируете и создаете новый исполняемый файл с таким же именем, вы не будете влиять на текущий процесс. Он будет продолжать использовать старый исполняемый файл. Любой новый процесс, который пытается открыть файл, получит новый. Если у вас есть system("foo"); в цикле, каждый раз, когда он его выполняет, он увидит, что означает имя файла foo.

Windows обрабатывает файлы по-разному. В общем случае, если есть процесс с использованием файла, файл заблокирован и не может быть удален или заменен.

Ответ 2

Это зависит.

Если ОС считывает весь исполняемый файл в память и не ссылается на образ диска, тогда да, вы можете перекомпилировать его, пока он "используется".

На практике это не всегда происходит. Если ОС держит дескриптор файла открытым (как и Windows) в исполняемом файле, это предотвратит удаление файла и/или перезапись.

С Linux/Unix можно перезаписать файл, который "используется". См. Ответ Дэвид Торнли для подробного объяснения.

Ответ 3

В Windows вы не можете удалить заблокированный файл, но большинство людей не знает, что вы можете переместить или переименовать исполняемый exe.

Итак, вы могли

  • переместите старый exe в каталог temp на том же диске
  • запланировать его для удаления при следующей перезагрузке: MoveFileEx (имя, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  • переместите новый exe на свое место.

Старая программа будет работать, но новые процессы будут использовать новый файл.

Ответ 4

В Linux, исполняемые файлы требуются, если необходимо, в память. Исполняемый файл на диске становится хранилищем для приложения. Это означает, что вы не можете изменить исполняемый файл на диске или повлиять на запущенное приложение. Если вы попытаетесь выполнить open(2) исполняемый исполняемый файл для записи, вы получите сообщение об ошибке ETXTBSY (текстовый файл занят) (проверьте справочную страницу для open(2)).

Как и многие другие, вы можете удалить файл из файловой системы (unlink(2)), и ядро ​​будет поддерживать ссылку на него, а не удалять его с диска, пока не будет больше ссылок (когда процесс завершается, он выдает ссылку на файл). Это означает, что вы можете эффективно "перезаписать" исполняемый исполняемый файл, сначала удалив его, а затем создав новый файл с тем же именем, что и старый файл.

Итак, дело сводится к тому, как компилятор создает исполняемый файл, когда "перезаписывает" существующий файл. Если он просто открывает файл для записи и обрезает его (O_WRONLY|O_CREAT|O_TRUNC), он будет терпеть неудачу с ошибкой ETXTBSY. Если он сначала удаляет существующий выходной файл и создает новый, он будет работать без ошибок.

Ответ 5

Я бы предположил, что это не позволит вам заменить файл, поскольку окна заблокировали его, когда он был в использовании.

Ответ 6

Это зависит. Из того, что я испытал, на Linux вы все равно можете запускать программу, если вы ее удалите (и она не слишком велика). Но я не думаю, что это определенное поведение.

Что касается цикла, в зависимости от того, как вы вызываете исполняемый файл, вы, вероятно, закончите сбой вашего script, когда он отправится на выполнение программы, написанной только наполовину.

Ответ 7

В Windows вы не можете, если исполняемый файл все еще запущен, файл будет заблокирован. Если exe фактически не запущен, новые прогоны должны забрать новый, в зависимости от того, как ваш script закодирован между прочим.

Я не знаю о Linux.

Ответ 8

Исполняемый файл может быть загружен полностью в память при запуске, однако, если он достаточно большой и работает достаточно долго, ОС может решить заменить некоторые неиспользуемые части.

Поскольку ОС предполагает, что программный файл все еще существует, нет никаких оснований фактически записывать эти блоки памяти в файл подкачки. Поэтому они просто недействительны и повторно используются. Если программе снова нужны эти страницы, ОС загружает их из исполняемого файла.

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

Не уверен, что Linux, но IIRC, он делает замену таким же образом.