Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- .so 라이브러리
- 리눅스 커널 드라이버
- 라즈베리파이
- 취준
- rtsp
- 캐릭터 디바이스
- udev
- qt widget
- systemd
- wiringpi
- 디바이스 트리 작성법
- cdev
- 디바이스 트리
- 멀티클라이언트
- 금융권 취준
- ioctl
- 노션
- 커널 모듈
- 가계부 개발
- IOT
- 바이브 코딩
- raspberry pi 4
- /dev
- pthreads
- 데몬 프로세스
- yocto
- SQLite
- 임베디드 리눅스
- 라즈베리파이 카메라
- 개발자 취준
Archives
- Today
- Total
이로또
임베디드 리눅스 드라이버의 이해 6편: 커널 영역에서 쓰레드 만들기 본문
이 글에서는 리눅스 커널 영역에서 스레드를 생성하고 관리하는 방법을 정리합니다.
핵심 구조체인 task_struct를 중심으로 스레드 상태, 생성 및 종료 흐름, 주요 함수 사용법 등을 실제 예제 코드와 함께 설명합니다. 특히 kthread_create(), kthread_run(), kthread_should_stop(), kthread_stop() 함수의 역할과 차이점을 구체적으로 다루며, 스레드 상태 전이 흐름도 함께 제공합니다.
목차
- task_struct란?
- 주요 필드 설명
- 커널 스레드 상태 및 전이
- 커널 스레드 생성과 관리
- kthread_create() vs kthread_run()
- 주요 함수 정리
- 예제 코드
- 스레드 종료 흐름과 주의사항
- 전체 요약
1. task_struct란?
task_struct는 리눅스 커널이 프로세스와 스레드를 관리할 때 사용하는 핵심 구조체로, 각 태스크의 상태, 우선순위, 메모리 정보 등을 저장합니다. 커널은 이 구조체를 통해 스케줄링 및 상태 전이를 관리합니다.
2. 주요 필드 설명
필드 | 설명 |
state | 태스크의 현재 상태 |
*stack | 커널 스택 포인터 |
prio, normal_prio | 우선순위 |
sched_class, sched_entity | 스케줄링 정보 |
cpu, cpus_allowed | 할당된 CPU |
mm, active_mm | 사용자 공간 메모리 정보 |
exit_state, exit_code | 종료 상태 |
tasks | 태스크 링크드 리스트 |
3. 커널 스레드 상태 및 전이
상태값 예시
값 | 의미 |
-1 | 실행 불가능 |
0 | 실행 가능 |
>0 | 대기 중 (sleep) |
상태 전이 흐름
[NEW] → [TASK_RUNNING] ↔ [TASK_RUNNING]
↓
[TASK_INTERRUPTIBLE / UNINTERRUPTIBLE]
↓
[TASK_ZOMBIE]
상태 | 설명 |
TASK_RUNNING | 실행 중 또는 대기 큐에 있음 |
TASK_INTERRUPTIBLE | 시그널로 깰 수 있는 대기 |
TASK_UNINTERRUPTIBLE | 시그널로 깨지 않는 대기 |
TASK_STOPPED | 정지된 상태 |
TASK_ZOMBIE | 종료 대기 중 |
4. 커널 스레드 생성과 관리
kthread란?
- 2.6 커널 이후 도입된 고수준 스레드 API
- ps 명령어 시 [이름] 형식으로 출력됨
주요 함수
함수 | 설명 |
kthread_create() | 생성만 수행 (실행은 wake_up_process()로) |
kthread_run() | 생성과 실행을 동시에 수행 |
kthread_should_stop() | 종료 요청 확인용 |
kthread_stop() | 스레드 종료 요청 및 정리 수행 |
예제 코드
static struct task_struct *my_kthread;
int my_thread_fn(void *data) {
while (!kthread_should_stop()) {
printk("running in kernel thread\n");
ssleep(1);
}
return 0;
}
static int __init my_module_init(void) {
my_kthread = kthread_run(my_thread_fn, NULL, "kthread_example");
return 0;
}
static void __exit my_module_exit(void) {
if (my_kthread)
kthread_stop(my_kthread);
}
5. 스레드 종료 흐름과 주의사항
종료 방식
- kthread_stop() 호출 시 내부적으로 종료 플래그 설정
- 스레드 함수 내 반복문에서 kthread_should_stop()을 체크해야 정상 종료됨
반환값
- kthread_stop()은 thread_fn()의 반환값을 리턴함
int thread_fn(void *arg) {
while (!kthread_should_stop()) {
printk("Thread working...\n");
ssleep(1);
}
return 123;
}
// 외부에서
int ret = kthread_stop(task); // ret == 123
6. 전체 요약
개념 | 함수 설명 |
task_struct | 태스크의 모든 정보를 담는 커널 구조체 |
kthread_create() | 스레드 생성 (비활성 상태) |
kthread_run() | 생성 + 실행 |
kthread_stop() | 종료 요청 및 정리 |
kthread_should_stop() | 종료 여부 확인 |
종료 방식 | 자발적 종료를 유도함 (flag 기반) |
'임베디드' 카테고리의 다른 글
임베디드 리눅스 드라이버의 이해 8편: 블로킹 입출력 (Blocking I/O) (1) | 2025.06.04 |
---|---|
임베디드 리눅스 드라이버의 이해 7편: 세마포어 경쟁과 커널 동기화 메커니즘 (2) | 2025.06.04 |
임베디드 리눅스 드라이버의 이해 5편: 커널과 하드웨어의 연결 (0) | 2025.06.04 |
임베디드 리눅스 드라이버의 이해 4편: 인터럽트 처리의 원리 (1) | 2025.06.04 |
임베디드 리눅스 드라이버의 이해 3편: 커널에서의 메모리 할당 (0) | 2025.06.04 |