转载_linux 两种方式 创建内核线程

本文介绍了在Linux环境下使用kernel_thread()和kthread_run()创建内核线程的方法,包括如何为线程设置名称以便于识别,以及创建过程中的错误处理。

kernel_thread()、daemonize()
------------------------------------------------------
int thread_func(void *arg)
{
    /* 
     * 设置线程名 -- thread_name,ps可以看到的线程名
     * 如果不使用daemonize设置内核线程名,并且kernel_thread()
     * 是用户态程序通过系统调用使用的,则ps将看到一个和用户进程同名
     * 的一个内核线程。
     */
    daemonize("thread_name"); 
    return 0;
}

 

{
    pid_t pid;
    /* 创建内核线程 */
    pid = kernel_thread(thread_func, NULL, CLONE_KERNEL);
    if (pid < 0)
    {
        printk("kernel_thread error\n");
    }
}

 

 



kthread_run() -- 这种创建方式比较简洁
------------------------------------------------------

#include <linux/kthread.h>

int thread_func(void *arg)
{
    return 0;
}


{
    struct task_struct * my_thread = NULL;
    int rc;
    my_thread = kthread_run(thread_func, NULL, "thread_name");
    if (IS_ERR(my_thread)) 
    {
        rc = PTR_ERR(my_thread);
        printk("error %d create thread_name thread", rc);
    }
}

注: kthread_run()最终调用kernel_thread()创建线程

 

 

 

 

 

 

 

kernel_thread()类似application编程里面的fork()
------------------------------------------------------
static int jffs2_garbage_collect_thread(void *_c)
{
    ...
    daemonize("jffs2_gcd_mtd%d", c->mtd->index);
    ...
    complete(&c->gc_thread_start);
    ...
}


int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
{
    pid_t pid;
    int ret = 0;

    BUG_ON(c->gc_task);

    init_completion(&c->gc_thread_start);
    init_completion(&c->gc_thread_exit);

    pid =kernel_thread(jffs2_garbage_collect_thread, c, CLONE_FS|CLONE_FILES);
    if (pid < 0) {  // 判断出错条件
        printk(KERN_WARNING "fork failed for JFFS2 garbage collect thread: %d\n", -pid);
        complete(&c->gc_thread_exit);
        ret = pid;
    } else {        // pid > 0 ,说明这个肯定在父进程中
        printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid);
        wait_for_completion(&c->gc_thread_start); //父进程等待子进程结束
    }

    return ret;
}

Linux内核线程是独立运行在内核空间的标准进程,内核经常使用它在后台执行一些操作 [^2][^4]。它也被叫做守护线程,在终端上用命令“ps -Al”列出的所有进程中,名字以k开头以d结尾的往往都是内核线程,比如kthreadd、kswapd [^3]。 内核线程和普通进程存在明显区别。内核线程没有独立的地址空间,mm指针被设置为NULL;它只在内核空间运行,从不切换到用户空间;并且和普通进程一样,可以被调度,也可以被抢占 [^2][^4]。实际上,内核线程只能由其他内核线程创建 [^2][^4]。 Linux 内核使用内核线程内核分成几个功能模块,例如 kswapd、kflushd 等,这在处理异步事件(如异步 IO)时特别有用,在内核中还能通过创建一个线程来查询按键状态 [^1]。内核线程的使用成本较低,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间 [^1]。支持多线程内核被称为多线程内核(Multi - Threads kernel),内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为它是调度的基本单位 [^1]。 在 Linux 驱动模块中,可以使用 kernel_thread()、kthread_create()/kthread_run() 两种方式创建内核线程,此外还可以用第三方库(如 pthread,pthread 也可用于用户空间)在驱动模块中创建线程 [^2]。 以下是一个简单的使用 kthread_create() 创建内核线程的示例代码: ```c #include <linux/init.h> #include <linux/module.h> #include <linux/kthread.h> #include <linux/delay.h> static struct task_struct *my_thread; static int my_thread_function(void *data) { while (!kthread_should_stop()) { printk(KERN_INFO "Kernel thread is running...\n"); msleep(1000); } return 0; } static int __init my_module_init(void) { my_thread = kthread_create(my_thread_function, NULL, "my_kthread"); if (IS_ERR(my_thread)) { printk(KERN_ERR "Failed to create kernel thread\n"); return PTR_ERR(my_thread); } wake_up_process(my_thread); return 0; } static void __exit my_module_exit(void) { kthread_stop(my_thread); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值