本文摘自http://www.cnblogs.com/zhuyp1015/archive/2012/06/11/2545702.html

内核多线程是在项目中使用到,自己也不熟悉,遇到一个很囧的问题,导致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 = ;

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 == ); tc = ; ///必须加这一行,内核才会进行调度。内核线程不像应用程序会主动调度,我们需要显式的使用调度函数,想要在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 == && waitqueue_active(&log_wait_queue)) { wake_up_interruptible(&log_wait_queue); } msleep_interruptible(); }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 ; } 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开始计数)

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

linux驱动之内核多线程(二)的更多相关文章

  1. linux驱动之内核多线程(一)

    本文摘自http://www.cnblogs.com/zhuyp1015/archive/2012/06/11/2545624.html Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进 ...

  2. linux驱动之内核多线程(四)

    本文摘自 http://www.cnblogs.com/zhuyp1015/archive/2012/06/13/2548494.html 自己创建的内核线程,当把模块加载到内核之后,可以通过:ps ...

  3. linux驱动之内核多线程(三)

    本文摘自 http://www.cnblogs.com/zhuyp1015/archive/2012/06/13/2548458.html 接上 一篇文章 ,这里介绍另一种线程间通信的方式:compl ...

  4. Linux驱动之内核自带的S3C2440的LCD驱动分析

    先来看一下应用程序是怎么操作屏幕的:Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户 ...

  5. 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序

    Nor Flash和Nand Flash的不同: 类型 NOR Flash  Nand Flash  接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...

  6. 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序

    NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...

  7. 嵌入式Linux驱动学习之路(二十)USB设备驱动

    USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...

  8. Linux驱动之内核加载模块过程分析

    Linux内核支持动态的加载模块运行:比如insmod first_drv.ko,这样就可以将模块加载到内核所在空间供应用程序调用.现在简单描述下insmod first_drv.ko的过程 1.in ...

  9. 小松之LINUX 驱动学习笔记(二)

    这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下 ...

随机推荐

  1. 常用核心数据库查询sql

    一.查询账户信息 -- 查询数据量 /*{"xdb_comment":"1","table":"mb_tran_hist" ...

  2. hostapd阅读(openwrt)-1

    好久没有来博客园写点东西了,这段时间主要搞了openwrt系统的移植,无线的校验等相关工作,鉴于我是一个懒惰的大龄菜鸟程序员,就先自我原谅自己了,好了废话少说,直奔主题--hostapd. 由于我主要 ...

  3. 中缀转逆波兰表达式 c++ 队列,栈

    记得早在几十天以前,xty 学长曾让我学这个.一直推到了现在哈 咕咕咕(能鸽善鹉orz) 抱歉,学妹我来还愿了! 中缀表达式比较适合人类的计算,但是后缀表达式更适合机器计算(毕竟没有那么多运算符优先级 ...

  4. Redis服务之常用配置(二)

    上一篇博客我们聊了下redis的INCLUDE.NETWORK.GENERAL配置段相关配置和说明,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/133831 ...

  5. 微服务迁移记(五):WEB层搭建(2)-SpringSecurity集成

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 接下来,集成SpringSecruity,实现用户 ...

  6. Day02_CMS前端开发

    CMS前端开发 1 Vue.js与Webpack研究 参考链接:https://www.cnblogs.com/artwalker/p/13387386.html 2 CMS前端工程创建 2.1 导入 ...

  7. Seaborn基础2

    import matplotlib.pyplot as plt import seaborn as sns import numpy as np def sinplot(flip = 1): x = ...

  8. JS中Math.random()的使用和扩展

    Math.random()方法返回大于等于 0 小于 1 的一个随机数.对于某些站点来说,这个方法非常实用,因为可以利用它来随机显示一些名人名言和新闻事件. 在连续整数中取得一个随机数 值 = Mat ...

  9. PHP image_type_to_extension - 获取图片后缀

    image_type_to_extension — 根据指定的图像类型返回对应的后缀名.高佣联盟 www.cgewang.com 语法 string image_type_to_extension ( ...

  10. 【机器学习的Tricks】随机权值平均优化器swa与pseudo-label伪标签

    文章来自公众号[机器学习炼丹术] 1 stochastic weight averaging(swa) 随机权值平均 这是一种全新的优化器,目前常见的有SGB,ADAM, [概述]:这是一种通过梯度下 ...