Как вручную (программно) разместить объекты в моем многоядерном проекте? - PullRequest
4 голосов
/ 08 декабря 2011

Я разрабатываю многоядерный проект для нашей встроенной архитектуры с использованием цепочки инструментов gnu. В этой архитектуре все независимые ядра совместно используют одно и то же пространство глобальной памяти. Каждое ядро ​​имеет собственную внутреннюю память, к которой можно обращаться из любого другого ядра через его глобальный 32-разрядный адрес.

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

Все становится сложнее, когда:

  1. Код не совпадает в двух ядрах, поэтому объекты не могут быть распределены по одинаковым адресам,

  2. Иногда мы используем «хост», который представляет собой другой процессор, на котором выполняется некоторый управляющий код, требующий доступа к объектам в ядрах, а также к общим объектам во внешней памяти.

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

Возможный взлом - использовать встроенную сборку для определения объектов и их явного размещения (используя ключевые слова .org и .global), но это выглядит несколько уродливо (а мы еще не проверили эту идею ...) )

Итак, вот вопросы:

  1. Существует ли полустандартный способ или элегантное решение для размещения объектов в программе на C вручную?

  2. Могу ли я объявить в своем коде объекты "uber" -extarnel и заставить компоновщик разрешать их адреса, используя исполняемый файл другого проекта?

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

Ответы [ 4 ]

3 голосов
/ 26 октября 2012

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

2 голосов
/ 08 декабря 2011

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

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

Затем вы можете поделиться структурами, либо: a) поместив их в специальный раздел и используя скрипт компоновщика, чтобы поместить его в известное место;б) размещение структуры в статических данных и размещение указателя на нее в известном месте, скажем, в файлах запуска сборки;или c) as (b), но выделяет структуру в куче и копирует указатель в известное местоположение указателя во время выполнения.Преимущество заключается в том, что указатель может быть предварительно настроен для внешних потребителей, что позволяет избежать некоторой путаницы.

Надеюсь, что это поможет

1 голос
/ 08 декабря 2011

Ответ на вопрос 1: нет, нет.

В остальном, это очень сильно зависит от используемой операционной системы.В нашей системе в то время, когда я был встроен, у нас была только одна память процессора (на базе 80186 и 68030), но она была многозадачной, но из того же двоичного файла.Наша цепочка инструментов была расширена для обработки памяти определенным образом.Цепочка инструментов выглядела так (на 80186):

  • Microsoft C 16bit или Borland-C
  • Линкер, ссылающийся на наш конкретный crt.o, который определил некоторые специальные символы и сегменты.*
  • Microsoft linker, генерирующий exe-файл и файл карты с адресной схемой MS-DOS
  • Локатор, который корректировал адреса в исполняемом файле и генерировал плоский двоичный файл
  • Address Patcher.
  • Горелка EPROM (позже Flash Loader).

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

Фактически, если у вас нет контроля над локатором (загрузчик elf в linux или загрузчик exe / dll в windows), вы 'снова прикручен.

1 голос
/ 08 декабря 2011
  1. Вы находитесь далеко от проторенного пути - не ожидайте ничего «стандартного» для всего этого:)
  2. Этот ответ предлагает метод прохождениясписок необработанных адресов для компоновщика.При связывании внешнего исполняемого файла создайте файл сопоставления компоновщика, а затем обработайте его для создания этой необработанной таблицы символов.

Вы также можете попробовать связать всю программу (все основные программы) в один исполняемый файл.Используйте определения разделов и скрипт компоновщика, чтобы поместить программу каждого ядра в его адресное пространство внутренней памяти;Вы можете построить программу каждого ядра отдельно, постепенно связать ее с одним файлом .o, затем использовать objcopy, чтобы переименовать его разделы, содержащие идентификатор ядра для сценария компоновщика, и переименовать (скрыть) закрытые символы , если выДублируем один и тот же код на нескольких ядрах.Наконец, вручную введите начальный адрес для каждого ядра в код начальной загрузки вместо использования обычного начального символа.

...