C의 스레드 간에 동적 데이터 전송 및 메모리 관리를 어떻게 수행합니까?

StackOverflow https://stackoverflow.com/questions/689514

  •  22-08-2019
  •  | 
  •  

문제

플랫폼:ARM9

프로그래밍 언어 C

요구 사항 - 일반 C, 외부 라이브러리 및 부스트 없음.

OS - REX RTOS

임베디드 플랫폼에서 두 개의 스레드가 실행 중입니다.

  1. 하나는 하드웨어와의 모든 통신 및 데이터 전송을 처리하는 드라이버 수준입니다.
  2. 두 번째 스레드는 하드웨어와의 데이터를 사용하는 애플리케이션을 실행합니다.

아이디어는 드라이버 스레드에서 앱 스레드를 분리하여 하드웨어 드라이버 스레드에서 하드웨어와 구현을 변경할 수 있지만 애플리케이션 스레드에 미치는 영향을 최소화하는 것입니다.

내 과제는 하드웨어에서 수신된 데이터가 동적일 수 있다는 것입니다.런타임 시 결정되므로 하드웨어와의 각 요청에 대해 애플리케이션 스레드가 얼마나 많은 메모리를 확보해야 하는지 미리 알 수 없습니다.

나는 드라이버 스레드가 읽을 데이터가 너무 많다는 것을 애플리케이션 스레드에 알릴 수 있다고 생각했습니다.그런 다음 애플리케이션 스레드는 메모리를 할당하고 드라이버 스레드에 데이터를 읽도록 요청합니다.그런 다음 그에 따라 데이터를 처리하는 것은 애플리케이션 스레드에 달려 있습니다.이렇게 하면 모든 메모리 관리가 애플리케이션 스레드 내에서 이루어집니다.

도움이 되었습니까?

해결책

몇 가지 옵션이 떠 오릅니다.

1) 드라이버의 메모리를 Malloc 앱에서 제거하십시오. 그러나 ... 우리는 실시간 요구 사항에 접근하는 모든 것에서 malloc 사용을 피하는 경향이 있습니다. Malloc/Free에 액세스 할 수 있고 "실시간"문제 또는 메모리 조각화 문제가 없다면 (즉, 힙이 충분히 큽니다), 이것은 매우 쉬운 접근법입니다. 드라이버는 메시지 큐를 통해 할당 된 포인터를 앱 스레드로 보냅니다. 메모리 누출을 조심하십시오.

2) 고리 또는 원형 버퍼. 드라이버는 고정 크기 링 버퍼를 완전히 관리하고 버퍼가 준비되었을 때 응용 프로그램에 메시지를 보냅니다. 자세한 내용은 여기를 참조하십시오. 원형 버퍼. 그런 다음 응용 프로그램은 드라이버 API를 통해 데이터를 다시 "사용 가능한"것으로 표시하여 앱 스레드에서 링 버퍼 세부 사항을 숨기는 데 도움이됩니다. 우리는이 접근법을 사용하여 귀하가 설명하는 매우 유사한 요구 사항이있는 드라이버 중 하나에 사용합니다. 이 경우 링 버퍼의 "최고의"크기를 결정하고 드라이버의 오버플로 처리 등을 결정해야합니다.

행운을 빕니다!

다른 팁

OS를 지정하지는 않지만 어떻게 든 "스레드"가 있습니다. 그들 중 하나가 드라이버 레벨 (인터럽트 핸들러)에 있고 다른 하나는 응용 프로그램 (userland/kernel)처럼 들립니다. 그러나 데이터가 처리되기 전에 드라이버와 앱이 통신하기 때문에 일치하지 않습니다.

당신의 용어는 혼란스럽고 고무적이지 않습니다. 이것은 홈브류 (RT) OS입니까?

실제 OS가있는 경우 드라이버를 작성하고 사용자 랜드에 데이터를 전달하는 방법이 있습니다. 문서를 읽거나 기존 드라이버 중 하나를 참조로 사용하십시오.

이것이 사용자 정의 OS 인 경우 아이디어를 위해 다른 오픈 소스 드라이버를 참조 할 수 있지만 편리하게 설정할 수는 없습니다. 드라이버 코드의 모든 메모리를 PrealLocate에 도달 할 때 데이터로 채우고 응용 프로그램 코드로 전달하십시오. 메모리의 양은 앱이 데이터를 처리 할 수있는 속도, 수용하려는 가장 많은 양의 데이터 및 앱을 지원하는 데 필요한 내부 데이터 큐잉의 수를위한 기능입니다.

이것이 C이기 때문에 앱이 드라이버에 콜백을 등록하도록 해야 했습니다.콜백의 목적은 드라이버가 장치에서 데이터를 읽은 후 데이터를 처리하는 것입니다.드라이버는 메모리를 관리합니다.메모리를 할당하고 콜백을 호출한 후 마지막으로 메모리를 해제합니다.또한 콜백에는 메모리에 대한 읽기 권한만 있습니다.따라서 앱은 이상적으로는 버퍼의 내용을 자체 메모리에 복사하고 콜백을 즉시 종료해야 합니다.그런 다음 원하는 시간과 방법으로 데이터를 자유롭게 처리할 수 있습니다.

콜백이 반환될 때 메모리가 더 이상 유효한 것으로 간주되어서는 안 된다는 점을 앱 콜백 사용에 명확하게 설명하기 위해 문서를 업데이트했습니다.콜백이 다른 방식으로 사용되는 경우 동작은 정의되지 않습니다.

나의 첫 번째 생각은 원형 버퍼를 사용하는 것입니다. 다음은 몇 가지 예제 코드입니다. 이것을 자신의 용도에 자유롭게 조정하십시오. 당신은 아마도 글로벌 변수를 원하지 않을 것입니다. #Defines를 원하지 않을 수도 있습니다.

#define LENGTH (1024)
#define MASK (LENGTH-1)
uint8 circularBuffer[ LENGTH ];
int circularBuffer_add = 0;
int circularBuffer_rmv = 0;

void copyIn( uint8 * circularBuffer, uint8 * inputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        circularBuffer[ circularBuffer_add ] = inputBuffer[ i ];
        circularBuffer_add = ( circularBuffer_add + 1 ) & MASK;
    } 
}

void copyOut( uint8 * circularBuffer, uint8 * outputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        outputBuffer[ i ] = circularBuffer[ circularBuffer_rmv ];
        circularBuffer_rmv = ( circularBuffer_rmv + 1 ) & MASK;
    } 
}

또한 위의 코드는 귀하의 데이터 단위가 "UINT8"이라고 가정합니다. 다른 데이터 유형을 사용하도록 변경할 수 있습니다. 또는 일반화하고 memcpy ()를 사용하여 원형 버퍼에 복사 할 수도 있습니다.

이 코드의 주요 기능은 ADD 및 RMV PTR을 처리하는 방법입니다.


위의 코드로 작업을 수행하면 어느 시점에서 하드웨어에서 모든 읽기를 전환하여 플랫폼을 사용하는 것이 좋습니다. 직접 메모리 액세스 API.

그것은이다 위의 코드는 DMA에 비해 많은주기를 사용하기 때문에 직접 메모리 액세스로 전환하는 것이 중요합니다. 거의 제로 사이클을 사용합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top