인프런 커뮤니티 질문&답변

김상현님의 프로필 이미지
김상현

작성한 질문수

FreeRTOS 프로그래밍

소스코드 분석-configUSE_PREEMPTION

TASKMAN 실습 중 이해가 안되는 것이 있습니다.

해결된 질문

작성

·

212

1

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

안녕하세요. TASKMAN 프로젝트 실습 중 이해가 안되는 내용이 있어서 질문 올립니다.

동일한 Priority를 가지는 Task1과 Task2 생성하고 3초 딜레이 후에 Task2의 Priority를 올리는 코드를 작성하여 결과를 보았습니다.

configUSE_TIME_SLICING 은 1, configUSE_PREEPTION 은 1로 설정해놓은 상태여서, 예상되는 결과로는 약 3초정도 Task1과 Task2가 스위칭되면서 실행되다가 3초후엔 Task2만 실행될 것으로 예상을 하였습니다. 그런데 예상과 다르게 3초정도 지나니까 아예 정지를 해버리더군요.

FreeRTOS 매뉴얼을 읽어보아도 별 문제 없이 제가 예상한대로 돌아가야할 것 같은데, 왜 이러는지 이해가 안됩니다.

사진은 01_TASKMAN 프로젝트의 TaskMain 함수의 내용 일부입니다. 확인 부탁 드립니다. 감사합니다.

답변 2

0

홍영기님의 프로필 이미지
홍영기
지식공유자

김상현님!

(ANS) 아! 원인을 찾은 것 같습니다.

fflush(stdout) 함수를 주석처리해보시죠. 이제 예상하신 것처럼 잘 동작하는 것을 볼 수 있어요.

printf 나 관련함수(fflush 와 같은)는 thread safe 하지 않아요.

해당 함수 내부적으로 임계구역이 존재한다는 뜻입니다(안전하지 않음).

그러면, 이 함수를 상호배제해서 사용해야 하는 것인가라는 질문만 남습니다.

하지만, 여기 딜레마가 있습니다.

우리가 printf 를 사용하는 이유는 보통 코드 실행을 추적하기 위한 것이죠. printf 는 디버깅 도구라는 말이죠.

디버깅 도구의 가장 이상적인 모습은

첫째, 이 함수 자체의 오버헤드(성능)가 크지 않아야 하죠. 

둘째, 실시간이면 좋겠죠.

셋째, 쓰레드 쉐이프해야 합니다.

그런데, 문제는 여기서 발생합니다. THREAD SAFE 와 오버헤드는 서로 모순관계에 있습니다.

THREAD SAFE 하게 처리하자면 오버헤드가 커지고, 오버헤드를 줄이거나 없애자면 위험을 감수해야 하는 겁니다.

그렇다고 printf 를 THREAD SAFE 하게 만들어 사용하는 것은 추천하지 않습니다. printf 함수내부적으로 사용한 인터럽트금지나 세마포어가 실시간을 중시하는 시스템의 실행 상태를 왜곡하거나 디버깅을 어렵게 만들 수 있습니다.

설명이 길어졌습니다만, 결론적으로 말씀드리자면, 

printf 함수나 관련 함수는 THREAD SAFE 않기 때문에, 디버깅하실 때 항상 주의를 기울이셔야 한다는 것입니다.

이와 관련된 추가 정보가 필요하시면 이 글을 참고해주세요.

김상현님의 프로필 이미지
김상현
질문자

감사합니다.

0

홍영기님의 프로필 이미지
홍영기
지식공유자

김상현님!

잘 구현하셨지만 한 가지를 놓치신 것 같네요.

수퍼 태스크(일명 사자태스크)에 해당하는 taskMain 이 실행중일때는 task1 도 task2 도, 그 어떤 것도 실행될 수 없죠.

이런 방법으로 구현해보시죠.

task1()

{

3초 시간지연;

task2 의 우선순위를 높여준다;

...

}

이와 관련된 내용의 영상을 시청하시려면 클릭

추가 문의사항 있으시면 다시 질문 남겨주세요.

감사합니다.

김상현님의 프로필 이미지
김상현
질문자

답변 감사합니다. 그런데 여전히 이해가 안되서 다시 질문 드립니다.

(TaskMain 함수 내에서)

Task1 생성

Taks2 생성       -> Task1과 Task2의 Priority는 동일

위의 상황에서 TaskMain이 계속 돌아가다가 vTaskDelay(pdMS_TO_TICKS(3000)) 함수 호출로 약 3초간 TaskMain이 Block 상태로 진입

TaskMain이 Block 상태에 있을 동안 Task1과 Task2가 번갈아가면서 실행

약 3초 후 TaskMain이 Ready 상태로 진입

스케쥴러가 Ready 상태에 있는 TaskMain 실행(우선순위가 높으므로)

TaskMain에서 Task2의 Priority를 높여줌

TaskMain 삭제

그렇다면 스케쥴러는 생성된 Task1과 Task2 둘 중에서 우선순위가 높은 Task2를 실행해야할 것으로 예상이 되는데... 제가 무엇을 놓치고 있는건가요?

김상현님의 프로필 이미지
김상현

작성한 질문수

질문하기