转自: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内核中实现生产者与消费者(避免无效唤醒)【转】的更多相关文章

  1. java多线程中的生产者与消费者之等待唤醒机制@Version1.0

    一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒:    Object类中提供了三个方法:    wait():等待    notify():唤醒单个线程    notify ...

  2. java多线程中的生产者与消费者之等待唤醒机制@Version2.0

    二.生产者消费者模式的学生类成员变量生产与消费demo, @Version2.0 在学生类中添加同步方法:synchronized get()消费者,synchronized set()生产者 最终版 ...

  3. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

  4. Linux内核中的队列 kfifo【转】

    转自:http://airekans.github.io/c/2015/10/12/linux-kernel-data-structure-kfifo#api 在内核中经常会有需要用到队列来传递数据的 ...

  5. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  6. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

  7. Linux内核中双向链表的经典实现

    概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...

  8. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  9. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

随机推荐

  1. BZOJ4953 Wf2017Posterize(动态规划)

    设f[i][j]为前i种强度选了j种且其中第i种选时前i个的最小误差.转移枚举上个选啥前缀和优化即可. #include<iostream> #include<cstdio> ...

  2. 考研路茫茫――单词情结 HDU - 2243(ac自动机 + 矩阵快速幂)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. Ants UVA - 1411(km板题竟然让我换了个板子)

    题意: 给出n个白点和n个黑点的坐标,要求用n条不相交的线段把它们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接到一条线段 解析: 带入负的欧几里得距离求就好了 假设a1-b1 与 ...

  4. Mining Your Own Business UVALive - 5135(点双联通分量)

    these days I‘m tired!,but very happy... #include<cstdio> #include<cstring> #include<s ...

  5. 跟我学Spring Cloud(Finchley版)-20-Spring Cloud Config-Git仓库配置详解 原

    在跟我学Spring Cloud(Finchley版)-19-配置中心-Spring Cloud Config 一节中,已实现使用Git仓库作为Config Server的后端存储,本节详细探讨如何配 ...

  6. Linux学习笔记二:tar命令使用

    tar命令详解 tar命令详解 -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的 ...

  7. Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲

    热浪扭曲效果的实现,分两部分,一是抓图,二是扭曲扰动.其中难点在于抓图的处理,网上的解决方案有两种,在移动平台都有很多问题,只好自己实现了一种新的方案,效果还不错. 网上方案1. 用GrabPass抓 ...

  8. Jenkins远程代码执行漏洞检查(CVE-2017-1000353)

    Jenkins的反序列化漏洞,攻击者使用该漏洞可以在被攻击服务器执行任意代码,漏洞利用不需要任何的权限 漏洞影响范围: 所有Jenkins主版本均受到影响(包括<=2.56版本)所有Jenkin ...

  9. Linux环境编译动态库和静态库总结

    对Linux环境动态库和静态库的一些基础知识做一些总结, 首先总结静态库的编译步骤. 1 先基于.cpp或者.c文件生成对应的.o文件 2将几个.o文件 使用ar -cr命令 生成libname.a文 ...

  10. 10.Android UiAutomator Junit 断言函数的使用

    一.断言函数介绍 1.断言函数: 确定被测试的方法是否按照预期的效果正常工作 比如说: if (假设成立){ 通过测试 }else{ 报错并终止当前用例测试 } 2.断言函数用例结构: 一个完整的测试 ...