PIC에서 malloc 사용


10

PIC에서 어떻게 사용 malloc()하고 free()기능합니까? stdlib.h헤더를 확인했는데 언급이 없습니다. MCC18을 사용하고 있습니다.

아무도 그것들을 사용해야 했습니까?

Windows XP에서 PIC로 라이브러리를 이식하기 때문에 필요합니다. 포팅 가이드는

운영 체제의 특정 기능을 내 PIC 기능에 맞게 조정

그러나 malloc()free()함수 를 "번역"하는 방법을 모르겠습니다 .


4
가능하면 정적 할당을 사용하십시오.
Nick T

1
왜? 문제는 실제로 꽤 큰 라이브러리의 맨 아래 계층 (플랫폼 별 라이브러리)을 작성하고 있으며이 기능을 사용하는 것이 무엇인지 전혀 모른다는 것입니다. 동적에서 정적으로 ..
stef

11
<4KB RAM의 PIC 마이크로 컨트롤러가 응용 프로그램에 적합하지 않은 것 같습니다. PC에서 포트를 시작하기 전에 PC 라이브러리의 메모리 사용량을 측정하십시오. ARM Cortex-M3과 같이 더 강력한 것을 사용하는 것이 좋습니다. 일반적으로 이식하려는 코드베이스가 너무 커서 이해하기 어려운 경우 PIC에 맞지 않습니다.
Toby Jaffey

실제 RAM이 소진되면 가상 메모리를 스왑 할 수 있으므로 Windows 드라이버 (및 일반적으로 응용 프로그램)는 기본적으로 '무제한 RAM'패러다임으로 작성됩니다. PIC18F87J11에서 사용 가능합니다. 드라이버가 사용할 메모리 양을 측정 할 수 없을 것 같습니다.
Adam Lawrence

또 다른 잠재적 인 문제 : Win32 int는 32 비트이지만 MCC18 컴파일러의 경우 16 비트입니다. 조심하지 않으면 이상한 오버플로 문제가 발생할 수 있습니다.
Adam Lawrence

답변:


8

많은 응용 프로그램에서 메모리를 할당해야하지만 그 후에 할당 된 것을 유지하면서 아무것도 해제 할 필요가 없습니다. 이러한 시스템에서는 링커를 사용하여 사용 가능한 모든 RAM을 사용하여 배열을 정의하고 해당 배열의 시작에 대한 포인터를 설정 한 다음 멋진 malloc 함수를 사용하면됩니다.

char * next_alloc;
void * malloc (int size)
{
    char * this_alloc;
    this_alloc = next_alloc;
    if ((END_OF_ALLOC_SPACE-this_alloc) <size)
      리턴 -1;
    next_alloc + = 크기;
    this_alloc을 반환;
}
무효 무료 (void * ptr)
{
    if (ptr)
        next_alloc = (char *) ptr;
}

멋지고 쉬우 며, 할당 횟수에 따라 2 바이트의 총 오버 헤드가 발생합니다. 블록에서 free ()를 호출하면 해당 블록과 그 이후의 모든 항목이 할당 해제됩니다.

두 개의 포인터를 사용하여 약간 더 복잡한 할당 패턴을 처리 할 수 ​​있습니다. 하나는 메모리의 맨 아래에서 위로 이동하고 다른 하나는 메모리에서 아래로 이동합니다. 힙의 데이터가 균일하고 외부 참조가 어디에 있는지 아는 경우 압축 가비지 수집기를 사용할 수도 있습니다.


가능성에 대한 완전한 정보를 얻으려면 electronics.stackexchange.com/questions/7850/
gavioto20

14

malloc()마이크로 컨트롤러에서 일반적으로 "나쁜 것"으로 간주됩니다. 그러나 절대적으로 필요한 경우 타사 버전을 찾고 싶을 것입니다.

