linux驱动之内核多线程(二)
本文摘自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驱动之内核多线程(二)的更多相关文章
- linux驱动之内核多线程(一)
本文摘自http://www.cnblogs.com/zhuyp1015/archive/2012/06/11/2545624.html Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进 ...
- linux驱动之内核多线程(四)
本文摘自 http://www.cnblogs.com/zhuyp1015/archive/2012/06/13/2548494.html 自己创建的内核线程,当把模块加载到内核之后,可以通过:ps ...
- linux驱动之内核多线程(三)
本文摘自 http://www.cnblogs.com/zhuyp1015/archive/2012/06/13/2548458.html 接上 一篇文章 ,这里介绍另一种线程间通信的方式:compl ...
- Linux驱动之内核自带的S3C2440的LCD驱动分析
先来看一下应用程序是怎么操作屏幕的:Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户 ...
- 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序
Nor Flash和Nand Flash的不同: 类型 NOR Flash Nand Flash 接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...
- 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序
NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...
- 嵌入式Linux驱动学习之路(二十)USB设备驱动
USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...
- Linux驱动之内核加载模块过程分析
Linux内核支持动态的加载模块运行:比如insmod first_drv.ko,这样就可以将模块加载到内核所在空间供应用程序调用.现在简单描述下insmod first_drv.ko的过程 1.in ...
- 小松之LINUX 驱动学习笔记(二)
这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下 ...
随机推荐
- CAS实现SSO 单点登录
结构 CAS分为两部分,CAS Server和CAS Client CAS Server用来负责用户的认证工作,就像是把第一次登录用户的一个标识存在这里,以便此用户在其他系统登录时验证其需不需要再次登 ...
- linux cp 拷贝不覆盖源文件
cp 参数 CP() User Commands CP() NAME cp - copy files and directories SYNOPSIS cp [OPTION]... [-T] SOUR ...
- Spring Boot 集成 WebSocket 实现服务端推送消息到客户端
假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的 ...
- PHP is_float()、 is_double()、is_real()函数
is_float() 函数用于检测变量是否是浮点型. 别名函数:is_double(),is_real().高佣联盟 www.cgewang.com 注意: 若想测试一个变量是否是数字或数字字符串(如 ...
- PHP is_iterable() 函数
is_iterable() 函数用于检测变量的是否是一个可迭代的值. PHP 版本要求: PHP 7 >= 7.1.0高佣联盟 www.cgewang.com 语法 bool is_iterab ...
- PHP mysqli_thread_id() 函数
返回当前连接的线程 ID,然后杀死连接: <?php 高佣联盟 www.cgewang.com // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli ...
- luogu P4725 多项式对数函数(多项式 ln)
LINK:多项式对数函数 多项式 ln 如题 是一个模板题.刚学会导数 几个知识点 \([f(x)\cdot g(x)]'=f(x)'g(x)+f(x)g(x)',f(g(x))'=f'(g(x))g ...
- 创建githup远程库并关联
第一种方法:远程new仓库时直接勾选初始化仓库,然后克隆到本地即可(注:本地对应层不可再初始化仓库git init).克隆下来的仓库已经与远程库建立了管理git removte 第二种方法:本地下面有 ...
- 使用VMware虚拟机建立Ubuntu与主机win7的文件共享与传输
1.要想在虚拟机与主机之间建立共享文件夹必须先安装VMware Tools.方法见https://www.cnblogs.com/lsc666js/p/13403919.html. 2.在VMware ...
- [NOI2012]随机数生成器【矩阵快速幂】
NOI2012 随机数生成器 题目描述 栋栋最近迷上了随机算法,而随机数是生成随机算法的基础.栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法 ...