Linux內核多線程(二)


內核多線程是在項目中使用到,自己也不熟悉,遇到一個很囧的問題,導致cpu運行100%。

這是寫的第一個內核線程程序,通過全局變量來實現兩個內核線程之間的通信。但是這里遇到致命錯誤,就是:每當 wait_event_interruptible()被wake_up_interruptible 喚醒之后線程就進入死循環。后面發現是線程不會主動的自己調度,需要顯式的通過schedule 或者 schedule_timeout()來調度。如果不加tc = 0 這一行,wait_event_intrruptible()就一直不會睡眠(參見前面的文章“等待隊列”),不會被調度放棄CPU,因此進入死循環。這個過程可以通過分析wait_event_intrruptible()的源代碼來看出。

 

#include <linux/init.h>   

#include <linux/module.h>   

#include <linux/kthread.h>   

#include <linux/wait.h>

  
MODULE_LICENSE("Dual BSD/GPL");  

  
static struct task_struct * _tsk;  

static struct task_struct * _tsk1;

static int tc = 0;

static wait_queue_head_t log_wait_queue;

  

static int thread_function(void *data)  
{  

    do {  

                printk(KERN_INFO "IN thread_function thread_function: %d times \n", tc);    

        
                   wait_event_interruptible(log_wait_queue,tc == 10);

                   tc = 0;  ///必須加這一行,內核才會進行調度。內核線程不像應用程序會主動調度,我們需要顯式的使用調度函數,想要在thread_function_1中去重置tc的值是不可能的,因為線程不會被調度,該線程會一直占用CPU

                           
                   printk(KERN_INFO "has been woke up !\n");

    }while(!kthread_should_stop());  

    return tc;  
}  


static int thread_function_1(void *data)  
{  

    do {  

              printk(KERN_INFO "IN thread_function_1 thread_function: %d times\n", ++tc);  

       

                   if(tc == 10 && waitqueue_active(&log_wait_queue))

                   {

                            wake_up_interruptible(&log_wait_queue);

                   }

                   msleep_interruptible(1000);

                  
    }while(!kthread_should_stop());  

    return tc;  

}  

  
static int hello_init(void)  

{  

    printk(KERN_INFO "Hello, world!\n");  

    init_waitqueue_head(&log_wait_queue);

    _tsk = kthread_run(thread_function, NULL, "mythread"); 

    if (IS_ERR(_tsk)) {  //需要使用IS_ERR()來判斷線程是否有效,后面會有文章介紹IS_ERR()

        printk(KERN_INFO "first create kthread failed!\n");  

    }  

    else {  

        printk(KERN_INFO "first create ktrhead ok!\n");  

    }  

          _tsk1 = kthread_run(thread_function_1,NULL, "mythread2");

    if (IS_ERR(_tsk1)) {  

        printk(KERN_INFO "second create kthread failed!\n");  

    }  

    else {  

        printk(KERN_INFO "second create ktrhead ok!\n");  

    }  

    return 0;  

}  

  
static void hello_exit(void)  
{  

    printk(KERN_INFO "Hello, exit!\n");  

    if (!IS_ERR(_tsk)){  

        int ret = kthread_stop(_tsk);  

        printk(KERN_INFO "First thread function has stopped ,return %d\n", ret);  

    }  

    if(!IS_ERR(_tsk1))

         {

                   int ret = kthread_stop(_tsk1);

                   printk(KERN_INFO "Second thread function_1 has stopped ,return %d\n",ret);

         }

}  

  
module_init(hello_init);  

module_exit(hello_exit);  

說明:這個程序的目的就是,使用一個線程(thread_function_1)通知另外一個線程(thread_function)某個條件(tc == 10)滿足(比如接收線程收到10幀然后通知處理線程處理接收到的數據)

運行結果:

程序加載並運行(tc 的值等於10 之后 就會喚醒另外一個線程,之后tc又從10開始計數):

程序卸載(程序卸載其實還是要很注意的,很多程序在卸載的時候回出現各種問題后面文章會提到):


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM