Linux 內核線程API指南


1. Linux 內核線程簡介

 Linux 內核線程(KERNEL THREAD)完全獨立運行在內核空間,並且不能被切換到用戶空間運行,也沒有獨立內核地址空間。除此之外,與普通的線程一樣,可以被調度和搶占。

2. Linux 內核線程相關的API

2.1 內核線程相關頭文件

  1. #include <linux/errno.h>
  2. #include <linux/sched.h>
  3. #include <linux/thread.h>

 

2.2 創建內核線程函數

1). kthread_create 函數用於創建一個內核線程,當時該內核線程並不會馬上啟動,需要調用wake_up_process啟動線程。相關函數詳情如下所示。
1 #define kthread_create(threadfn, data, namefmt, arg...) \
2     kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)
 1 /**  2  * kthread_create_on_node - create a kthread.  3  * @threadfn: the function to run until signal_pending(current).  4  * @data: data ptr for @threadfn.  5  * @node: memory node number.  6  * @namefmt: printf-style name for the thread.  7  *  8  * Description: This helper function creates and names a kernel  9  * thread. The thread will be stopped: use wake_up_process() to start 10  * it. See also kthread_run(). 11  * 12  * If thread is going to be bound on a particular cpu, give its node 13  * in @node, to get NUMA affinity for kthread stack, or else give -1. 14  * When woken, the thread will run @threadfn() with @data as its 15  * argument. @threadfn() can either call do_exit() directly if it is a 16  * standalone thread for which no one will call kthread_stop(), or 17  * return when 'kthread_should_stop()' is true (which means 18  * kthread_stop() has been called). The return value should be zero 19  * or a negative error number; it will be passed to kthread_stop(). 20  * 21  * Returns a task_struct or ERR_PTR(-ENOMEM). 22  */
23 struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), 24                        void *data, 25                        int node, 26                        const char namefmt[], 27                        ...)

 

2). kthread_run 創建內核函數並啟動,函數原型如下所示。

 1 /**  2  * kthread_run - create and wake a thread.  3  * @threadfn: the function to run until signal_pending(current).  4  * @data: data ptr for @threadfn.  5  * @namefmt: printf-style name for the thread.  6  *  7  * Description: Convenient wrapper for kthread_create() followed by  8  * wake_up_process(). Returns the kthread or ERR_PTR(-ENOMEM).  9  */
10 #define kthread_run(threadfn, data, namefmt, ...)               \
11 ({ \ 12     struct task_struct *__k \ 13         = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ 14     if (!IS_ERR(__k)) \ 15  wake_up_process(__k); \ 16  __k; \ 17 })

 

3). kthread_stop 函數功能是結束某個線程(do_exit函數也可以實現相同功能),

/** * kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_stop() for @k to return true, wakes it, and * waits for it to exit. This can also be called after kthread_create() * instead of calling wake_up_process(): the thread will exit without * calling threadfn(). * * If threadfn() may call do_exit() itself, the caller must ensure * task_struct can't go away. * * Returns the result of threadfn(), or %-EINTR if wake_up_process() * was never called. */
int kthread_stop(struct task_struct *k)

 

4).   schedule_timeout 函數對當前進程進行調度,讓其進入睡眠狀態,讓出占有的系統資源,回到超時喚醒。

/** * schedule_timeout - sleep until timeout * @timeout: timeout value in jiffies * * Make the current task sleep until @timeout jiffies have * elapsed. The routine will return immediately unless * the current task state has been set (see set_current_state()). * * You can set the task state as follows - * * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to * pass before the routine returns. The routine will return 0 * * %TASK_INTERRUPTIBLE - the routine may return early if a signal is * delivered to the current task. In this case the remaining time * in jiffies will be returned, or 0 if the timer expired in time * * The current task state is guaranteed to be TASK_RUNNING when this * routine returns. * * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule * the CPU away without a bound on the timeout. In this case the return * value will be %MAX_SCHEDULE_TIMEOUT. * * In all cases the return value is guaranteed to be non-negative. */ signed long __sched schedule_timeout(signed long timeout)

 

 

3. 使用舉例

代碼評論:

  1. 這次實現了在linux 內核中創建了兩個內核線程,兩個線程都可以運行成功。

  2. 兩個內核線程運行全靠內核任務調度器進行調度,且使用了while(1) 死循環,占用系統資源過多。

#include <linux/errno.h> #include <linux/sched.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kthread.h> #include <linux/delay.h>

struct mytask_struct { unsigned long long int counter; struct task_struct *mykthread1; struct task_struct *mykthread2; }; static struct mytask_struct mytask = { .counter = 0, .mykthread1 = NULL, .mykthread2 = NULL, }; static int my_thread1(void *data) { while(1) { printk(KERN_INFO " my_thread1 counter %lld\n", ++mytask.counter); mdelay(1000); } return 0; } static int my_thread2(void *data) { while(1) { printk(KERN_INFO " my_thread2 counter %lld\n", ++mytask.counter); mdelay(1000); } return 0; } static int __init thread_init(void) { mytask.mykthread1 = kthread_create(my_thread1,NULL,"my_thread1"); if (IS_ERR(mytask.mykthread1)) { printk(KERN_EMERG "Create thread1 fail\n"); return PTR_ERR(mytask.mykthread1); }
    wake_up_process(mytask.mythread1);
 mytask.mykthread2 = kthread_run(my_thread2,NULL,"my_thread2"); if (IS_ERR(mytask.mykthread2)) { printk(KERN_EMERG "Create thread2 fail\n"); kthread_stop(mytask.mykthread1); return PTR_ERR(mytask.mykthread2); } return 0; } static void __exit thread_exit(void) { kthread_stop(mytask.mykthread1); kthread_stop(mytask.mykthread2); return; } module_init(thread_init); module_exit(thread_exit); MODULE_AUTHOR("https://www.cnblogs.com/Lyunfei/tag/"); MODULE_DESCRIPTION("Linux Kthread"); MODULE_LICENSE("GPL");

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM