В основном я занимаюсь разработкой для устройств с портированным Linux, поэтому стандартная библиотека C предоставляет множество своих функций за счет реализации системных вызовов, которые имеют стандартизированное поведение.
Однако для голого металла ОС не существует. Существует ли какой-либо стандарт, связанный с тем, как должна быть реализована библиотека ac, или вам приходится заново изучать особенности реализации библиотек, когда вы переключаетесь на новую плату, которая обеспечивает другой BSP?
Ответы:
Да, есть стандарт, просто стандартная библиотека Си . Функции библиотеки не требуют «полноценной» ОС или какой-либо ОС вообще, и существует целый ряд реализаций, адаптированных к «голому металлу» кода, возможно , Newlib является наиболее известным.
Рассматривая Newlib в качестве примера, он требует от вас написать небольшое подмножество основных функций, в основном то, как файлы и распределение памяти обрабатываются в вашей системе. Если вы используете общую целевую платформу, есть вероятность, что кто-то уже сделал эту работу за вас.
Если вы используете linux (возможно, также OSX и, возможно, даже cygwin / msys?) И тип
man strlen
, у него должен быть раздел, называемый чем-то вродеCONFORMING TO
, который скажет вам, что реализация соответствует определенному стандарту. Таким образом, вы можете выяснить, является ли то, что вы используете, стандартной функцией или зависит от конкретной ОС.источник
stdlib
реализует,stdio
не будучи зависимым от ОС. какfopen()
,fclose()
,fread()
,fwrite()
,putc()
иgetc()
? а какmalloc()
работает без общения с ОС?getchar
иputchar
которые знают о UART вашего оборудования; затем слои Newlibprintf
поверх них. Файловый ввод / вывод также будет опираться на несколько примитивов.stdin
иstdout
иstderr
(которая заботится оputchar()
иgetchar()
), которая направляет ввод / вывод из / в UART, если на вашей платформе есть файловое хранилище, как, например, с флеш-памятью, вы должны также написать для этого клей. и вы должны иметь средства дляmalloc()
иfree()
. Я думаю, что если вы позаботитесь об этих проблемах, вы можете в значительной степени запустить портативный C во встроенной цели (нет,argv
ниargc
).Во-первых, стандарт C определяет нечто, называемое «автономной» реализацией, в отличие от «размещенной» реализации (с которой большинство из нас знакомо - полный спектр функций C, поддерживаемых базовой ОС).
«Отдельно стоящая» реализация должна определять только подмножество заголовков библиотеки C, а именно те, которые не требуют поддержки, или даже определения функций (они просто выполняют
#define
s иtypedef
s):<float.h>
<iso646.h>
<limits.h>
<stdalign.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
<stdnoreturn.h>
Когда вы сделаете следующий шаг в направлении размещенной реализации, вы обнаружите, что существует очень мало функций, которые действительно должны каким-либо образом взаимодействовать с «системой», а остальная часть библиотеки может быть реализована поверх этих «примитивов». ». При реализации PDCLib я приложил некоторые усилия, чтобы изолировать их в отдельном подкаталоге для легкой идентификации при переносе lib на новую платформу (примеры для порта Linux в скобках):
getenv()
(extern char * * environ
)system()
(fork()
/execve()
/wait()
)malloc()
иfree()
(brk()
/sbrk()
)_Exit()
(_exit()
)time()
(еще не реализовано)И для
<stdio.h>
(возможно, наиболее "вовлеченного в ОС" из заголовков C99):open()
)close()
)unlink()
)link()
/unlink()
)write()
)read()
)lseek()
)Некоторые детали библиотеки являются необязательными, поскольку стандарт просто предлагает их реализовать стандартным способом, но не делает такую реализацию обязательным требованием.
По
time()
закону функция может просто вернуться,(time_t)-1
если нет доступных механизмов учета времени.Описанные обработчики сигналов
<signal.h>
не должны вызываться ничем, кроме вызоваraise()
, нет требования, чтобы система фактически отправляла что-то подобноеSIGSEGV
в приложение.Заголовок C11
<threads.h>
, который (по очевидным причинам) очень зависит от ОС, вообще не требуется указывать, если реализация определяет__STDC_NO_THREADS__
...Есть еще примеры, но у меня их сейчас нет под рукой.
Остальная часть библиотеки может быть реализована без какой-либо помощи со стороны среды. (*)
(*) Предостережение: реализация PDCLib еще не завершена, поэтому я мог пропустить одну или две вещи. ;-)
источник
Стандарт C фактически определяется отдельно от операционной среды. Не делается никаких предположений о наличии хост-ОС, и те части, которые зависят от хоста, определяются как таковые.
То есть C Standard уже довольно голый металл.
Конечно, те языковые части, которые мы так любим, библиотеки, часто находятся там, где основной язык подталкивает к размещению конкретных вещей. Следовательно, типичный материал для кросс-компиляции "xxx-lib" найден для многих инструментов на платформе.
источник
Пример минимального запуска Newlib
Здесь я приведу высоко автоматизированный и документированный пример, который показывает newlib в действии в QEMU .
С newlib вы реализуете свои собственные системные вызовы для вашей платформы baremetal.
Например, в приведенном выше примере у нас есть пример программы
exit.c
:и в отдельном C-файле
common.c
мы реализуемexit
с полухостингом ARM :Другие типичные системные вызовы, которые вы реализуете:
write
выводить результаты на хост. Это можно сделать с помощью:brk
дляmalloc
.Легко на голом металле, так как нам не нужно заботиться о подкачке!
TODO Интересно, реально ли достичь выполнения системных вызовов с упреждающим планированием, не вдаваясь в полноценную RTOS, такую как Zephyr или FreeRTOS .
Самое замечательное в Newlib - это то, что он реализует все не связанные с ОС вещи, подобные
string.h
вам, и позволяет вам реализовывать только заглушки ОС.Кроме того, вам не нужно реализовывать все заглушки, а только те, которые вам понадобятся. Например, если ваша программа нужна только вам
exit
, вам не нужно предоставлятьprint
.В исходном дереве Newlib уже есть некоторые реализации, в том числе реализация ARM-полухостинга
newlib/libc/sys/arm
, но по большей части вы должны реализовать свою собственную. Это, однако, обеспечивает прочную основу для этой задачи.Самый простой способ настроить Newlib - это создать собственный компилятор с помощью crosstool-NG, вам просто нужно сообщить ему, что вы хотите использовать Newlib в качестве библиотеки C. Моя установка обрабатывает это автоматически для вас с помощью этого скрипта , который использует конфиги newlib, представленные на
crosstool_ng_config
.Я думаю, что C ++ также будет работать, но TODO протестирует его.
источник
Когда вы используете его без использования металла, вы обнаруживаете некоторые неосуществленные зависимости и вынуждены их обрабатывать. Все эти зависимости связаны с настройкой внутренних устройств в соответствии с индивидуальностью вашей системы. Например, когда я пытался использовать sprintf (), который использует malloc () внутри. Malloc имеет символ функции "t_sbrk" в качестве ловушки в коде, который должен быть реализован пользователем для обеспечения аппаратных ограничений. Здесь я могу реализовать это или создать свой собственный malloc (), если я считаю, что мог бы сделать лучше для встроенного оборудования, в основном для других целей, а не только для sprintf.
источник