基于内核线程的创建、使用和退出以及延时宏的补充说明介绍

杨宁博客

杨宁博客

2016-02-19 09:49

清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐基于内核线程的创建、使用和退出以及延时宏的补充说明介绍,无聊中的都看过来。

相关函数:

kthread_create():创建内核线程
代码如下:

struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);  kernel thread可以用kernel_thread创建,但是在执行函数里面必须用daemonize释放资源并挂到init下,还需要用completion等待这一过程的完成。为了简化操作,定义了kthread_create。

线程创建后,不会马上运行,而是需要将kthread_create() 返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。
 

kthread_run():创建并启动线程的函数。
代码如下:

struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,const char *namefmt, ...);它实际上是个宏,由kthread_create()和wake_up_process()组成。

它实际上是个宏,由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():通过发送信号给线程,使之退出。
代码如下:

int kthread_stop(struct task_struct *thread);

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。
但如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。

同时,在调用kthread_stop函数时,线程函数不能已经运行结束。否则,kthread_stop函数会一直进行等待。

内核线程的一般框架

int threadfunc(void *data){

        …

        while(1){

               set_current_state(TASK_UNINTERRUPTIBLE);

               if(kthread_should_stop()) break;

               if(){//条件为真

                      //进行业务处理

               }

               else{//条件为假

                      //让出CPU运行其他线程,并在指定的时间内重新被调度

                      schedule_timeout(HZ);

               }

        }

        …

        return 0;

}

线程相关测试命令

  可以使用top命令来查看线程(包括内核线程)的CPU利用率。命令如下:

    top –p 线程号

  可以使用下面命令来查找线程号:

    ps aux|grep 线程名

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

示例程序:使用模块加载内核线程,实现每1s在内核中打印字符。

(makefile略去,和以前一篇博文一样的写法。)
代码如下:

#include linux/init.h
#include linux/module.h
#include linux/kernel.h
#include linux/sched.h   //wake_up_process()
#include linux/kthread.h //kthread_create(),kthread_run()
#include linux/err.h //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)
do {
long timeout = (nMilliSec) * HZ / 1000;
while(timeout 0)
{
timeout = schedule_timeout(timeout);
}
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%sn",mydata);
    }
    kfree(mydata);
    return 0;

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...n");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
    }
    wake_up_process(my_task);
    return 0;#include linux/init.h
#include linux/module.h
#include linux/kernel.h
#include linux/sched.h   //wake_up_process()
#include linux/kthread.h //kthread_create(),kthread_run()
#include linux/err.h //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)
do {
long timeout = (nMilliSec) * HZ / 1000;
while(timeout 0)
{
timeout = schedule_timeout(timeout);
}
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%sn",mydata);
    }
    kfree(mydata);
    return 0;

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...n");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
}

static void __exit kernel_thread_exit(void)
{
    if(my_task){
        printk(KERN_ALERT "Cancel this kernel thread.n");
        kthread_stop(my_task);
        printk(KERN_ALERT "Canceled.n");
        }
}

module_init(kernel_thread_init);
module_exit(kernel_thread_exit);

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

MODULE_LICENSE("GPL");
MODULE_AUTHOR("anonymous");

补充说明:

  这个延时宏在一些情况下会造成内核线程CPU占用率过高的情况。根据对schedule_timeout()源码的分析,它只是周期使线程成为TASK_RUNNING状态,这个线程并没有真正的睡眠。解决办法:在while循环中的起始处加入set_current_state(TASK_INTERRUPTIBLE)即可。

展开更多 50%)
分享

猜你喜欢

基于内核线程的创建、使用和退出以及延时宏的补充说明介绍

编程语言 网络编程
基于内核线程的创建、使用和退出以及延时宏的补充说明介绍

理解iOS多线程应用的开发以及线程的创建方法

编程语言 网络编程
理解iOS多线程应用的开发以及线程的创建方法

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

内核线程优先级设置的方法介绍

编程语言 网络编程
内核线程优先级设置的方法介绍

java线程之使用Runnable接口创建线程的方法

编程语言 网络编程
java线程之使用Runnable接口创建线程的方法

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

基于条件变量的消息队列 说明介绍

编程语言 网络编程
基于条件变量的消息队列 说明介绍

基于Android AppWidgetProvider的使用介绍

编程语言 网络编程
基于Android AppWidgetProvider的使用介绍

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

详解玩游戏电脑自动断电关机的缘由

详解玩游戏电脑自动断电关机的缘由

android调试工具DDMS的使用详解

android调试工具DDMS的使用详解
下拉加载更多内容 ↓