베어 메탈의 C 표준 라이브러리


24

나는 주로 리눅스를 이식 한 장치에서 개발을하고 있기 때문에 표준 C 라이브러리는 표준화 된 동작을 가진 시스템 호출을 구현하여 많은 기능을 제공합니다.

그러나 베어 메탈의 경우 기본 OS가 없습니다. ac 라이브러리를 구현하는 방법과 관련된 표준이 있습니까? 아니면 다른 BSP를 제공하는 새 보드로 전환 할 때 라이브러리 구현의 특성을 다시 배워야합니까?


4
귀하의 질문에 대한 잘못된 사이트입니다.
ott--

8
나는에 속해 있기 때문에 오프 주제로이 질문을 닫으 투표 해요 스택 오버플로 .
uint128_t

1
일반적으로 당신은없이합니다. 운영 체제가없는 이유는 무엇입니까? memcpy와 그런 확신. fopen, close 등을 구현하는 것이 반드시 필요한 것은 아니지만 파일 시스템은 예를 들어 램에 대해 사소한 것입니다. printf ()는 매우 무겁고, 톤과 톤이 필요한 코드입니다. 모든 I / O는 교체하거나 수행하지 않습니다. newlib는 매우 극단적이지만, 없이는 할 수 없다면 도움이되지만 어쨌든 백엔드에서 시스템을 구현해야하므로 추가 계층이 필요합니까?
old_timer

12
이 질문은 소프트웨어에 관한 것이지만, 일반적으로 SO에 의해 거부되는 임베디드 프로그래밍에만 국한됩니다. 여기에 이미 좋은 답변이 있으므로 마이그레이션이 적합하지 않습니다.
Dave Tweed

1
newlib가 아래 답변에 언급되어 있지만 newlib -nano가 유용 할 수도 있습니다. newlib-nano 는 리소스가 제한된 임베디드 시스템에 사용하기 위해 제거 된 버전입니다. Cortex M0 MCU의 프로젝트에서 사용합니다. 많은 컴파일러 (Atollic TrueSTUDIO가 하나임)는 newlib 또는 newlib-nano를 사용하는 옵션을 제공합니다.
jjmilburn

답변:


20

그렇습니다. 표준 인 C 표준 라이브러리가 있습니다. 라이브러리 함수는 "완전히 터진"OS 나 다른 OS를 전혀 필요로하지 않으며, "베어 메탈 (bare metal)"코드에 맞게 여러 가지 구현이 있으며 Newlib은 아마도 가장 잘 알려져 있습니다.

Newlib을 예로 들면, 주로 시스템에서 파일 및 메모리 할당이 처리되는 방식의 핵심 기능 중 일부를 작성해야합니다. 공통 대상 플랫폼을 사용하는 경우 누군가 이미이 작업을 수행했을 가능성이 있습니다.

linux (아마도 OSX 및 cygwin / msys?) 및 type man strlen을 사용하는 경우와 같은 섹션이 있어야 CONFORMING TO구현이 특정 표준을 준수 함을 알 수 있습니다. 이 방법을 사용하면 사용중인 것이 표준 기능인지 또는 특정 OS에 의존하는지 알아낼 수 있습니다.


1
OS에 의존하지 않고 어떻게 stdlib구현 하는지 궁금 stdio합니다. 같은 fopen(), fclose(), fread(), fwrite(), putc()getc()? 그리고 malloc()OS와 대화 하지 않고 어떻게 작동합니까?
robert bristow-johnson 2012

4
Newlib에는 그 아래에 "libgloss"라는 레이어가 있습니다. 여기에는 플랫폼에 대한 수십 개의 함수가 포함되어 있습니다. 예를 들어, getcharputchar이는 하드웨어의 UART에 대해 알고; 그 printf위에 Newlib 레이어 가 있습니다. 파일 I / O도 마찬가지로 몇 가지 기본 요소에 의존합니다.
Brian Drummond

그래, 나는 파이프의 두 번째 단락을주의 깊게 읽지 않았다. 처리 외에 stdinstdoutstderr (어떤을 담당 putchar()하고 getchar()다음 또한 대한 쓰기 접착제에 있고, 플랫폼은 플래시와 같은 파일 저장이 있으면하는 UART에 /에서 / O를 내가 지시하는). 당신은 할 수있는 수단이 있어야 malloc()하고 free(). 이러한 문제를 해결하면 포함 된 대상 ( argv또는 없음 argc) 에서 휴대용 C를 거의 실행할 수 있다고 생각합니다 .
robert bristow-johnson

2
코드 공간이 1 또는 2kB 인 MCU를 다루는 경우 Newlib도 엄청 납니다.
Brian Drummond

2
@dwelch 자신 만의 OS를 만들지 않고 C 라이브러리를 만듭니다. 당신이 그것을 원하지 않는다면, 예, 그것은 불필요합니다.
파이프

8

ac 라이브러리를 구현하는 방법과 관련된 표준이 있습니까? 아니면 다른 BSP를 제공하는 새 보드로 전환 할 때 라이브러리 구현의 특성을 다시 배워야합니까?

먼저, C 표준은 "호스트 된"구현 (기본 OS에서 지원하는 모든 C 함수의 범위)과 달리 "자립형"구현이라고하는 것을 정의합니다.

"자립형"구현은 C 라이브러리 헤더의 서브 세트, 즉 지원이 필요 하지 않은 서브 세트 또는 함수의 정의 (단지 #defines 및 typedefs) 만 정의하면됩니다 .

  • <float.h>
  • <iso646.h>
  • <limits.h>
  • <stdalign.h>
  • <stdarg.h>
  • <stdbool.h>
  • <stddef.h>
  • <stdint.h>
  • <stdnoreturn.h>

호스팅 된 구현을 향한 다음 단계를 진행할 때 실제로 어떤 방식 으로든 "시스템"을 인터페이스해야하는 기능은 거의 없으며, 나머지 라이브러리는 "기본적"위에 구현할 수 있습니다. ". PDCLib을 구현할 때 lib를 새로운 플랫폼으로 포팅 할 때 쉽게 식별 할 수 있도록 별도의 하위 디렉토리에 이들을 분리하기 위해 노력했습니다 (리눅스 포트 괄호 안의 예).

  • getenv()( extern char * * environ)
  • system()( fork()/ execve()/ wait())
  • malloc()그리고 free()( brk()/ sbrk())
  • _Exit()( _exit())
  • time() (아직 구현되지 않음)

그리고 <stdio.h>(아마도 C99 헤더 중 가장 "OS 관련") :

  • 파일을 여는 방법 ( open())
  • 닫는 방법 ( close())
  • 그것을 제거하는 방법 ( unlink())
  • 이름을 바꾸는 방법 ( link()/ unlink())
  • 그것에 쓸 수있는 방법 ( write())
  • 읽을 수있는 방법 ( read())
  • 그 안에 재배치하는 방법 ( lseek())

라이브러리의 특정 세부 사항은 선택 사항이며 표준 은 표준 방식으로 구현되도록 제공 하지만 그러한 구현을 요구 사항으로 만들지는 않습니다.

  • time()기능은 법적으로 만 반환 할 수 있습니다 (time_t)-1시간을 지키는 메커니즘을 사용할 수없는 경우.

  • 에 대해 설명 된 신호 처리기는에 대한 <signal.h>호출 이외의 다른 방법으로 호출 할 필요 raise()가 없으며, 시스템이 실제로 응용 프로그램에 비슷한 것을 보낼 필요는 없습니다 SIGSEGV.

  • 구현이 정의한다면 <threads.h>(명백한 이유로) OS에 매우 의존적 인 C11 헤더 는 전혀 제공 될 필요가 없습니다 __STDC_NO_THREADS__...

더 많은 예가 있지만 지금 당장은 없습니다.

나머지 라이브러리는 환경의 도움없이 구현할 수 있습니다. (*)


(*)주의 사항 : PDCLib 구현이 아직 완료되지 않았으므로 한두 가지를 간과했을 수도 있습니다. ;-)


4

표준 C는 실제로 운영 환경과 별도로 정의됩니다. 호스트 OS가 존재한다는 가정은 없으며 호스트에 의존하는 부분은 그대로 정의됩니다.

즉, C 표준은 이미 꽤 노출 된 금속입니다.

물론, 우리가 좋아하는 언어 부분 인 라이브러리는 종종 핵심 언어가 특정 내용을 호스트하는 곳입니다. 따라서 많은 베어 메탈 플랫폼 도구에 사용되는 일반적인 "xxx-lib"크로스 컴파일러 제품입니다.


3

Newlib 최소 실행 가능 예제

여기서는 QEMU에서 작동하는 newlib를 보여주는 고도로 자동화되고 문서화 된 예제를 제공합니다 .

newlib을 사용하면 베어 메탈 플랫폼에 대한 자체 시스템 호출을 구현할 수 있습니다.

예를 들어, 위 예제에는 예제 프로그램이 있습니다 exit.c.

#include <stdio.h>
#include <stdlib.h>

void main(void) {
    exit(0);
}

