Linux内核中实现生产者与消费者(避免无效唤醒)【转】
转自:http://blog.csdn.net/crazycoder8848/article/details/42581399
本文关注的重点是,避免内核线程的无效唤醒,并且主要是关注消费者线程的设计。
因此,为了省事,这里关与生产者,消费者本身的处理流程可能不够严密。
1. 生产者
一个内核线程,每生产一个商品后,就唤醒消费者,然后自己睡眠1秒钟。
2. 消费者
一个内核线程,每当被唤醒后,就消费商品,然后进入睡眠。
对于消费者线程的这种设计,有几个好处:响应快,平时不占任何cpu。
但这种设计有一点要注意,那就是要避免线程的无效唤醒。如何实现,看看消费者线程的代码就知道了。
/*
* kernel programming test code
*
* Copyright (C) 2014 Sun Mingbao <sunmingbao@126.com>
* Dual licensed under the MIT and/or GPL licenses.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
MODULE_AUTHOR("Sun Mingbao <sunmingbao@126.com>");
MODULE_DESCRIPTION("kernel programming test code");
MODULE_VERSION("1.0");
MODULE_LICENSE("Dual MIT/GPL");
#define MODULE_NAME "test"
#define WRITE_CONSOLE(fmt, args...) \
do \
{ \
printk(KERN_ALERT fmt,##args); \
} while (0)
#define DBG_PRINT(fmt, args...) \
do \
{ \
WRITE_CONSOLE(MODULE_NAME"_DBG:%s(%d)-%s:\n"fmt"\n", __FILE__,__LINE__,__FUNCTION__,##args); \
} while (0)
static struct task_struct *consumer_thread;
static struct task_struct *producer_thread;
static u32 cnt_consumer, cnt_producer;
static int has_something_to_consume = 0;
static void consume()
{
has_something_to_consume = 0;
cnt_consumer++;
}
static void produce()
{
has_something_to_consume = 1;
cnt_producer++;
}
static int consumer_thread_func(void * data)
{
while (!kthread_should_stop())
{
if (has_something_to_consume)
{
consume();
}
set_current_state(TASK_INTERRUPTIBLE);
if (has_something_to_consume)
{
set_current_state(TASK_RUNNING);
continue;
}
schedule();
}
if (has_something_to_consume)
{
consume();
}
}
static int producer_thread_func(void * data)
{
while (!kthread_should_stop())
{
produce();
if (consumer_thread->state & TASK_INTERRUPTIBLE)
{
wake_up_process(consumer_thread);
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
}
}
static int __init create_threads(void)
{
consumer_thread=kthread_run(consumer_thread_func, NULL, "consumer_thread");
producer_thread=kthread_run(producer_thread_func, NULL, "producer_thread");
return 0;
}
static struct proc_dir_entry *my_proc_dir;
static int misc_info_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
{
int ret;
static char proc_file_contents[128];
static int proc_file_len = 0;
if (0==offset || 0==proc_file_len)
{
proc_file_len=sprintf(proc_file_contents, "cnt_producer:%u\n""cnt_consumer:%u\n", cnt_producer, cnt_consumer);
}
ret=snprintf(buffer, length, "%s", proc_file_contents+offset);
if(ret+offset==proc_file_len)
*eof = 1;
return ret;
}
static int __init create_my_proc_entries(void)
{
my_proc_dir = proc_mkdir(MODULE_NAME, NULL);
create_proc_read_entry("misc_info"
,0
, my_proc_dir
, misc_info_read_proc
, NULL);
return 0;
}
static void __exit remove_my_proc_entries(void)
{
remove_proc_entry("misc_info", my_proc_dir);
remove_proc_entry(MODULE_NAME, NULL);
}
static int __init test_init(void)
{
int retval;
DBG_PRINT("start");
retval=create_threads();
if (retval < 0)
{
goto EXIT;
}
create_my_proc_entries();
DBG_PRINT("start succeed");
EXIT:
return retval;
}
static void __exit stop_threads(void)
{
kthread_stop(consumer_thread);
kthread_stop(producer_thread);
}
static void __exit test_exit(void)
{
DBG_PRINT("quit");
remove_my_proc_entries();
stop_threads();
}
module_init(test_init);
module_exit(test_exit);
Linux内核中实现生产者与消费者(避免无效唤醒)【转】的更多相关文章
- java多线程中的生产者与消费者之等待唤醒机制@Version1.0
一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒: Object类中提供了三个方法: wait():等待 notify():唤醒单个线程 notify ...
- java多线程中的生产者与消费者之等待唤醒机制@Version2.0
二.生产者消费者模式的学生类成员变量生产与消费demo, @Version2.0 在学生类中添加同步方法:synchronized get()消费者,synchronized set()生产者 最终版 ...
- Linux内核中常用的数据结构和算法(转)
知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...
- Linux内核中的队列 kfifo【转】
转自:http://airekans.github.io/c/2015/10/12/linux-kernel-data-structure-kfifo#api 在内核中经常会有需要用到队列来传递数据的 ...
- Linux 内核中的 Device Mapper 机制
本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
- Linux内核中双向链表的经典实现
概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...
- Linux内核中的fastcall和asmlinkage宏
代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析
一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...
随机推荐
- python的N个小功能(找到符合要求的图片,重命名,改格式,缩放,进行随机分配)
########################################################################## 循环读取该目录下所有子目录和子文件 ####### ...
- 【bzoj3203】[Sdoi2013]保护出题人 凸包+二分
题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的 ...
- IDEA使用switch传入String编译不通过
今天在使用IDEA的时候,用到switch分支语句,传入String参数的时候一直报错,下面是源码报错截图: 看错误提示并没有提到switch支持String类型,不过ava1.7之后就支持Strin ...
- 【BZOJ1951】古代猪文(CRT,卢卡斯定理)
[BZOJ1951]古代猪文(CRT,卢卡斯定理) 题面 BZOJ 洛谷 题解 要求什么很显然吧... \[Ans=G^{\sum_{k|N}{C_N^k}}\] 给定的模数是一个质数,要求解的东西相 ...
- 【BZOJ1063】【NOI2008】道路设计(动态规划)
[BZOJ1063][NOI2008]道路设计(动态规划) 题面 BZOJ 题解 发现每个点最多只能被修一次等价于每个点最多只能和两条铁路相邻 考虑一个\(dp\) 设\(f[i][0/1/2]\)表 ...
- THUSC2018滚粗记
THUSC2018滚粗记 前言 大家好,我是\(yyb\),我的博客里又多了一篇滚粗记, 我记得我原来在某篇滚粗记中曾经写过 \(yyb\)还会写很多很多次滚粗记才会有一篇不是滚粗记的东西. 看起来这 ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】
题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...
- git使用经验(一)
在使用Git Push代码到数据仓库时,提示如下错误: [remote rejected] master -> master (branch is currently checked out) ...
- 形态学及其他集合运算(Morphological and Other Set Operations)
摘 要:本实验主要实现形态学图像处理.主要验证图像集合的交并补运算.膨胀和腐蚀处理并利用图像集合的运算,实现形态学边界抽取算法并进行特征边界抽取.同时将膨胀和腐蚀扩展至灰度图像,编写函数实现灰度 ...
- centos 前端环境搭建
Node.js 安装 wget 下载安装 yum -y install gcc make gcc-c++ openssl-devel wget node v6.11.0 下载 wget https:/ ...