-
[Zephyr] Thread공부/Embedded 2025. 1. 6. 01:10
Zephyr OS Docs를 읽고 적당히 메모하는 글...
https://docs.zephyrproject.org/latest/kernel/services/threads/index.html
Zephyr OS Thread
스레드는 인터럽트 서비스 루틴으로 수행하기에는 너무 길거나 복잡한 처리에 사용하게 되고
애플리케이션에서는 RAM이 수용가능한 범위에서는 많은 스레드를 정의해서 스레드 ID로 참조하여 사용할 수 있다.
스레드의 중요 구성 요소
stack area: 스레드의 스택을 위한 메모리 영역으로 요구 사항에 맞게 스택 크기를 조정할 수 있다.
thread control block: 스레드의 메타 데이터를 관리하기 위해 커널이 기록하는 블럭, 스레드의 상태/우선순위/스택 포인터 등을 포함함
entry point function: 스레드가 시작되면 호출되는 진입 함수, 최대 3개의 인자 값을 전달 가능하다.
scheduling prioity: 커널의 스케줄러가 스레드에 CPU를 할당할 때 사용하는 우선순위이다.
- https://docs.zephyrproject.org/latest/kernel/services/scheduling/index.html#scheduling-v2thread options: 커널이 스레드를 처리할 때의 옵션을 지정한다.
- https://docs.zephyrproject.org/latest/kernel/services/threads/index.html#thread-options-v2
start delay:스레드를 실행하기 전에 기다릴 시간을 지정한다.
execution mode: 스레드가 실행될 때의 모드로 아래와 같이 나눠진다.
- supervisor mode: 스레드는 모든 권한, CPU 명령어/전체 메모리 주소 공간/주변 장치에 접근 가능
- user mode: 제한된 권한으로 CONFIG_USERSPACE 옵션에 따라 다름
스레드의 라이프 사이클
생성(Creation)
스레드를 사용하기 전에 생성해야한다.
커널은 스레드에 대해 TCB 생성하고 스레드의 스택 한 부분을 초기화한다.
K_NO_WAIT: 커널이 스레드를 즉시 시작하도록 지시
종료(Termination)
스레드가 한 번 시작되면 영원히 실행되지만, entry point function에서 반환을 해서 동기적으로 실행을 종료할 수 있음
스레드 종료 전에 소유한 리소스(뮤텍스, 동적할당 메모리 등)은 모두 해제하고 종료해야한다.
Zephyr OS의 커널은 스레드가 소유했던 리소스를 회수해주지 않음
// 해당 스레드가 종료될 때 까지 기다림 // 스레드가 종료되면 커널은 스레드 구조체가 사용되지 않도록 보장함 int k_thread_join (struct k_thread *thread, k_timeout_t timeout)
중단(Aborting)
스레드는 aborting를 통해 비동기적으로 실행을 종료할 수 있음
스레드가 fetal error 상태를 유발했을 경우 커널이 스레드를 자동으로 중단시킴
void k_thread_abort(k_tid_t thread)
연기(Suspension)
스레드를 일시정지 시킬 수 있음, 자신을 포함한 어떤 스레드도 중단 가능
- k_sleep(): 스레드가 스스로 실행을 특정 시간 동안 중단하고, 자동으로 실행 가능 상태로 복귀함
- k_thread_suspend(): k_thread_resume() 호출 전까지 무기한 실행되지 않음
// 자신을 포함한 어떤 스레드도 중단 가능 void k_thread_suspend(k_tid_t thread) // 중단된 스레드를 다시 실행 가능한 상태로 전환 void k_thread_resume(k_tid_t thread)
스레드 상태
스레드 실행을 방해하는 것이 없다면, 해당 스레드는 Ready 상태가 되고, 현재 스레드로 선택될 수 있음
Unready 상태의 원인
- 아직 스레드가 시작되기 전
- 커널 객체의 작업 완료를 기다리고 있을 때(
- timeout 대기 중(k_sleep)
- 스레드가 중단(suspended)상태이거나 종료(terminated/aborted)상태 일 때
대충 아래와 같은 상태 사이클들을 가짐
스레드 스택 객체
모든 스레드는 CPU가 뭔가 하기 위해(함수 호출, 변수 저장 등...) 스택 버퍼가 필요함
Kernel-only Stacks
- 스레드가 사용자 모드에서 실행되지 않거나, 스택이 인터럽트 처리와 같은 특수 컨텍스트에 사용될 때
- K_KERNEL_STACK 매크로로 스택을 정의하는 것이 좋음
- 커널이 권한 승격을 위한 스택이나 사용자 모드 스레드에만 적용되는 메모리 관리 데이터 구조를 위한 추가 공간이 필요 없어 메모리를 절약 가능
- 사용자 모드에서 해당 스택을 사용하려하면 fetal error가 발생
- CONFIG_USERSPACE가 비활성화 되있다면 K_THREAD_STACK 매크로는 K_KERNEL_STACK 매크로와 동일하게 동작
Thread Stacks
스택이 사용자 스레드를 호스트할 때, 또는 이를 잘 모를 때 K_THREAD_STACK 매크로로 스택을 정의
메모리를 더 많이 사용 가능하지만, 사용자 스레드에 사용하는데 적합
→ CONFIG_USERSPACE를 끄면 K_THREAD_STACK == K_KERNEL_STACK
스레드 우선 순위
...
ㄴㄴ
ㄴ
ㄴ
ㄴ
ㄴ
ㄴ
ㄴ
ㄴ
ㄴ
ㄴㄴ
'공부 > Embedded' 카테고리의 다른 글
[Zephyr] Workqueue (0) 2025.01.07 [Zephyr] System Thread (0) 2025.01.07 AMBA Bus Protocol (3) 2024.12.08 [Renode] .repl(Platform description format) (1) 2024.12.01 [Renode] Leon3 hello world 찍기 (0) 2024.11.20