天天看點

Linux核心中實作生産者與消費者(避免無效喚醒)【轉】

本文關注的重點是,避免核心線程的無效喚醒,并且主要是關注消費者線程的設計。

是以,為了省事,這裡關與生産者,消費者本身的處理流程可能不夠嚴密。

1. 生産者

一個核心線程,每生産一個商品後,就喚醒消費者,然後自己睡眠1秒鐘。

2. 消費者

一個核心線程,每當被喚醒後,就消費商品,然後進入睡眠。

對于消費者線程的這種設計,有幾個好處:響應快,平時不占任何cpu。

但這種設計有一點要注意,那就是要避免線程的無效喚醒。如何實作,看看消費者線程的代碼就知道了。

/*

 * kernel programming test code

 *

 * Copyright (C) 2014 Sun Mingbao <[email protected]>

 * 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 <[email protected]>");

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...) \

        WRITE_CONSOLE(MODULE_NAME"_DBG:%s(%d)-%s:\n"fmt"\n", __FILE__,__LINE__,__FUNCTION__,##args); \

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

            set_current_state(TASK_RUNNING);

            continue;

        schedule();

    }

    if (has_something_to_consume)

        consume();

static int producer_thread_func(void * data)

        produce();

        if (consumer_thread->state & TASK_INTERRUPTIBLE)

            wake_up_process(consumer_thread);

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

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

版權聲明:本文沒有任何版權限制,任何人可以以任何方式使用本文。

繼續閱讀