운이 좋으면 이식하려는 코드가 메모리 블록 재사용에 의존하지 않을 수 있습니다. 이 경우 간단한 할당자를 작성하여 포인터를 RAM 버퍼로 반환 한 다음 요청 된 블록 크기만큼 포인터를 진행시킵니다.

PC 라이브러리를 마이크로 컨트롤러로 포팅하기 전에이 방법을 성공적으로 사용했습니다.

아래에서는로 할당자를 설정하고로 my_malloc_init()메모리를 할당합니다 my_malloc(). my_free()의존성을 만족 시키지만 실제로는 아무것도하지 않습니다. 결국에는 공간이 부족할 것입니다.

이 작업을 수행하려면 코드의 최악의 메모리 요구 사항을 측정 한 다음 (가능한 경우 PC에서 수행) HEAP_SIZE그에 따라 설정해야합니다 . 동적 메모리가 필요한 라이브러리 부분에 들어가기 전에를 호출하십시오 my_malloc_init(). 재사용하기 전에 아직 아무것도 가리 키지 않도록하십시오 heap.

uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;

void my_malloc_init(void)
{
    heap_ptr = heap;
}

void *my_malloc(size_t len)
{
    uint8_t *p = heap_ptr;
    heap_ptr += len;
    if (heap_ptr >= heap + HEAP_SIZE)
        return NULL;
    else
        return p;
}

void my_free(void)
{
    // do nothing
}

(참고 : 실제로는 포인터 정렬을 고려해야합니다 (예 : heap_ptr2 또는 4 바이트 반올림 ))

또 다른 옵션은 FreeListmalloc() 와 같이 일반적으로 제공되는 것보다 간단한 할당 구조를 사용하는 것인데 , 가변 크기 블록을 할당 할 수는 없습니다.


3
malloc이 언제 임베디드에서 좋은 것으로 간주되는지 궁금합니다.
Kellenjb

1
다른 사람들이 말했듯이 프로그램에서 동적 할당을 원하지 않는다는 데 여전히 동의하지만 이것이 좋은 방법입니다. 임베디드 용으로 설계된 타사 malloc이 가장 최선의 선택입니다. 분할을 피해야합니다. @jobyTaffey 잘 작성되었습니다.
Kortuk

1
@Kellenjb 글쎄요, 그것은 완전히 새로운 질문입니다 :-)
Toby Jaffey

1
my_free는 heap_ptr을 전달 된 값으로 설정하여 표시된 항목과 그 뒤에 할당 된 모든 항목을 효과적으로 해제해야한다고 제안합니다. 분명히 그러한 사용법을 허용하는 것을 순서대로 할당해야하지만 그러한 패턴은 드문 일이 아닙니다. 또 다른 유용한 변형은 두 쌍의 할당 / 자유 기능을 갖는 것인데, 그 중 하나는 하향식을 할당하고 다른 하나는 상향식을 할당합니다.
supercat

13

이것은 귀하의 질문에 대한 답이 아니지만 동적 메모리 할당은 일반적으로 작은 RAM 환경과 운영 체제가없는 경우 (예 : 마이크로 컨트롤러 세계에서) 쇠약합니다 ... 임베디드 환경에서 사용 가능한 힙 공간은 일반적으로 수백 바이트로 측정 ...

malloc과 free를 구현하는 것은 본질적으로 "free segment"구조의 링크 된 목록을 유지 관리하는 것입니다. 상상할 수 있듯이 free segment와 관련된 메타 데이터는 일반적으로 사용 가능한 메모리 양과 비교할 때 거의 중요하지 않습니다. "의 동적 메모리 풀 관리는 사용 가능한 많은 양의 리소스를 소비합니다.


메타 데이터 오버 헤드가 매우 작은 구현이 있습니다. 할당 된 블록의 경우 크기 만 필요합니다. 사용되지 않는 블록의 경우, 링크 된 목록 포인터는 일반적으로 아주 적당한 최소 블록 크기 일지라도 무료로 적합 할 수 있습니다.
복원 Monica Monica

