1. kernel_thread VS kthread
2. kernel_thread
A. 소개
B. daemonize()
3. kthread
4. kthread 예제
1. kernel_thread VS kthread
linux kernel 에서 쓰레드를 구현하는 기법엔 크게 두가지가 있습니다.
첫번째는 kernel_thread() 를 사용하는 것이고
두번째는 kthread_xxxx() 를 사용하는 것입니다.
kernel_thread() 는 가장 기본적인 쓰레드 구현 방법인데 실제 커널 코드상에서는 사용 빈도가 극히 드뭅니다.
kernel_thread() 를 직접 사용하면 이것저것 해 줘야 할 것들이 많아지는데 kthread_xxxx() 계열을 사용하면 코드가 상당히 간단해 집니다.
kthread_create() kthread_run() kthread_bind() kthread_sop() kthread_should_stop() kthread_data() |
자세한 내용은 커널 소스 트리와 linux/kthread.h 를 참조해 주십시요.
2. kernel_thread
A. 소개
kernel_thread 는 잘 사용안하는 방법으로 생각됩니다. 커널 코드를 살펴보아도 5~6 군데에서만 사용하고 있습니다.
쓰레드 종료와 SMP 에 대해서는 크게 신경쓰고 있지 않는 것으로 보입니다.
샘플 코드는 아래와 같습니다.
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/kthread.h> int flag=0; struct task_struct *th_id; static int kernel_thread_thr_wait(void *arg) { int i = 0; char *text = (char *)arg; while(flag) { printk(KERN_ALERT "KERNEL_THREAD. %d [ %s ]\n", i, text); ++i; udelay(1000); } printk(KERN_ALERT "KERNEL_THREAD. Stoped\n"); return 0; } static void DONE(void) { flag = 0; } static int __init kernel_thread_init(void) { flag = 1; th_id = (struct task_struct *)kernel_thread(kernel_thread_thr_wait, "TEST", CLONE_KERNEL); if(IS_ERR(th_id)){ printk(KERN_ALERT "Fail to create the thread\n"); return -1; } udelay(5000); DONE(); 로 udelay(5000); return 0; } static void kernel_thread_release(void) { printk(KERN_ALERT "Exit %s()\n", __FUNCTION__); } module_init(kernel_thread_init); module_exit(kernel_thread_release); MODULE_LICENSE("Dual BSD/GPL"); |
B. daemonize()
kernel_thread() 로 생성된 쓰레드는 부모 쓰레드가 자식 쓰레드보다 먼저 죽게되면 자식 쓰레드는 좀비 쓰레드가 됩니다.
이런 일을 방지하기 위해서 daemonize() 를 호출하여 부모 쓰레드를 kthreadd 라는 커널 쓰레드로 바꿔주어서 자식 쓰레드가 죽을 때까지 기다릴 수 있게 만들어 줍니다.
사용방법은 커널 소스트리를 살펴봐 주세요.
3. kthread
대다수의 커널 쓰레드 들은 kthread 를 사용하여 구현되어 있습니다. (커널 소스 트리 검색)
쓰레드 생성 api
kthread_create();
kthread_run();
쓰레드 정지 api
kthread_stop();
kthread_should_stop();
그외 api
kthread_bind();
kthread_data();
kthreadadd();
kthread_worker();
init_kthread_worker();
init_kthread_work();
kthread_worker_fn();
queue_kthread_work();
flush_kthread_work();
flush_kthread_worker();
많은 API 가 있지만 주로 사용하는 API 는 아래와 같습니다.
kthread_create(); : 쓰레드 생성
kthread_run(); : 쓰레드 생성 + 잘생성되었는지 검사
kthread_stop(); : 쓰레드 종료하라고 명령 내림
kthread_should_stop(); : 쓰레드 종료 명령이 내려졌는지 검사함.
kthread_bind() : 쓰레드가 사용할 cpu 지정.
4. kthread 예제
kthread 에 대한 간단한 예제는 아래와 같습니다.
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/kthread.h> struct task_struct *g_th_id=NULL; static int kthread_example_thr_fun(void *arg) { printk(KERN_ALERT "@ %s() : called\n", __FUNCTION__); while(!kthread_should_stop()) { printk(KERN_ALERT "@ %s() : loop\n", __FUNCTION__); ssleep(1); } printk(KERN_ALERT "@ %s() : kthread_should_stop() called. Bye.\n", __FUNCTION__); return 0; } static int __init kthread_example_init(void) { printk(KERN_ALERT "@ %s() : called\n", __FUNCTION__); if(g_th_id == NULL){ g_th_id = (struct task_struct *)kthread_run(kthread_example_thr_fun, NULL, "kthread_example"); } return 0; } static void __exit kthread_example_release(void) { if(g_th_id){ kthread_stop(g_th_id); g_th_id = NULL; } printk(KERN_ALERT "@ %s() : Bye.\n", __FUNCTION__); } module_init(kthread_example_init); module_exit(kthread_example_release); MODULE_LICENSE("Dual BSD/GPL"); |
위 코드를 살펴보면 g_th_id 을 자동관리해 주지 않는다는 것을 알 수 있습니다.
항상 g_th_id 에 대한 관리를 확실히 해 주는 것이 중요할 것으로 예상됩니다.
'development' 카테고리의 다른 글
[kernel] 스핀락 (1) | 2012.01.04 |
---|---|
[program] Makefile (0) | 2012.01.04 |
[kernel] 시간지연 (1) | 2012.01.02 |
[kernel] 커널 메모리 모델 (0) | 2011.12.29 |
[etc] 빌드 시스템 (0) | 2011.12.23 |