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开始计数):

程序卸载(程序卸载其实还是要很注意的,很多程序在卸载的时候回出现各种问题后面文章会提到):

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux内核,可以通过内核线程(kernel thread)来实现多线程内核线程是独立运行在内核空间的标准进程,与普通进程相比,内核线程没有独立的地址空间,mm指针被设置为NULL,只在内核空间运行,不切换到用户空间去。内核线程可以被调度和抢占。 在Linux内核,可以使用kthread_run()函数来创建内核线程。这个函数接受一个执行函数和一个参数作为参数,可以在执行函数完成一些后台任务。创建的内核线程可以通过kthread_stop()函数来停止。 在早期的Linux 2.6版本,可以使用kernel_thread()函数来创建内核线程。但在较新的版本已不推荐使用该方式,因为在4.1版本不再使用export。使用kernel_thread()创建的非内核线程需要在其执行函数调用daemonize()函数来释放资源。 除了以上两种方式,还可以使用kthread_create()函数来创建内核线程。这个函数与kthread_run()类似,用法也相似。 总之,在Linux内核可以通过内核线程来实现多线程的功能,这些内核线程可以在后台执行一些任务,具有调度和抢占的特性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Linux内核多线程](https://blog.csdn.net/Frank_sample/article/details/116455771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值