태그 보관물: c

c

베어 메탈의 C 표준 라이브러리 라이브러리는 표준화 된 동작을 가진 시스템 호출을

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

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



답변

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

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

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


답변

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 구현이 아직 완료되지 않았으므로 한두 가지를 간과했을 수도 있습니다. 😉


답변

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

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

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


답변

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는 그것을 테스트합니다.


답변

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


답변