zoukankan      html  css  js  c++  java
  • 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: "fmt" ", __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 ""cnt_consumer:%u ", 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);


    版权声明:本文没有任何版权限制,任何人可以以任何方式使用本文。
  • 相关阅读:
    Dell FC Switch zone configuration
    RMAN参考使用手册[转载]
    CentOS下SVN简介、下载、安装
    教你制作启动U盘 用U盘装系统(转载)
    RMAN简明使用手册[转载]
    控制文件和重做日志文件(1)[转载)
    RMAN快速入门指南[转载]
    Dell服务转移
    BE Learing 8 异常及解决办法
    10g rman备份恢复案例[转载]
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/8193770.html
Copyright © 2011-2022 走看看