内核线程

基于Linux-5.10

1. 内核线程的创建

(1) 使用 kthread_create 创建线程

//include/linux/kthread.h
#define kthread_create(threadfn, data, namefmt, arg...) \
    kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg)

这个函数可以像 printk() 一样传入某种格式的线程名,线程创建后,不会马上运行,需要唤醒后才能执行,一般调用 wake_up_process() 唤醒线程。

 

(2) 使用 kthread_run 创建被唤醒线程

//include/linux/kthread.h
#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;                                   \
})

注:内核线程名超过15字节,截取的是前15字节的字符串,应用线程截取的却是最后15字节的字符串。

 

2. 内核线程的停止

线程一旦启动起来后,会一直运行,除非该线程主动调用 do_exit() 退出,或者其它的线程调用 kthread_stop() 结束它的运行。

//kernel/kthread.c
int kthread_stop(struct task_struct *k)

主要逻辑是将 KTHREAD_SHOULD_STOP 设置到 k->set_child_tid->flags 中,然后唤醒线程,等待其退出,并返回线程的 k->exit_code。能正确使线程退出依赖于线程执行流程中调用 kthread_should_stop() 对此标志的检查,若是判断为真,就退出内核线程的执行流程。

 

3. 将内核线程标记为RT线程

//core_ctl.c
int cluster_init(const struct cpumask *mask) {
    ...
    struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; //这样设置后prio=0,最高,赋值为0应该是99.

    cluster->core_ctl_thread = kthread_run(try_core_ctl, (void *) cluster, "core_ctl_v2.1/%d", first_cpu);
    if (IS_ERR(cluster->core_ctl_thread))
        return PTR_ERR(cluster->core_ctl_thread);

    sched_setscheduler_nocheck(cluster->core_ctl_thread, SCHED_FIFO, &param);
}

 

4. 内核线程也可以被用作worker线程

/* 将内核线程定义为worker并初始化 #define DEFINE_KTHREAD_WORKER(worker) struct kthread_worker worker = KTHREAD_WORKER_INIT(worker) */
static DEFINE_KTHREAD_WORKER(worker);
struct task_struct *work_thread = kthread_run(kthread_worker_fn, &worker, "kthread_worker_thread");

/* 定义work并初始化 */
struct kthread_work work;
void work_callback_func(struct kthread_work *work) {...}
kthread_init_work(&work, work_callback_func);

/* 对worker queue work */
kthread_queue_work(&worker, &work);

queue work后会唤醒 work_thread 执行 kthread_worker_fn(),会在进程上下文中执行 work_callback_func() 回调,使用起来比较方便。

 

posted on 2022-01-01 15:34  Hello-World3  阅读(385)  评论(0编辑  收藏  举报

导航