해결된 질문
작성
·
212
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 생성
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를 실행해야할 것으로 예상이 되는데... 제가 무엇을 놓치고 있는건가요?
감사합니다.