Skip to main content
 首页 » 操作系统

Linux 内核线程

2022年07月19日202kerrycode

基于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); 
}

本文参考链接:https://www.cnblogs.com/hellokitty2/p/15755485.html