The focus of this article is to avoid invalid wake-up of kernel threads and focus primarily on the design of consumer threads.
Therefore, in order to save trouble, here and the producers, consumers themselves, the processing process may not be rigorous.
1. Producers
A kernel thread that wakes the consumer after each product is produced, and then sleeps for 1 seconds.
2. Consumers
A kernel thread, whenever awakened, consumes goods and then goes to sleep.
There are several benefits to this design for consumer threading: Fast response and no CPU at all.
But one thing to note about this design is to avoid invalid wake-up of threads. How to implement, see the code of the consumer thread to know.
/*
* Kernel Programming test code
*
* Copyright (C) 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 ...) \
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);
Implement producer and consumer in Linux kernel (avoid invalid wakeup)