큐와 메일박스에 이어서 파이프도 설명하고 넘어가야 합니다. 그리고 전반적인 OS의 내용을 요약할 테니 복습과 예습을 동시에 해봅시다.
[파이프]
큐와 매우 비슷한 작동을 합니다. RTOS는 파이프를 생성할 수 있고, 쓸 수 있고, 읽을 수 있습니다. 그러나 파이프의 세부 사항은 메일박스나 큐처럼 알토스마다 다양합니다. 변형을 보고 생각해봅시다.
- 어떤 RTOS는 다양한 길이의 메시지를 파이프에 쓸 수 있도록 합니다. 보통 길이가 고정된 상태인 메일박스나 큐와는 다르죠.
- 어떤 알토스에서 파이프는 완전히 바이트 수에 의해서 운영되곤 합니다. 만약에 태스크 A가 11바이트를 파이프에 쓰고 태스크 B가 19바이트를 파이프에 썼다면 태스크 C가 파이프로부터 14바이트를 읽었을 때 C는 A가 쓴 11바이트를 얻고 B가 쓴 첫 3 바이트를 얻게 됩니다. B가 쓴 나머지 16바이트는 어떤 태 스크가 됐든 다음에 읽을 때까지 남아있는 상태가 됩니다.
- 어떤 RTOS는 파이프로부터 읽고 쓰기 위해서 표준 C 라이브러리 함수인 fread와 fwrite를 사용합니다.
[그래서 결국에는 어떤걸 사용해야 하나요?]
가장 중요한 결론일지도 모릅니다. 그래서 어쩌라는 건가! 큐, 메일박스, 파이프는 RTOS에 따라서 매우 다양하니까 어떤 순간에 어떤 걸 사용하는 게 좋다는 말이 매우 어렵습니다. 내가 좋다고 한들 아니라고 반박하면 할 말이 없을지도 모르기도 하고요. RTOS가 제조사 가이드 기능을 설계할 때 우연성, 속도, 메모리 공간, 함수 내에서 인터럽트가 금지되어야만 하는 시간 등과 같은 일반적인 프로그래밍에서의 트레이드오프 관계를 만들어 놓았을 겁니다. 대부분의 RTOS 제조사는 문서에 이들 기능에 대한 특징을 잘 설명해놨습니다. 일을 제대로 했다면요. 현재의 상황에 어떤 것이 가장 적합한지를 결정하기 위해서 이런 문서를 꼭 읽어봅시다. 결론은 설명서를 잘 보자인데 비난해도 소용없습니다. 원래 이렇게 만들어진 거예요.
[함정이 숨어있다.]
태스크 간에 데이터를 공유하는 것을 쉽게 만들어진 것들이지만 버그가 쉽게 시스템에 침투하도록 합니다. 아주 쉬운게 하나도 없죠. 프로그래머들이 스스로 문제를 만들 수 있는 알려진 방법을 보여드립니다.
- 대부분의 알토스는 주어진 큐, 메일박스, 파이프에 대해서 어떤 태스크도 읽고 쓸 수 있도록 제한을 하지는 않습니다. 그러므로 매 태스크가 정확한 것을 사용하는지 확실히 하는 게 중요합니다. 어떤 태스크가 온도 데이터를 에러 코드를 원하는 태스크에 의해 준비된 큐에 써서 넣는다면, 이 시스템은 멀쩡하게 동작하지 못할 겁니다. 쉽게 혼란을 초래할 것이 분명해 보이죠.
- 알토스는 데이터가 그것을 읽는 태스크에 의해서 올바르게 해석된다는 보장을 해주지는 못합니다. 하나의 태스크가 정수를 큐에 쓰고 다른 태스크가 그 값을 읽어서 포인터로 간주한다고 생각해보면 그 제품은 문제를 찾아서 고칠 때까지 선적되지 못할 것입니다. 대부분의 컴파일러는 아래와 같은 코드에서 멈춰버리기 때문에 많은 이들이 이런 버그를 찾도록 만듭니다. 어떤 문제를 발생시키는 코드는 컴파일러에 의해서 넘어가서 시스템에 속하기도 합니다.
- 모두 공간을 소모하는 것은 보통 임베디드 소프트웨어에 큰 재앙을 초래할 가능성이 높습니다. 태스크가 데이터를 다른 태스크에 넘길 때 공간을 모두 소모하는 것은 얼핏 봐도 바람직하진 않습니다. 에러를 기록하는 서브시스템은 큐가 가득 차면 에러를 보고하는데 실패하고 이는 용인되지 않습니다. 이 문제를 해결하는 방법은 부족하게 사용하는 겁니다. 심플하죠? 실행할 수 있는 유일한 방법 중 하나는 첨부터 부족하지 않도록 아주 크게 만드는 것이니 꼭 알아둡시다.
- 포인터를 한 태스크에서 다른 태스크로 이들을 통해 전달하는 것은 공유 데이터 문제를 부주의하게 만들어 낼 수 있습니다. malloc과 free를 호출하는 것을 피하는 단순화 버전을 떠올려봅시다.
[예습과 복습 총망라]
- 태스크는 동작을 제어하거나 데이터를 공유하기 위해서 서로 통신할 수 있어야 함. 대부분의 알토스들은 이러한 목적을 위해서 메시지 큐, 메일박스, 파이프 서비스 조합을 제공함. 이런 서비스들의 특정한 성질들은 RTOS 마다 다름. 사용하는 알토스가 어떤 것을 제공하는지 알려면 그에 따라오는 매뉴얼을 꼭 읽어봐야 함.
- 버퍼에 대한 포인터를 태스크에서 태스크로 큐로 보내는 것은 데이터 블록을 보내기 위한 일반적인 방법임.
- 대부분의 알토스들은 주기적으로 인터럽트를 발생시켜서 모든 RTOS 타이밍 서비스가 사용할 수 있도록 하는 심장박동 타이머를 가지고 있음. 심장박동 타이머 인터럽트들 사이의 간격은 시스템 틱이라고 부름. 대부분의 일반적인 RTOS의 타이밍 서비스는 아래를 참고.
- 태스크는 미리 정한 개수의 시스템 틱만큼 스스로 대기 상태로 될 수 있음
- 세마포어, 큐 등을 얼마의 시스템 틱 동안 기다릴지 제한할 수 있음
- 프로그램은 미리 정한 개수의 시스템 틱 후에 특정한 함수를 호출하도록 RTOS에게 알려줄 수 있음
- 이벤트는 태스크들이 서로 신호를 보낼 수 있는 1비트 플래그임. 이벤트는 그룹 형태로 될 수 있고, 태스크는 그룹 안에 있는 이벤트들의 조합을 기다릴 수 있음.
- 많은 RTOS들이 표준적인 malloc과 free 함수들을 제공하지만 소프트웨어 엔지니어들은 그들 함수들이 느리고 수행 시간이 예측 가능하지 않기 때문에 사용하는 것을 자제해야 함. 대신 고정된 크기의 버퍼들로 되어 있는 메모리 풀 기반의 메모리 할당을 사용하는 것이 일반적임
- RTOS에 있는 인터럽트 루틴들은 반드시 아래 두 가지 규칙을 준수해야 함.
- 인터럽트 루틴은 대기 상태로 들어갈 수 있는 RTOS 함수를 호출해서는 안됨.
- 인터럽트 루틴은 RTOS가 인터럽트 루틴이 수행되고 있다는 정보를 알고 있지 않는 한, 어떤 종류의 RTOS 함수를 호출해서는 안됨. 인터럽트 루틴이 수행 중이라는 것을 여러 다양한 방법을 이용해서 알 수 있음.
참고)
메시지큐 / 메일박스 : 또 다른 수단
RTOS를 왜 사용하는지 알았으니 이번에는 제공되는 또 다른 기능들에 대해서 알아보겠습니다. 태스크간 통신, 타이머 서비스, 메모리 관리, 이벤트, 인터럽트 루틴 등 상호작용에 대해서 말이죠.
ppojjaknews.tistory.com
'IT > 임베디드 시스템' 카테고리의 다른 글
RTOS에서의 이벤트와 메모리 관리 (0) | 2020.06.09 |
---|---|
타이머 함수 - 임베디드 시스템 시간 관리 함수 (0) | 2020.06.09 |
메시지큐 / 메일박스 : 또 다른 수단 (0) | 2020.06.06 |
세마포어의 용도/종류/문제 그리고 공유데이터 보호 방법 (0) | 2020.06.03 |
RTOS 문제 해결 툴 - 세마포어 (0) | 2020.06.03 |
댓글