Безопасно ли перекомпилировать исполняемый файл во время его работы? - PullRequest
27 голосов
/ 28 июля 2010

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

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

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

Ответы [ 8 ]

28 голосов
/ 28 июля 2010

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

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

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

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

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

7 голосов
/ 28 июля 2010

Это зависит.

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

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

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

6 голосов
/ 29 июля 2010

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

Так что вы можете

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

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

5 голосов
/ 29 июля 2010

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

Как говорили многие другиеВы можете удалить файл из файловой системы (unlink(2)), и ядро ​​сохранит ссылку на него и не удалит его с диска до тех пор, пока не останется больше ссылок (когда процесс завершится, он выпустит свою ссылку на файл),Это означает, что вы можете эффективно «перезаписать» используемый исполняемый файл, сначала удалив его, а затем создав новый файл с тем же именем, что и у старого.при перезаписи существующего файла.Если он просто открывает файл для записи и усекает его (O_WRONLY|O_CREAT|O_TRUNC), произойдет сбой с ошибкой ETXTBSY.Если он сначала удалит существующий выходной файл и создаст новый, он будет работать без ошибок.

0 голосов
/ 28 июля 2010

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

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

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

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

0 голосов
/ 28 июля 2010

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

Я не знаю о Linux.

0 голосов
/ 28 июля 2010

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

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

0 голосов
/ 28 июля 2010

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

...