Nano Hash - криптовалюты, майнинг, программирование

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

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

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

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


  • Какой язык и реализация? Для большинства компиляторов Common Lisp нет проблем с заменой исполняемого файла на лету. Другие системы работают иначе. 28.07.2010
  • Это исполняемый файл C++. Я не уверен, как это влияет на операционную систему, хотя... 28.07.2010
  • Разница в том, что компиляция и выполнение — это совершенно разные шаги, и поэтому все зависит от того, как ОС обрабатывает исполняемые файлы. 28.07.2010

Ответы:


1

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

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

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

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

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

28.07.2010
  • Интересно - это дает мне хорошее представление о том, как Linux обрабатывает файлы. 28.07.2010
  • [Linux] От того, как вы замените файл, зависит, будет он работать или нет. Вы не можете открыть используемый исполняемый файл для записи. 29.07.2010
  • Что, если на полпути к выводу компоновщика файла .exe я попытаюсь запустить его? Будет ли он пытаться запустить наполовину написанный исполняемый файл? 29.07.2010
  • @Thanatos: обычно файлы записываются во временное имя, а затем mv записываются на правильный путь и имя. Это означает, что вы получите либо новую, либо старую версию. Если нет, и он пишет это на месте, я сомневаюсь, что вы сможете выполнить программу. В обычных условиях вы не сможете запустить наполовину написанный исполняемый файл. 29.07.2010

  • 2

    Это зависит.

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

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

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

    28.07.2010

    3

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

    Так что вы могли

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

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

    28.07.2010
  • Интересная информация, которую можно использовать для демонстрации того, как неудачный выбор дизайна может привести к странным обходным путям. Разделив информацию о файле на имя файла и индексный дескриптор, нет необходимости в таких сложных командах. Также нет необходимости в перезагрузке. Обновление может происходить на лету. 19.04.2011

  • 4

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

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

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

    29.07.2010

    5

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

    28.07.2010

    6

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

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

    28.07.2010

    7

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

    Я не знаю насчёт линукса.

    28.07.2010

    8

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

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

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

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

    28.07.2010
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..