timer: move doc to README

This commit is contained in:
Ciro Santilli
2018-07-07 19:23:04 +01:00
parent 7d16a5c024
commit f59ca5a214
4 changed files with 39 additions and 29 deletions

View File

@@ -3958,11 +3958,7 @@ Bibliography:
* https://stackoverflow.com/questions/3299386/how-to-use-netlink-socket-to-communicate-with-a-kernel-module * https://stackoverflow.com/questions/3299386/how-to-use-netlink-socket-to-communicate-with-a-kernel-module
* https://en.wikipedia.org/wiki/Netlink * https://en.wikipedia.org/wiki/Netlink
=== Linux kernel asynchronous APIs === kthread
In this section we will document asynchronous APIs of Linux kernel, especially kthread-related scheduled events.
==== kthread
Kernel threads are managed exactly like userland threads; they also have a backing `task_struct`, and are scheduled with the same mechanism: Kernel threads are managed exactly like userland threads; they also have a backing `task_struct`, and are scheduled with the same mechanism:
@@ -4000,7 +3996,7 @@ Bibliography:
* http://stackoverflow.com/questions/10177641/proper-way-of-handling-threads-in-kernel * 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 * http://stackoverflow.com/questions/4084708/how-to-wait-for-a-linux-kernel-thread-kthreadto-exit
===== kthreads ==== kthreads
Let's launch two threads and see if they actually run in parallel: Let's launch two threads and see if they actually run in parallel:
@@ -4034,7 +4030,7 @@ Possible very likely outcome:
The threads almost always interleaved nicely, thus confirming that they are actually running in parallel. The threads almost always interleaved nicely, thus confirming that they are actually running in parallel.
===== sleep ==== sleep
Count to dmesg every one second from `0` up to `n - 1`: Count to dmesg every one second from `0` up to `n - 1`:
@@ -4044,14 +4040,14 @@ insmod /sleep.ko n=5
Source: link:kernel_module/sleep.c[] Source: link:kernel_module/sleep.c[]
The sleep is done with a call to `usleep_range` directly inside `module_init` for simplicity. The sleep is done with a call to link:https://github.com/torvalds/linux/blob/v4.17/kernel/time/timer.c#L1984[`usleep_range`] directly inside `module_init` for simplicity.
Bibliography: Bibliography:
* https://stackoverflow.com/questions/15994603/how-to-sleep-in-the-linux-kernel/44153288#44153288 * https://stackoverflow.com/questions/15994603/how-to-sleep-in-the-linux-kernel/44153288#44153288
* https://github.com/torvalds/linux/blob/v4.17/Documentation/timers/timers-howto.txt * https://github.com/torvalds/linux/blob/v4.17/Documentation/timers/timers-howto.txt
===== Workqueue ==== Workqueues
A more convenient front-end for <<kthread>>: A more convenient front-end for <<kthread>>:
@@ -4089,11 +4085,11 @@ Stop:
rmmod work_from_work rmmod work_from_work
.... ....
The sleep is done indirectly through: `queue_delayed_work`, which waits the specified time before scheduling the work. The sleep is done indirectly through: link:https://github.com/torvalds/linux/blob/v4.17/include/linux/workqueue.h#L522[`queue_delayed_work`], which waits the specified time before scheduling the work.
Source: link:kernel_module/work_from_work.c[] Source: link:kernel_module/work_from_work.c[]
===== schedule ==== schedule
Let's block the entire kernel! Yay: Let's block the entire kernel! Yay:
@@ -4128,6 +4124,31 @@ The system also responds if we <<number-of-cores,add another core>>:
./run -c 2 -F 'dmesg -n 1;insmod /schedule.ko schedule=0' ./run -c 2 -F 'dmesg -n 1;insmod /schedule.ko schedule=0'
.... ....
=== Timers
Count from `0` to `9` infinitely many times in 1 second intervals using timers:
....
insmod /timer.ko
....
Stop counting:
....
rmmod timer
....
Source: link:kernel_module/timer.c[]
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.
Bibliography:
* http://stackoverflow.com/questions/10812858/timers-in-linux-device-drivers
* https://gist.github.com/yagihiro/310149
=== IRQ === IRQ
==== irq.ko ==== irq.ko

View File

@@ -1,4 +1 @@
https://github.com/cirosantilli/linux-kernel-module-cheat#directory-structure https://github.com/cirosantilli/linux-kernel-module-cheat#directory-structure
. Asynchronous
.. link:timer.c[]

View File

@@ -1,22 +1,11 @@
/* /* https://github.com/cirosantilli/linux-kernel-module-cheat#timers */
Print the jiffies every second.
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/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/timer.h> #include <linux/timer.h>
static int i;
/* We would normally mark this as static and give it a more generic name. /* We would normally mark this as static and give it a more generic name.
* But let's do it like this this time for the sake of our GDB kernel module step debugging example. */ * But let's do it like this this time for the sake of our GDB kernel module step debugging example. */
void lkmc_timer_callback(struct timer_list *data); void lkmc_timer_callback(struct timer_list *data);
@@ -26,7 +15,10 @@ DEFINE_TIMER(mytimer, lkmc_timer_callback);
void lkmc_timer_callback(struct timer_list *data) void lkmc_timer_callback(struct timer_list *data)
{ {
pr_info("%u\n", (unsigned)jiffies); pr_info("%d\n", i);
i++;
if (i == 10)
i = 0;
mod_timer(&mytimer, jiffies + onesec); mod_timer(&mytimer, jiffies + onesec);
} }

View File

@@ -1,4 +1,4 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#workqueue */ /* https://github.com/cirosantilli/linux-kernel-module-cheat#workqueues */
#include <linux/delay.h> /* usleep_range */ #include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h> #include <linux/kernel.h>