마이크로 컨트롤러를 사용하는 작고 오래 실행되는 시스템의 문제는 일반적으로 메타 데이터가 아니라 메모리 조각화에 관한 것입니다. 더 나쁜 것은, 코드를 조금만 변경하면 이전에는 없었던 메모리 조각화가 발생하여 프로그램이 갑자기 너무 빨리 작동하지 않게하는 순진한 모양의 변경이 이루어질 수 있습니다.
복원 Monica Monica

11

C18 표준 라이브러리가 malloc및을 지원 하는지 free모르겠지만 Microchip 앱 노트 AN914 는 자신의 구현 방법을 보여줍니다.

어쨌든 토마스와 다른 포스터는 매우 작은 RAM 공간 으로 PIC에서 동적 메모리를 사용하는 것은 위험에 처해 있다고 제안했습니다 . 운영 체제가 제공하는 고급 가상 메모리 관리자가 없기 때문에 연속적인 공간이 빠르게 소진되어 할당 및 충돌이 발생할 수 있습니다 . 더 나쁜 것은 결정적이지 않을 수 있으며 디버그하기가 어려울 것입니다.

당신이하고있는 일이 런타임에 동적으로 결정되고 (대부분의 임베디드 일에는 드물게) 몇 가지 매우 특별한 경우 에만 공간을 할당 해야하는 경우 볼 수 malloc있고 free수용 가능합니다.


연속 공간 부족, 즉 힙 조각화는 주소 공간의 크기와 가상 메모리의 유무에 전적으로 독립적 인 문제입니다. 힙 조각화를 줄이기 위해 일부 낭비되는 RAM을 교환하고 싶을 수도 있지만 결국 장기 실행 시스템에서는 힙 공간이 부족하지 않을 것이라는 보장이 없습니다. 여기서 작은 시스템과 큰 시스템의 유일한 차이점은 디스크가 스 래싱을 시작하는 데 걸리는 시간 (디스크 페이징 된 VM이있는 시스템) 또는 할당자가 NULL (내장 된 항목)을 반환하는 데 걸리는 시간 중 하나입니다.
복원 Monica Monica

@ KuberOber : 일반적으로 특정 크기의 RAM이 동시에 할당되기 위해 특정 (작은) 양의 RAM을 필요로하지 않는 모든 할당 및 릴리스 작업 시퀀스를 처리 할 수 ​​있음을 보장 할 수 있습니다. 임베디드 시스템의 문제점은 최악의 경우에도 성공을 보장하려면 조각화없이 필요한 것보다 훨씬 많은 RAM이 필요하다는 것입니다.
supercat

@supercat 당신이 맞아요. 나는 참으로 극적으로 극적이었다. 그러한 보증에 대한 공식적인 증거가 있습니다.
복원 Monica Monica

2

글쎄, 메모리면에서 PIC는 얼마나 큽니까?

malloc은 메모리를 할당 하는 매우 비효율적 인 방법입니다. 문제는 빈번한 여유 공간과 mallocs로 인해 메모리가 조각화 될 수 있고 단지 몇 킬로바이트의 메모리로 할당 실패가 너무 일반적이라는 것입니다. 더 작은 칩이나 이전 PIC18을 사용하는 경우 Microoc이 구현하기가 매우 어렵거나 (어쩌면 불가능할 수도 있음) 보았을 때 malloc을 지원하지 않을 가능성이 높습니다. 그만한 가치가 있습니다. 언급하지는 않지만 속도가 느립니다. 이미 사용 가능한 정적 버퍼를 사용하려면 1주기를, malloc을 수행하려면 100에서 1,000주기를 사용하십시오.

