程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 基於內核線程的創建、使用和退出以及延時宏的補充說明介紹

基於內核線程的創建、使用和退出以及延時宏的補充說明介紹

編輯:C語言基礎知識

相關函數:

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 線程名

示例程序:使用模塊加載內核線程,實現每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;#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;
}

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)即可。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved