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

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


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



更多相关文章

  1. Python爬取京东评论(多线程+队列+bs4+pymysql)
  2. 利用读写锁实现sqlite多线程写的问题
  3. 线程往数据库里插数据时偶尔会报错
  4. SQLite3使用总结备忘(多线程/WAL/锁等)
  5. Android之用Handler实现主线程和子线程互相通信以及子线程和子线
  6. 《Android 创建线程源码与OOM分析》
  7. 重新认识Java线程的概念
  8. java线程实现与进程(二)
  9. java多线程jdk1.7与jdk1.6结果不一致的问题

随机推荐

  1. Android中文 API (31) ―― TimePicker
  2. Android 四大核心组件之Activity[生命周
  3. android api Demo之自定义Animation,实现3
  4. 《Android 智能穿戴设备开发-从入门精通
  5. Android(安卓)BroadCast
  6. Android SDK目录结构介绍
  7. Android之android exported="false"作用
  8. android核心模块及相关技术
  9. 安卓开发中Spinner的基本用法(总结)
  10. Android中的日历读写操作!!!