Связывание и загрузка на переведенных языках
В скомпилированных языках исходный код превращается компилятором в объектный код, а различные объектные файлы (если их несколько) связаны компоновщиком и загружаются в память загрузчиком для выполнения.
Если у меня есть приложение, написанное с использованием интерпретированного языка (например, ruby или python), и если исходный код разделен по файлам, когда именно эти файлы объединяются. Другими словами, когда связь сделана? Есть ли в интерпретируемых языках компоновщики и загрузчики, или переводчик все делает?
Я действительно смущен этим и не в состоянии обдумать это!! Кто-нибудь может пролить свет на это?!
2 ответа
Интерпретируемый язык - это более или менее большая конфигурация для исполняемого файла, который называется интерпретатором. Этот исполняемый файл (например, /usr/bin/python
) это программа, которая на самом деле работает. Затем он читает сценарий, который должен выполнить (например, /home/alfe/bin/factorial.py
) и выполняет его в простейшей форме построчно.
Во время этого процесса могут встречаться ссылки на другие файлы (другие модули, например, /usr/python/lib/math.py
), а затем он будет читать и интерпретировать те.
во многих таких языках есть встроенные механизмы, позволяющие сократить накладные расходы на этот процесс путем создания версий байт-кода сценариев, которые они интерпретируют. Так что вполне может быть файл /usr/python/lib/math.pyc
например, который переводчик поместил туда после первой обработки и который он может прочитать и интерпретировать быстрее, чем оригинал /usr/python/lib/math.py
, Но это на самом деле не является частью концепции интерпретируемых языков¹.
Иногда двоичная библиотека является частью интерпретируемого языка; в зависимости от сложности интерпретатора он может связать эту библиотеку во время выполнения и затем использовать ее. Это наиболее типично для системных модулей и прочего, которые должны быть оптимизированы.
Но в целом можно сказать, что двоичный машинный код не генерируется вообще. И ничего не связано во время компиляции. На самом деле реального времени компиляции не существует, хотя эту первую обработку входных сценариев можно назвать этапом компиляции.
Примечания:
The) Концепция интерпретации сценариев не включает ни "компиляцию" (предварительный перевод источника в более быструю для интерпретации форму), ни "кэширование" этой формы путем хранения файлов, подобных .pyc
файлы. В связи с вашим вопросом, касающимся связывания и разбиения программ на несколько файлов или модулей, эти аспекты предварительной компиляции и кэширования являются лишь техническими деталями для ускорения процесса. Сама концепция такова: прочитайте одну строку входного скрипта и выполните его. Затем прочитайте следующую строку и так далее.
Ну, в Python модули загружаются и выполняются или анализируются, когда интерпретатор находит какой-либо метод или указание для этого. Там нет ссылок, но есть загрузка, конечно (когда файл запрашивается в коде).
Python делает что-то умное, чтобы улучшить его производительность. Компилируется в байт-код (.pyc
файлы) при первом запуске файла. Это существенно улучшает выполнение кода в следующий раз, когда модуль импортируется или выполняется.
Так что поведение более или менее:
- Файл выполнен
- Внутри файла интерпретатор находит ссылку на другой файл
- Он анализирует его и потенциально выполняет его. Это означает, что каждое определение класса, переменной или метода станет доступным во время выполнения.
И это, как процесс выполняется (очень общий). Конечно, существуют оптимизации и кэши для повышения производительности.
Надеюсь это поможет!