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

Как программы Haskell скомпилированы и выполнены внутри?

У меня возникли проблемы с пониманием того, как Haskell (GHC) компилирует программы и как эти программы запускаются.

  • GHC - это канонический пример нетривиальной программы, написанной в Haskell. Однако части GHC, похоже, не записываются в Haskell, а именно среда выполнения (в C/C -). Почему это? Почему? (Я знаю этот сайт и его друзей, но не может их сильно понять.)
  • Говоря о среде выполнения: зачем нужен компилируемый язык? Должна ли компилированная программа быть машинным кодом и ничем другим? Из того, что я понимаю, среда выполнения несколько похожа на виртуальную машину или интерпретатор байт-кода, который имеет дело с какой-то формой мета-кода и делает фактические расчеты на основе этого. Итак: что делает время выполнения GHC точно и почему это необходимо в первую очередь?
  • Что касается FFI: как обрабатываются вызовы C? Первоначально я думал, что использование FFI генерирует один исполняемый файл, где Haskell и C скомпилируются вместе. Тем не менее, я несколько раз читаю, что программы GHC делают вызов из программы функции C. Это особенно важно для понимания проблемы, с которой FFI имеет параллельное программирование. Итак: как функции FFI отличаются от обычных функций Haskell?
4b9b3361

Ответ 1

Чтобы скомпилировать и выполнить язык программирования на складе, вам нужно несколько вещей:

  • компилятор для перевода исходного языка в код сборки, исполняемый собственным хостом
  • библиотека поддержки (также называемая runtime) для примитивных языковых служб, таких как управление памятью, управление вводами и потоками. Вещи, которые должны быть задействованы из системных служб нижнего уровня.

C, Java и GHC Haskell являются примерами таких систем. В случае GHC здесь описывается целая архитектура.. Части также описаны индивидуально и подробно.

Ответ 2

Я могу предложить некоторую точность в отношении времени выполнения.

Виртуальная машина - это "тип", но не единственный. Система исполнения - это просто среда (и набор сервисов), которую может принять ваша программа, во время ее выполнения. Даже очень низкоуровневые языки, такие как C и С++, имеют системы времени исполнения (подумайте о malloc... кто-то/что-то делает выделение для вас или даже деление на нулевые проверки).

В целом языки более высокого уровня имеют более богатое время выполнения (что означает, что среда выполнения предлагает больше услуг для исполняющей программы); они варьируются от управления памятью (например, сбор мусора) до инфраструктуры отражения/интроспекции (думаю, ruby ​​и т.д.) для проверки границ массива, но в значительной степени на всех языках имеется какая-то система времени выполнения (если только операционная система).

Ответ 3

1: Почему RTS не написана в Haskell?

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

2: Зачем компилируемой программе требуется среда выполнения? Из того, что я понимаю, это что-то вроде интерпретатора байт-кода Java.

GHCi использует что-то почти так же, как интерпретатор байт-кода Java. Скомпилированных программ GHC нет; скомпилированная программа - это исходный машинный код.

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

(Это немного похоже на то, что скомпилирована программа C, это исходный машинный код, но вы все равно не можете запускать его без операционной системы, такой как Windows или Linux или что-то в этом роде.)

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

В каждой скомпилированной программе Haskell есть копия этой программы сборщика мусора, которая является лишь одной частью Haskell RTS. Аналогично, несколько потоков Haskell могут выполняться внутри одного потока ОС, поэтому в RTS есть планировщик потоков внутри него. Я мог бы продолжить...

3: Как обрабатывается FFI? Я думал, что все было скомпилировано.

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