建立核心線程:
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data, const char namefmt[]);
喚醒核心線程(可以喚醒所有進程(線程)):
wake_up_process(struct task_struct *k);
建立並運行核心線程:
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data, const char namefmt[]);
通知核心線程停止:
int kthread_stop(struct task_struct *k);
返回threadfn函數的傳回值, 如果k沒有被wake_up_process(k)過將返回-EINTR
不是強制停止, 如果核心線程不停止將一直等待
檢查是否收到停止訊號:
int kthread_should_stop(void);
kthread_create與kernel_thread的區別
從表面上來看,這兩個函數非常的類似,但是實現卻是相差甚遠。
kthread_create是通過work_queue來實現的,kernel_thread是通過do_fork來實現的。
kernel thread可以用kernel_thread建立,但是在執行函數裡面必須用daemonize釋放資源並掛到init下,還需要用 completion等待這一過程的完成。
kthread_create是比較正牌的建立函數,這個不必要調用daemonize,用這個建立的kernel thread都掛在了kthread線程下。
可以在非核心線程中調用kernel_thread, 但這樣建立的線程必須在自己調用daemonize(...)來釋放資源,成為真正的核心線程。
#include <linux/kernel.h>
#include <linux/module.h>
static int noop(void *dummy)
{
int i = 0;
daemonize("mythread");
while(i++ < 5) {
printk("current->mm = %p\n", current->mm);
printk("current->active_mm = %p\n", current->active_mm);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(10 * HZ);
}
return 0;
}
static int test_init(void)
{
kernel_thread(noop, NULL, CLONE_KERNEL | SIGCHLD);
return 0;
}
static void test_exit(void) {}
module_init(test_init);
module_exit(test_exit);
”mythread“就是給這個核心線程取的名字, 可以用ps -A來查看。
schedule()用於進程調度, 可以理解為放棄CPU的使用權.
kthread_create建立線程
1 使用kthread_create建立線程:
struct task_struct *kthread_create(int (*threadfn)(void *data), void *data,
const char *namefmt, ...);
這個函數可以像printk一樣傳入某種格式的線程名
線程建立後,不會馬上運行,而是需要將kthread_create() 返回的task_struct指標傳給wake_up_process(),然後通過此函數運行線程。
2. 當然,還有一個建立並啟動線程的函數:kthread_run
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data,
const char *namefmt, ...);
3. 線程一旦啟動起來後,會一直運行,除非該線程主動調用do_exit函數,或者其他的進程調用kthread_stop函數,結束線程的運行。
int kthread_stop(struct task_struct *thread);
kthread_stop() 通過發送訊號給線程。
如果線程函數正在處理一個非常重要的任務,它不會被中斷的。當然如果線程函數永遠不返回並且不檢查訊號,它將永遠都不會停止。
參考:Kernel threads made easy -- view plaincopy to clipboardprint?
#include <linux/kthread.h>
static struct task_struct * _task;
static struct task_struct * _task2;
static struct task_struct * _task3;
static int thread_func(void *data)
{
int j,k;
int timeout;
wait_queue_head_t timeout_wq;
static int i = 0;
i++;
j = 0;
k = i;
printk("thread_func %d started\n", i);
init_waitqueue_head(&timeout_wq);
while(!kthread_should_stop())
{
interruptible_sleep_on_timeout(&timeout_wq, HZ);
printk("[%d]sleeping..%d\n", k, j++);
}
return 0;
}
void my_start_thread(void)
{
//_task = kthread_create(thread_func, NULL, "thread_func2");
//wake_up_process(_task);
_task = kthread_run(thread_func, NULL, "thread_func2");
_task2 = kthread_run(thread_func, NULL, "thread_func2");
_task3 = kthread_run(thread_func, NULL, "thread_func2");
if (!IS_ERR(_task))
{
printk("kthread_create done\n");
}
else
{
printk("kthread_create error\n");
}
}
void my_end_thread(void)
{
int ret = 0;
ret = kthread_stop(_task);
printk("end thread. ret = %d\n" , ret);
ret = kthread_stop(_task2);
printk("end thread. ret = %d\n" , ret);
ret = kthread_stop(_task3);
printk("end thread. ret = %d\n" , ret);
}
#include <linux/kthread.h>
static struct task_struct * _task;
static struct task_struct * _task2;
static struct task_struct * _task3;
static int thread_func(void *data)
{
int j,k;
int timeout;
wait_queue_head_t timeout_wq;
static int i = 0;
i++;
j = 0;
k = i;
printk("thread_func %d started\n", i);
init_waitqueue_head(&timeout_wq);
while(!kthread_should_stop())
{
interruptible_sleep_on_timeout(&timeout_wq, HZ);
printk("[%d]sleeping..%d\n", k, j++);
}
return 0;
}
void my_start_thread(void)
{
//_task = kthread_create(thread_func, NULL, "thread_func2");
//wake_up_process(_task);
_task = kthread_run(thread_func, NULL, "thread_func2");
_task2 = kthread_run(thread_func, NULL, "thread_func2");
_task3 = kthread_run(thread_func, NULL, "thread_func2");
if (!IS_ERR(_task))
{
printk("kthread_create done\n");
}
else
{
printk("kthread_create error\n");
}
}
void my_end_thread(void)
{
int ret = 0;
ret = kthread_stop(_task);
printk("end thread. ret = %d\n" , ret);
ret = kthread_stop(_task2);
printk("end thread. ret = %d\n" , ret);
ret = kthread_stop(_task3);
printk("end thread. ret = %d\n" , ret);
} 在執行kthread_stop的時候,目標線程必須沒有退出,否則會Oops。原因很容易理解,當目標線程退出的時候,其對應的task結構也變得無效,kthread_stop引用該無效task結構就會出錯。 為了避免這種情況,需要確保線程沒有退出,其方法如代碼中所示: thread_func() { // do your work here // wait to exit while(!thread_could_stop()) { wait(); } } exit_code() { kthread_stop(_task); //發訊號給task,通知其可以退出了 } 這種退出機制很溫和,一切盡在thread_func()的掌控之中,線程在退出時可以從容地釋放資源,而不是莫名其妙地被人“暗殺”。