线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每个线程并行执行不同的任务。
很多时候会需要在后台执行一些任务,比如做一个需要实时监控某个模块状态的debug功能,这种任务可以通过内核线程实现。
头文件
//wake_up_process()#include //kthread_create(), kthread_run()#include //IS_ERR()、PTR_ERR()#include
操作线程的步骤:
1.创建线程kthread_create
2.唤醒线程wake_up_process
3.结束线程kthread_stop
*另外Linux也提供了接口kthread_run将1和2整合成一个步骤。
创建线程kthread_create
kthread_create是kthread_create_on_node的宏定义,创建线程后不会马上运行,其源码如下:
#define kthread_create(threadfn, data, namefmt, arg...) \ kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg)
kthread_create_on_node的定义在文件kernel/kthread.c中,原型如下:
__printf(4, 5)struct task_struct *kthread_create_on_node( int (*threadfn)(void *data), void *data, int node, const char namefmt[], ...);
参数说明
threadfn:线程函数,即开启线程后需要call的API;
data:线程函数的形参,可以是NULL;
namefmt:线程名称;
返回值:线程指针strcut task_struct *;
唤醒线程wake_up_process
使用kthread_create创建线程后,需要将返回值
(struct task_struct *)作为参数传入wake_up_process()将线程唤醒,线程才会跑起来,原型:
extern int wake_up_process(struct task_struct *tsk);
创建并运行线程kthread_run
kthread_run是将kthread_create以及wake_up_process整合的宏定义,创建线程并运行,源码如下:
#define kthread_run(threadfn, data, namefmt, ...) \({ \ struct task_struct *__k \ = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ if (!IS_ERR(__k)) \ wake_up_process(__k); \ __k; \})
结束线程kthread_stop
将创建线程时返回的线程指针(struct task_struct *)作为参数传入kthread_stop(),设置结束标志should_stop,原型:
int kthread_stop(struct task_struct *k);
在线程中用到的其他API
set_freezable()//将线程设置成可冻结,如果系统会休眠,则需要使用kthread_should_stop()//检查线程的结束标志should_stop并返回set_current_state()//设置线程任务的当前状态,参数宏定义在头文件include/linux/sched.h中
创建线程实例
LunuxMemo_kthread.c
#include #include #include //wake_up_process()#include //kthread_create(), kthread_run()#include //IS_ERR()、PTR_ERR()#define CREATE_KTHREAD 1#define STOP_KTHREAD 0//kthread taskvoid LinuxMemo_kthread_task(void){ printk(KERN_EMERG "Plz Follow Wechat Account: LinuxMemo\n"); /* * Add YOUR code here */}//kthread functionint LinuxMemo_thread_func(void *data){ char *name = (char *)data; //name = "LinuxMemo" printk(KERN_EMERG "Plz Follow Wechat Account: %s\n", name); set_freezable(); //set kthread freezable while (!kthread_should_stop()) { LinuxMemo_kthread_task(); } return 0;}//Create or stop a kthreadint LinuxMemo_kthread_set(int set){ char *name = "LinuxMemo"; static struct task_struct *LinuxMemo_kthread; if (CREATE_KTHREAD == set) { //create and wake up a kthread LinuxMemo_kthread = kthread_create(LinuxMemo_thread_func, (void *)name, "LinuxMemo_kthread"); if (IS_ERR(LinuxMemo_task)) { printk(KERN_EMERG "[%s] create LinuxMemo_kthread error\n", __func__); err = PTR_ERR(LinuxMemo_kthread); LinuxMemo_kthread = NULL; return err; } wake_up_process(LinuxMemo_task); printk(KERN_EMERG "[%s] LinuxMemo_kthread start\n", __func__); } else if (STOP_KTHREAD == set) { if (LinuxMemo_kthread) { //Stop a kthread if (0 == kthread_stop(LinuxMemo_kthread)) { printk(KERN_EMERG "[%s] LinuxMemo_kthread stop\n", __func__); } else { printk(KERN_EMERG "[%s] LinuxMemo_kthread stop error\n", __func__); } LinuxMemo_task = NULL; } } return 0;}