mirror of https://github.com/tLDP/LDP
43 lines
2.6 KiB
Plaintext
43 lines
2.6 KiB
Plaintext
<sect1><title>Scheduling Tasks</title>
|
|
|
|
<indexterm><primary>scheduling tasks</primary></indexterm>
|
|
<indexterm><primary>tasks</primary><secondary>scheduling</secondary></indexterm>
|
|
<indexterm><primary>housekeeping</primary></indexterm>
|
|
<indexterm><primary>crontab</primary></indexterm>
|
|
|
|
<para>Very often, we have <quote>housekeeping</quote> tasks which have to be done at a certain time, or every so often. If the
|
|
task is to be done by a process, we do it by putting it in the <filename>crontab</filename> file. If the task is to be done
|
|
by a kernel module, we have two possibilities. The first is to put a process in the <filename>crontab</filename> file which
|
|
will wake up the module by a system call when necessary, for example by opening a file. This is terribly inefficient, however
|
|
-- we run a new process off of <filename>crontab</filename>, read a new executable to memory, and all this just to wake up a
|
|
kernel module which is in memory anyway.</para>
|
|
|
|
<indexterm><primary>task</primary></indexterm>
|
|
<indexterm><primary>workqueue_struct</primary></indexterm>
|
|
<indexterm><primary>queue_delayed_work</primary></indexterm>
|
|
|
|
<para>Instead of doing that, we can create a function that will be called once for every timer interrupt. The way we do this
|
|
is we create a task, held in a <structname>workqueue_struct</structname> structure, which will hold a pointer to the function. Then,
|
|
we use <function>queue_delayed_work</function> to put that task on a task list called <structname>my_workqueue</structname>,
|
|
which is the list of tasks to be executed on the next timer interrupt. Because we want the function to keep on being executed,
|
|
we need to put it back on <structname>my_workqueue</structname> whenever it is called, for the next timer interrupt.</para>
|
|
|
|
<indexterm><primary>rmmod</primary></indexterm>
|
|
<indexterm><primary>reference count</primary></indexterm>
|
|
<indexterm><primary>module_cleanup</primary></indexterm>
|
|
|
|
<para>There's one more point we need to remember here. When a module is removed by <command>rmmod</command>, first its
|
|
reference count is checked. If it is zero, <function>module_cleanup</function> is called. Then, the module is removed from
|
|
memory with all its functions. Things need to be shut down properly, or bad things will happen. See the code below how
|
|
this can be done in a safe way. </para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>sched.c</secondary></indexterm>
|
|
|
|
<example><title>sched.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/11-SchedulingTasks/sched.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
</sect1>
|
|
|
|
|
|
<!--
|
|
vim: tw=128
|
|
-->
|