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");

 

转载于:https://www.cnblogs.com/Lyunfei/p/10506854.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值