별도의 C 파일에서 common.c, 우리는 구현 exitARM은 세미 호스팅 :

void _exit(int status) {
    __asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
}

구현할 다른 일반적인 syscall은 다음과 같습니다.

  • write결과를 호스트에 출력합니다. 이것은 다음 중 하나를 사용하여 수행 할 수 있습니다.

    • 더 많은 세미 호스팅
    • UART 하드웨어
  • brk에 대한 malloc.

    페이징에 신경 쓸 필요가 없으므로 베어 메탈에서 쉽게 사용할 수 있습니다.

TODO Zephyr 또는 FreeRTOS 와 같은 완전한 RTOS 로 들어 가지 않고 선제 적 스케줄링 syscall 실행에 도달하는 것이 현실적인지 궁금합니다 .

Newlib의 멋진 점은 그것이 string.h당신 과 같은 모든 비 OS 관련 사항 을 구현하고 OS 스텁 만 구현할 수 있다는 것입니다.

또한 모든 스텁을 구현할 필요는 없지만 필요한 스텁 만 구현하십시오. 예를 들어, 프로그램에만 필요 exit하면을 제공 할 필요가 없습니다 print.

Newlib 소스 트리에는 ARM 세미 호스팅 구현을 포함하여 이미 일부 구현이 newlib/libc/sys/arm있지만 대부분의 경우 자체 구현해야합니다. 그러나 작업을위한 견고한 기반을 제공합니다.

Newlib를 설정하는 가장 쉬운 방법은 crosstool-NG를 사용하여 자체 컴파일러를 빌드하는 것입니다. Newlib를 C 라이브러리로 사용하고 싶다고 말하면됩니다. 내 설정은 이 스크립트 를 사용하여 자동으로 처리합니다. 이 스크립트 는에있는 newlib 구성을 사용합니다 crosstool_ng_config.

C ++도 효과가 있다고 생각하지만 TODO는 그것을 테스트합니다.


3
@ downvoters : 정보를 배우고 향상시킬 수 있도록 설명하십시오. 앞으로 독자들은 웹에서 사용할 수있는 유일한 Newlib 설정의 가치를 볼 수있을 것입니다. :-)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件 8'18

2

베어 메탈을 사용할 때 구현되지 않은 일부 종속성을 발견하고 처리해야합니다. 이러한 모든 종속성은 시스템의 성격에 따라 내부를 조정하는 것입니다. 예를 들어 malloc ()을 사용하는 sprintf ()를 사용하려고했을 때. Malloc은 "t_sbrk"기능 심볼을 코드의 후크 (hook in code)로 가지고 있으며, 하드웨어 구속을 강화하기 위해 사용자가 구현해야합니다. 여기서는 sprintf뿐만 아니라 주로 다른 용도로 임베디드 하드웨어를 위해 더 나은 것을 할 수 있다고 생각하면 그것을 구현하거나 내 malloc ()을 만들 수 있습니다.


sprintf에 malloc ()이 필요한 이유는 무엇입니까?
supercat

모르겠어요 나는 당신의 요점이 이미 가지고있는 버퍼라고 생각합니까? 그러나 printf조차도 malloc이 필요하지 않습니다. 요청 된 출력의 계산이 스택 할당 (동적 함수 변수)의 예측보다 무거울 때 일부 내부 변수를 동적으로 할당 할 수 있습니까? sprintf에 malloc (arm-none-eabi-newlib)이 필요하다고 확신합니다. 이제 컴퓨터에서 sprintf (glibc)를 사용하는 간단한 프로그램을 실험했습니다. 그것은 결코 malloc을 불렀다. 그런 다음 printf를 사용했습니다. malloc이라고 불렀습니다. Malloc은 가짜였으며 항상 0을 반환했습니다. 그러나 제대로 작동했습니다. 그들은 문자열과 십진 변수를 인쇄해야했습니다. @supercat
Ayhan

내 응용 프로그램이 사용하는 형식을 지원하도록 사용자 정의 된 printf 또는 유사한 방법의 몇 가지 버전을 직접 만들었습니다. 십진 출력에는 가능한 가장 긴 수를 보유 할만큼 충분한 버퍼가 필요하지만 기본 루틴은 첫 번째 멤버가 출력 할 데이터와 함께 해당 구조에 대한 포인터를 승인하는 출력 함수 인 구조를 승인합니다. 이러한 디자인을 통해 curses 스타일 콘솔, 소켓 등에 출력되는 printf 변형을 추가 할 수 있습니다. 그런 것에서 "malloc"이 필요하지 않았습니다.
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.