zoukankan      html  css  js  c++  java
  • 内核线程的创建、使用和退出;关于延时宏的补充说明

      启发主要来自于http://blog.csdn.net/newnewman80/article/details/7050090,基本是根据自己的习惯重组的。

    相关函数:

    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()组成。 

    #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 线程名

    示例程序:使用模块加载内核线程,实现每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,'\0',strlen(data)+1);
        strncpy(mydata,data,strlen(data));
        while(!kthread_should_stop())
        {
            SLEEP_MILLI_SEC(1000);
            printk("%s\n",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;
    }
    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); MODULE_LICENSE("GPL"); MODULE_AUTHOR("anonymous");

    补充说明:

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

     

  • 相关阅读:
    今晚直播 | 揭秘携程应用路由生态系统
    OpenStack虚拟云桌面在携程呼叫中心的应用
    从设计到开发,硅谷技术专家教你做“声控”APP
    深度学习系列 | 诺亚面向语音语义的深度学习研究进展
    知识图谱中的推理技术及其在高考机器人中的应用
    用户在线广告点击行为预测的深度学习模型
    知识库上的问答系统:实体、文本及系统观点
    深度学习在搜狗无线搜索广告中的应用
    元旦三天假期,实现一个电商退单管理系统【四】-手机客户端实现
    元旦三天假期,实现一个电商退单管理系统【三】
  • 原文地址:https://www.cnblogs.com/wuyuegb2312/p/2568411.html
Copyright © 2011-2022 走看看