博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux内核中实现生产者与消费者(避免无效唤醒)【转】
阅读量:6423 次
发布时间:2019-06-23

本文共 3352 字,大约阅读时间需要 11 分钟。

转自:

本文关注的重点是,避免内核线程的无效唤醒,并且主要是关注消费者线程的设计。

因此,为了省事,这里关与生产者,消费者本身的处理流程可能不够严密。

 

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);

 

版权声明:本文没有任何版权限制,任何人可以以任何方式使用本文。

转载地址:http://wqrra.baihongyu.com/

你可能感兴趣的文章
小游戏:线圈切方块
查看>>
IBinder对象在进程间传递的形式(一)
查看>>
view变化监听器ViewTreeObserver介绍
查看>>
EF5+MVC4系列(8) ActionResult的返回值
查看>>
CALayer: autoresizingMask
查看>>
android获取sd卡路径方法
查看>>
C#最良心脚本语言C#Light/Evil,Xamarin\WP8\Unity热更新最良心方案,再次进化.
查看>>
ERROR 1820 (HY000): You must SET PASSWORD before executing this statement
查看>>
自定义TexturePacker插件导出自己的plist文件
查看>>
[转]关于MYSQL Innodb 锁行还是锁表
查看>>
linux内核设计学习
查看>>
hdu 4771 Stealing Harry Potter's Precious (2013亚洲区杭州现场赛)(搜索 bfs + dfs) 带权值的路径...
查看>>
R12.2.0 buildStage 运行结果
查看>>
[转载]AxureRP 7超强部件库下载
查看>>
用 Jenkins 打包 iOS
查看>>
求一行的和
查看>>
oracle的decode函数在mysql的实现
查看>>
hdu 5593 ZYB's Tree 树形dp
查看>>
c#调用c++开发的dll const char* 返回值接收问题
查看>>
算法入门经典大赛 Dynamic Programming
查看>>