kthread, timer

This commit is contained in:
Ciro Santilli
2017-05-16 09:26:08 +01:00
parent 39d041484d
commit f367ffc6cf
6 changed files with 137 additions and 10 deletions

45
kernel_module/kthread.c Normal file
View File

@@ -0,0 +1,45 @@
/*
Kernel threads are managed exactly like userland threads.
They also have a backing task_struct, and are scheduled with the same mechanism.
See also:
- http://stackoverflow.com/questions/10177641/proper-way-of-handling-threads-in-kernel
- http://stackoverflow.com/questions/4084708/how-to-wait-for-a-linux-kernel-thread-kthreadto-exit
*/
#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static struct task_struct *kthread;
static int work_func(void *data)
{
int i = 0;
while (!kthread_should_stop()) {
printk(KERN_INFO "%d\n", i);
usleep_range(1000000, 1000001);
i++;
if (i == 10)
i = 0;
}
return 0;
}
int init_module(void)
{
kthread = kthread_create(work_func, NULL, "mykthread");
wake_up_process(kthread);
return 0;
}
void cleanup_module(void)
{
/* Waits for thread to return. */
kthread_stop(kthread);
}

View File

@@ -9,7 +9,7 @@ dmesg prints an integer every second until rmmod.
Since insmod returns, this also illustrates how the work queues are asynchronous.
*/
#include <linux/delay.h>
#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h> /* atomic_t */
@@ -32,10 +32,9 @@ static void work_func(struct work_struct *work)
}
}
DECLARE_WORK(work, work_func);
int init_module(void)
{
DECLARE_WORK(work, work_func);
queue = create_workqueue("myworkqueue");
queue_work(queue, &work);
return 0;

41
kernel_module/timer.c Normal file
View File

@@ -0,0 +1,41 @@
/*
Timers are callbacks that run when an interrupt happens, from the interrupt context itself.
Therefore they produce more accurate timing than thread scheduling, which is more complex,
but you can't do too much work inside of them.
See also:
- http://stackoverflow.com/questions/10812858/timers-in-linux-device-drivers
- https://gist.github.com/yagihiro/310149
*/
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
MODULE_LICENSE("GPL");
static void callback(unsigned long data);
static unsigned long onesec;
DEFINE_TIMER(mytimer, callback, 0, 0);
static void callback(unsigned long data)
{
pr_info("%u\n", (unsigned)jiffies);
mod_timer(&mytimer, jiffies + onesec);
}
int init_module(void)
{
onesec = msecs_to_jiffies(1000);
mod_timer(&mytimer, jiffies + onesec);
return 0;
}
void cleanup_module(void)
{
del_timer(&mytimer);
}

View File

@@ -0,0 +1,35 @@
/*
Declare more work from a workqueue.
TODO: kernel panic. Why?
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
MODULE_LICENSE("GPL");
static int i = 0;
static struct workqueue_struct *queue;
static void work_func(struct work_struct *work)
{
DECLARE_DELAYED_WORK(next_work, work_func);
printk(KERN_INFO "%d\n", i);
i++;
queue_delayed_work(queue, &next_work, HZ);
}
int init_module(void)
{
DECLARE_WORK(work, work_func);
queue = create_workqueue("myworkqueue");
queue_work(queue, &work);
return 0;
}
void cleanup_module(void)
{
destroy_workqueue(queue);
}

View File

@@ -10,6 +10,8 @@ Creates a separate thread. So init_module can return, but some work will still g
Can't call this just workqueue.c because there is already a built-in with that name:
https://unix.stackexchange.com/questions/364956/how-can-insmod-fail-with-kernel-module-is-already-loaded-even-is-lsmod-does-not
Workqueues are a convenience frontend for kthreads.
Bibliography:
- https://www.ibm.com/developerworks/library/l-tasklets/