정적으로 할당하려면 malloc이 필요하지 않을 때까지 sprintf 함수용 버퍼 (있는 경우 약 128 바이트), SD 카드 용 버퍼 (있는 경우) 등을 작성하십시오. 이상적으로는 꼭 필요한 곳에만 사용하고 정적 할당을 피할 수는 없지만 이러한 상황은 일반적으로 드물고 더 크고 강력한 마이크로 컨트롤러를 살펴보아야한다는 신호일 수 있습니다.

그리고 PIC18에서 "운영 체제"를 개발 / 포팅하고 마이크로 컨트롤러를 지원하는 경우 정적 할당을 지원할 수 있습니다. 예를 들어, SQLite3는 정적 할당을 지원합니다. 큰 버퍼 배열을 할당하고 가능한 경우 마이크로 컨트롤러가 아닌 경우에도이를 사용합니다. 그렇지 않은 경우 작은 PIC18 용으로 설계 되었습니까?


무슨 말인지 알 겠어요. 128K의 램을 가진 PIC18F87J11을 사용하고 있다면 충분합니까?
stef

스테파노 칩에는 3,904 바이트의 RAM이 있습니다. 128K의 프로그램 플래시 메모리가 있습니다.
W5VO

@Stefao Salati-3.8KB는 작습니다.
Thomas O

알겠습니다. 어쨌든 충분하다고 생각하십니까?
stef

@ 스테파노 살라 티, 사과 할 필요가 없습니다. 나는 당신이 정말로 그것을 밀고 있다고 생각합니다. 작동하지만 성능과 사용 가능한 메모리가 부족합니다.
Thomas O

2

당신이 고려하는 경우 malloc()free()임베디드 소프트웨어에 대한 당신이 uc에 / OS-II와 살펴 보시기 바랍니다 OSMemGet()OSMemPut(). malloc()임의의 메모리 블록을 할당하는 동안 OSMem*()미리 할당 된 풀에서 고정 크기 블록을 제공하십시오. 이 방법 malloc()은 정적 할당 의 유연성 과 견고성 간에 균형이 잘 맞습니다.


0

AFAIK,이 작업을 올바르게 수행하려면 실제로 일종의 MMU (메모리 관리 장치)가있는 장치를보고 있어야합니다. PIC18 시리즈의 동적 할당 메커니즘은 존재하지만 실제로는 그다지 견고하지는 않을 것입니다. 그리고 PIC18 시리즈의 한계를 뛰어 넘는 펌웨어 작업을하는 사람 으로서는 말할 수 없습니다. 메모리 관리자에 모든 오버 헤드를 소비하는 경우 상당한 규모의 응용 프로그램.

더 나은 솔루션 : 수행중인 작업과 동적 할당이 필요한 이유를 이해하십시오. 정적 할당으로 작동하도록 리팩터링 할 수 없는지 확인하십시오. (라이브러리 / 응용 프로그램이 자유롭게 확장되거나 수용 할 수있는 입력량에 제한이없는 것을 수행하도록 설계된 경우에는 이것이 가능하지 않을 수도 있습니다.) 그러나 때로는 생각한다면 당신이하려는 일에 대해, 대신 정적 할당을 사용하는 것이 가능하고 (아마도 훨씬 쉽다는 것을) 알 수 있습니다.


1
당신은 틀 렸습니다. MMU를 사용하면 외부 메모리 (PIC의 4kB 이상)와 인터페이스 할 수 있습니다. MMU 유무에 따른 동적 및 정적 할당에는 거의 차이가 없습니다. 가상 메모리에 들어가기 시작하면 차이가 있지만 malloc과 접하는 것과 관련이 있습니다.
케빈 베르메르

1
초기 매킨토시 프로그래머는 초기 매킨토시 컴퓨터에 MMU가 없었음에도 불구하고 malloc () 및 free () (또는 파스칼 동등 물)를 자주 사용했습니다. malloc ()을 사용하여 "올바로"MMU가 필요하다는 생각은 나에게 잘못된 것 같습니다.
davidcary
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.