mirror of
https://github.com/sysprog21/lkmpg.git
synced 2025-04-22 20:53:23 +08:00
deploy: 678757e19c2e664bf15d8145ef785c1e899401d0
This commit is contained in:
parent
2a1bb161c5
commit
2b4fa35c5a
238
index.html
238
index.html
@ -17,7 +17,7 @@
|
||||
|
||||
<h2 class='titleHead'>The Linux Kernel Module Programming Guide</h2>
|
||||
<div class='author'><span class='ecrm-1200'>Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang</span></div><br />
|
||||
<div class='date'><span class='ecrm-1200'>August 6, 2021</span></div>
|
||||
<div class='date'><span class='ecrm-1200'>August 7, 2021</span></div>
|
||||
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ have contributed new material to this book, you must make the material and sourc
|
||||
|
||||
|
||||
code available for your revisions. Please make revisions and updates available directly
|
||||
to the document maintainer, Peter Jay Salzman <p@dirac.org>. This will allow
|
||||
to the document maintainer, Jim Huang <jserv@ccns.ncku.edu.tw>. This will allow
|
||||
for the merging of updates and provide consistent revisions to the Linux
|
||||
community.
|
||||
</p><!-- l. 63 --><p class='indent'> If you publish or distribute this book commercially, donations, royalties, and/or
|
||||
@ -3133,65 +3133,67 @@ patch.
|
||||
<!-- l. 1230 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='sleep'><span class='titlemark'>0.11.1 </span> <a id='x1-430000.11.1'></a>Sleep</h4>
|
||||
<!-- l. 1232 --><p class='noindent'>What do you do when somebody asks you for something you can’t do right away? If
|
||||
you’re a human being and you’re bothered by a human being, the only thing you can
|
||||
say is: "<span class='ecti-1000'>Not right now, I’m busy. Go away!</span>". But if you’re a kernel module and
|
||||
you’re bothered by a process, you have another possibility. You can put the process
|
||||
to sleep until you can service it. After all, processes are being put to sleep by the
|
||||
kernel and woken up all the time (that’s the way multiple processes appear to run on
|
||||
the same time on a single CPU).
|
||||
</p><!-- l. 1234 --><p class='indent'> This kernel module is an example of this. The file (called <span class='ecbx-1000'>/proc/sleep</span>) can only
|
||||
<!-- l. 1232 --><p class='noindent'>What do you do when somebody asks you for something you can not do right
|
||||
away? If you are a human being and you are bothered by a human being, the
|
||||
only thing you can say is: "<span class='ecti-1000'>Not right now, I’m busy. Go away!</span>". But if you
|
||||
are a kernel module and you are bothered by a process, you have another
|
||||
possibility. You can put the process to sleep until you can service it. After all,
|
||||
processes are being put to sleep by the kernel and woken up all the time (that
|
||||
is the way multiple processes appear to run on the same time on a single
|
||||
CPU).
|
||||
</p><!-- l. 1238 --><p class='indent'> This kernel module is an example of this. The file (called <span class='ecbx-1000'>/proc/sleep</span>) can only
|
||||
be opened by a single process at a time. If the file is already open, the kernel module
|
||||
calls wait_event_interruptible. The easiest way to keep a file open is to open it
|
||||
calls <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>wait_event_interruptible</span></span></span>. The easiest way to keep a file open is to open it
|
||||
with:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb52'><a id='x1-43003r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>tail -f</span></pre>
|
||||
<!-- l. 1240 --><p class='indent'> This function changes the status of the task (a task is the kernel data
|
||||
structure which holds information about a process and the system call it’s in, if
|
||||
<!-- l. 1247 --><p class='indent'> This function changes the status of the task (a task is the kernel data
|
||||
structure which holds information about a process and the system call it is in, if
|
||||
any) to <span class='ecbx-1000'>TASK_INTERRUPTIBLE</span>, which means that the task will
|
||||
not run until it is woken up somehow, and adds it to WaitQ, the queue
|
||||
of tasks waiting to access the file. Then, the function calls the scheduler
|
||||
to context switch to a different process, one which has some use for the
|
||||
CPU.
|
||||
</p><!-- l. 1242 --><p class='indent'> When a process is done with the file, it closes it, and module_close is called. That
|
||||
function wakes up all the processes in the queue (there’s no mechanism
|
||||
</p><!-- l. 1251 --><p class='indent'> When a process is done with the file, it closes it, and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>module_close</span></span></span> is called.
|
||||
That function wakes up all the processes in the queue (there’s no mechanism
|
||||
to only wake up one of them). It then returns and the process which just
|
||||
closed the file can continue to run. In time, the scheduler decides that that
|
||||
process has had enough and gives control of the CPU to another process.
|
||||
Eventually, one of the processes which was in the queue will be given control
|
||||
of the CPU by the scheduler. It starts at the point right after the call to
|
||||
<span class='ecbx-1000'>module_interruptible_sleep_on</span>.
|
||||
</p><!-- l. 1244 --><p class='indent'> This means that the process is still in kernel mode - as far as the process is
|
||||
concerned, it issued the open system call and the system call hasn’t returned yet.
|
||||
The process doesn’t know somebody else used the CPU for most of the time between
|
||||
the moment it issued the call and the moment it returned.
|
||||
</p><!-- l. 1246 --><p class='indent'> It can then proceed to set a global variable to tell all the other processes that the
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>module_interruptible_sleep_on</span></span></span>.
|
||||
</p><!-- l. 1258 --><p class='indent'> This means that the process is still in kernel mode - as far as the process
|
||||
is concerned, it issued the open system call and the system call has not
|
||||
returned yet. The process does not know somebody else used the CPU for
|
||||
most of the time between the moment it issued the call and the moment it
|
||||
returned.
|
||||
</p><!-- l. 1261 --><p class='indent'> It can then proceed to set a global variable to tell all the other processes that the
|
||||
file is still open and go on with its life. When the other processes get a piece of the
|
||||
CPU, they’ll see that global variable and go back to sleep.
|
||||
</p><!-- l. 1248 --><p class='indent'> So we’ll use tail -f to keep the file open in the background, while trying to
|
||||
</p><!-- l. 1264 --><p class='indent'> So we will use <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>tail -f</span></span></span> to keep the file open in the background, while trying to
|
||||
access it with another process (again in the background, so that we need not
|
||||
switch to a different vt). As soon as the first background process is killed
|
||||
with kill %1 , the second is woken up, is able to access the file and finally
|
||||
terminates.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1250 --><p class='indent'> To make our life more interesting, <span class='ecbx-1000'>module_close </span>doesn’t have a monopoly
|
||||
with kill %1 , the second is woken up, is able to access the file and finally
|
||||
terminates.
|
||||
</p><!-- l. 1267 --><p class='indent'> To make our life more interesting, <span class='ecbx-1000'>module_close </span>does not have a monopoly
|
||||
on waking up the processes which wait to access the file. A signal, such as
|
||||
<span class='ecti-1000'>Ctrl +c </span>(<span class='ecbx-1000'>SIGINT</span>) can also wake up a process. This is because we used
|
||||
<span class='ecbx-1000'>module_interruptible_sleep_on</span>. We could have used <span class='ecbx-1000'>module_sleep_on</span>
|
||||
instead, but that would have resulted in extremely angry users whose <span class='ecti-1000'>Ctrl+c</span>’s are
|
||||
ignored.
|
||||
</p><!-- l. 1252 --><p class='indent'> In that case, we want to return with <span class='ecbx-1000'>-EINTR </span>immediately. This is important so
|
||||
</p><!-- l. 1271 --><p class='indent'> In that case, we want to return with <span class='ecbx-1000'>-EINTR </span>immediately. This is important so
|
||||
users can, for example, kill the process before it receives the file.
|
||||
</p><!-- l. 1254 --><p class='indent'> There is one more point to remember. Some times processes don’t want to sleep,
|
||||
</p><!-- l. 1273 --><p class='indent'> There is one more point to remember. Some times processes don’t want to sleep,
|
||||
they want either to get what they want immediately, or to be told it cannot be done.
|
||||
Such processes use the <span class='ecbx-1000'>O_NONBLOCK </span>flag when opening the file. The kernel is
|
||||
supposed to respond by returning with the error code <span class='ecbx-1000'>-EAGAIN </span>from operations
|
||||
which would otherwise block, such as opening the file in this example. The program
|
||||
cat_noblock, available in the source directory for this chapter, can be used to open a
|
||||
file with <span class='ecbx-1000'>O_NONBLOCK</span>.
|
||||
Such processes use the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>O_NONBLOCK</span></span></span> flag when opening the file. The kernel is supposed
|
||||
to respond by returning with the error code <span class='ecbx-1000'>-EAGAIN </span>from operations which
|
||||
would otherwise block, such as opening the file in this example. The program
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>cat_nonblock</span></span></span>, available in the <span class='ecti-1000'>examples/other </span>directory for this chapter, can be
|
||||
used to open a file with <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>O_NONBLOCK</span></span></span>.
|
||||
|
||||
|
||||
|
||||
@ -3218,7 +3220,7 @@ $ cat_nonblock /proc/sleep
|
||||
Last input:
|
||||
$
|
||||
</pre>
|
||||
<!-- l. 1277 --><p class='nopar'>
|
||||
<!-- l. 1298 --><p class='nopar'>
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb53'><a id='x1-43005r1'></a><span class='ecrm-0500'>1</span><span id='textcolor1628'><span class='ectt-0800'>/*</span></span>
|
||||
@ -3563,13 +3565,13 @@ $
|
||||
<a id='x1-43677r57'></a><span class='ecrm-0500'>57</span>
|
||||
<a id='x1-43679r58'></a><span class='ecrm-0500'>58</span><span class='ectt-0800'> </span><span id='textcolor1921'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0;</span>
|
||||
<a id='x1-43681r59'></a><span class='ecrm-0500'>59</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 1283 --><p class='noindent'>
|
||||
<!-- l. 1304 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='completions'><span class='titlemark'>0.11.2 </span> <a id='x1-440000.11.2'></a>Completions</h4>
|
||||
<!-- l. 1285 --><p class='noindent'>Sometimes one thing should happen before another within a module having multiple
|
||||
threads. Rather than using <span class='ecbx-1000'>/proc/sleep </span>commands the kernel has another way to
|
||||
do this which allows timeouts or interrupts to also happen.
|
||||
</p><!-- l. 1287 --><p class='indent'> In the following example two threads are started, but one needs to start before
|
||||
<!-- l. 1306 --><p class='noindent'>Sometimes one thing should happen before another within a module having multiple
|
||||
threads. Rather than using <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/bin/sleep</span></span></span> commands, the kernel has another way to do
|
||||
this which allows timeouts or interrupts to also happen.
|
||||
</p><!-- l. 1309 --><p class='indent'> In the following example two threads are started, but one needs to start before
|
||||
another.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -3652,27 +3654,27 @@ another.
|
||||
<a id='x1-44148r74'></a><span class='ecrm-0500'>74</span>
|
||||
<a id='x1-44150r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor1972'><span class='ectt-0800'>"Completions example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-44152r76'></a><span class='ecrm-0500'>76</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor1973'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1291 --><p class='indent'> The <span class='ecti-1000'>machine </span>structure stores the completion states for the two threads. At the
|
||||
<!-- l. 1313 --><p class='indent'> The <span class='ecti-1000'>machine </span>structure stores the completion states for the two threads. At the
|
||||
exit point of each thread the respective completion state is updated, and
|
||||
<span class='ecti-1000'>wait_for_completion </span>is used by the flywheel thread to ensure that it doesn’t begin
|
||||
prematurely.
|
||||
</p><!-- l. 1293 --><p class='indent'> So even though <span class='ecti-1000'>flywheel_thread </span>is started first you should notice if you load this
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>{wait_for_completion</span></span></span> is used by the flywheel thread to ensure that it does not
|
||||
begin prematurely.
|
||||
</p><!-- l. 1316 --><p class='indent'> So even though <span class='ecti-1000'>flywheel_thread </span>is started first you should notice if you load this
|
||||
module and run <span class='ecti-1000'>dmesg </span>that turning the crank always happens first because the
|
||||
flywheel thread waits for it to complete.
|
||||
</p><!-- l. 1295 --><p class='indent'> There are other variations upon the <span class='ecti-1000'>wait_for_completion </span>function, which include
|
||||
timeouts or being interrupted, but this basic mechanism is enough for many common
|
||||
situations without adding a lot of complexity.
|
||||
</p><!-- l. 1297 --><p class='noindent'>
|
||||
</p><!-- l. 1318 --><p class='indent'> There are other variations upon the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>wait_for_completion</span></span></span> function, which
|
||||
include timeouts or being interrupted, but this basic mechanism is enough for many
|
||||
common situations without adding a lot of complexity.
|
||||
</p><!-- l. 1320 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='avoiding-collisions-and-deadlocks'><span class='titlemark'>0.12 </span> <a id='x1-450000.12'></a>Avoiding Collisions and Deadlocks</h3>
|
||||
<!-- l. 1299 --><p class='noindent'>If processes running on different CPUs or in different threads try to access the same
|
||||
<!-- l. 1322 --><p class='noindent'>If processes running on different CPUs or in different threads try to access the same
|
||||
memory then it’s possible that strange things can happen or your system can lock
|
||||
up. To avoid this various types of mutual exclusion kernel functions are available.
|
||||
These indicate if a section of code is "locked" or "unlocked" so that simultaneous
|
||||
attempts to run it can’t happen.
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='mutex'><span class='titlemark'>0.12.1 </span> <a id='x1-460000.12.1'></a>Mutex</h4>
|
||||
<!-- l. 1302 --><p class='noindent'>You can use kernel mutexes (mutual exclusions) in much the same manner that you
|
||||
<!-- l. 1325 --><p class='noindent'>You can use kernel mutexes (mutual exclusions) in much the same manner that you
|
||||
might deploy them in userland. This may be all that’s needed to avoid collisions in
|
||||
most cases.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -3718,10 +3720,10 @@ most cases.
|
||||
<a id='x1-46078r39'></a><span class='ecrm-0500'>39</span>
|
||||
<a id='x1-46080r40'></a><span class='ecrm-0500'>40</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2014'><span class='ectt-0800'>"Mutex example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-46082r41'></a><span class='ecrm-0500'>41</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2015'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1306 --><p class='noindent'>
|
||||
<!-- l. 1329 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='spinlocks'><span class='titlemark'>0.12.2 </span> <a id='x1-470000.12.2'></a>Spinlocks</h4>
|
||||
<!-- l. 1308 --><p class='noindent'>As the name suggests, spinlocks lock up the CPU that the code is running on,
|
||||
<!-- l. 1331 --><p class='noindent'>As the name suggests, spinlocks lock up the CPU that the code is running on,
|
||||
taking 100% of its resources. Because of this you should only use the spinlock
|
||||
mechanism around code which is likely to take no more than a few milliseconds to
|
||||
run and so won’t noticably slow anything down from the user’s point of
|
||||
@ -3729,7 +3731,7 @@ view.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1310 --><p class='indent'> The example here is <span class='ecti-1000'>"irq safe" </span>in that if interrupts happen during the lock then
|
||||
</p><!-- l. 1333 --><p class='indent'> The example here is <span class='ecti-1000'>"irq safe" </span>in that if interrupts happen during the lock then
|
||||
they won’t be forgotten and will activate when the unlock happens, using the <span class='ecti-1000'>flags</span>
|
||||
variable to retain their state.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -3799,10 +3801,10 @@ variable to retain their state.
|
||||
<a id='x1-47126r63'></a><span class='ecrm-0500'>63</span>
|
||||
<a id='x1-47128r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2072'><span class='ectt-0800'>"Spinlock example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-47130r65'></a><span class='ecrm-0500'>65</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2073'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1314 --><p class='noindent'>
|
||||
<!-- l. 1337 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='read-and-write-locks'><span class='titlemark'>0.12.3 </span> <a id='x1-480000.12.3'></a>Read and write locks</h4>
|
||||
<!-- l. 1316 --><p class='noindent'>Read and write locks are specialised kinds of spinlocks so that you can exclusively
|
||||
<!-- l. 1339 --><p class='noindent'>Read and write locks are specialised kinds of spinlocks so that you can exclusively
|
||||
read from something or write to something. Like the earlier spinlocks example the
|
||||
one below shows an "irq safe" situation in which if other functions were triggered
|
||||
from irqs which might also read and write to whatever you are concerned
|
||||
@ -3867,13 +3869,13 @@ module.
|
||||
<a id='x1-48106r53'></a><span class='ecrm-0500'>53</span>
|
||||
<a id='x1-48108r54'></a><span class='ecrm-0500'>54</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2120'><span class='ectt-0800'>"Read/Write locks example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-48110r55'></a><span class='ecrm-0500'>55</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2121'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1320 --><p class='indent'> Of course if you know for sure that there are no functions triggered by irqs
|
||||
<!-- l. 1343 --><p class='indent'> Of course if you know for sure that there are no functions triggered by irqs
|
||||
which could possibly interfere with your logic then you can use the simpler
|
||||
<span class='ecti-1000'>read_lock(&myrwlock) </span>and <span class='ecti-1000'>read_unlock(&myrwlock) </span>or the corresponding write
|
||||
functions.
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='atomic-operations'><span class='titlemark'>0.12.4 </span> <a id='x1-490000.12.4'></a>Atomic operations</h4>
|
||||
<!-- l. 1323 --><p class='noindent'>If you’re doing simple arithmetic: adding, subtracting or bitwise operations then
|
||||
<!-- l. 1346 --><p class='noindent'>If you’re doing simple arithmetic: adding, subtracting or bitwise operations then
|
||||
there’s another way in the multi-CPU and multi-hyperthreaded world to stop other
|
||||
parts of the system from messing with your mojo. By using atomic operations you
|
||||
can be confident that your addition, subtraction or bit flip did actually happen
|
||||
@ -3958,21 +3960,21 @@ below.
|
||||
|
||||
|
||||
|
||||
<!-- l. 1327 --><p class='noindent'>
|
||||
<!-- l. 1350 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='replacing-print-macros'><span class='titlemark'>0.13 </span> <a id='x1-500000.13'></a>Replacing Print Macros</h3>
|
||||
<!-- l. 1329 --><p class='noindent'>
|
||||
<!-- l. 1352 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='replacement'><span class='titlemark'>0.13.1 </span> <a id='x1-510000.13.1'></a>Replacement</h4>
|
||||
<!-- l. 1331 --><p class='noindent'>In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s
|
||||
<!-- l. 1354 --><p class='noindent'>In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s
|
||||
true for developing kernel modules, but in actual use, you want to be able
|
||||
to send messages to whichever tty the command to load the module came
|
||||
from.
|
||||
</p><!-- l. 1333 --><p class='indent'> "tty" is an abbreviation of <span class='ecti-1000'>teletype</span>: originally a combination keyboard-printer
|
||||
</p><!-- l. 1356 --><p class='indent'> "tty" is an abbreviation of <span class='ecti-1000'>teletype</span>: originally a combination keyboard-printer
|
||||
used to communicate with a Unix system, and today an abstraction for the text
|
||||
stream used for a Unix program, whether it’s a physical terminal, an xterm on an X
|
||||
display, a network connection used with ssh, etc.
|
||||
</p><!-- l. 1335 --><p class='indent'> The way this is done is by using current, a pointer to the currently running task,
|
||||
</p><!-- l. 1358 --><p class='indent'> The way this is done is by using current, a pointer to the currently running task,
|
||||
to get the current task’s tty structure. Then, we look inside that tty structure to find
|
||||
a pointer to a string write function, which we use to write a string to the
|
||||
tty.
|
||||
@ -4061,16 +4063,16 @@ tty.
|
||||
<a id='x1-51162r81'></a><span class='ecrm-0500'>81</span>
|
||||
<a id='x1-51164r82'></a><span class='ecrm-0500'>82</span><span class='ectt-0800'>module_init(print_string_init);</span>
|
||||
<a id='x1-51166r83'></a><span class='ecrm-0500'>83</span><span class='ectt-0800'>module_exit(print_string_exit);</span></pre>
|
||||
<!-- l. 1339 --><p class='noindent'>
|
||||
<!-- l. 1362 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='flashing-keyboard-leds'><span class='titlemark'>0.13.2 </span> <a id='x1-520000.13.2'></a>Flashing keyboard LEDs</h4>
|
||||
<!-- l. 1341 --><p class='noindent'>In certain conditions, you may desire a simpler and more direct way to communicate
|
||||
<!-- l. 1364 --><p class='noindent'>In certain conditions, you may desire a simpler and more direct way to communicate
|
||||
to the external world. Flashing keyboard LEDs can be such a solution: It is an
|
||||
immediate way to attract attention or to display a status condition. Keyboard LEDs
|
||||
are present on every hardware, they are always visible, they do not need any setup,
|
||||
and their use is rather simple and non-intrusive, compared to writing to a tty or a
|
||||
file.
|
||||
</p><!-- l. 1343 --><p class='indent'> The following source code illustrates a minimal kernel module which, when
|
||||
</p><!-- l. 1366 --><p class='indent'> The following source code illustrates a minimal kernel module which, when
|
||||
loaded, starts blinking the keyboard LEDs until it is unloaded.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4167,7 +4169,7 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
|
||||
<a id='x1-52182r91'></a><span class='ecrm-0500'>91</span>
|
||||
<a id='x1-52184r92'></a><span class='ecrm-0500'>92</span><span class='ectt-0800'>module_init(kbleds_init);</span>
|
||||
<a id='x1-52186r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>module_exit(kbleds_cleanup);</span></pre>
|
||||
<!-- l. 1347 --><p class='indent'> If none of the examples in this chapter fit your debugging needs there might yet
|
||||
<!-- l. 1370 --><p class='indent'> If none of the examples in this chapter fit your debugging needs there might yet
|
||||
be some other tricks to try. Ever wondered what CONFIG_LL_DEBUG in
|
||||
make menuconfig is good for? If you activate that you get low level access
|
||||
to the serial port. While this might not sound very powerful by itself, you
|
||||
@ -4180,22 +4182,22 @@ over a serial line. If you find yourself porting the kernel to some new and
|
||||
former unsupported architecture this is usually amongst the first things that
|
||||
should be implemented. Logging over a netconsole might also be worth a
|
||||
try.
|
||||
</p><!-- l. 1349 --><p class='indent'> While you have seen lots of stuff that can be used to aid debugging here, there are
|
||||
</p><!-- l. 1372 --><p class='indent'> While you have seen lots of stuff that can be used to aid debugging here, there are
|
||||
some things to be aware of. Debugging is almost always intrusive. Adding debug code
|
||||
can change the situation enough to make the bug seem to dissappear. Thus you
|
||||
should try to keep debug code to a minimum and make sure it does not show up in
|
||||
production code.
|
||||
</p><!-- l. 1351 --><p class='noindent'>
|
||||
</p><!-- l. 1374 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='scheduling-tasks'><span class='titlemark'>0.14 </span> <a id='x1-530000.14'></a>Scheduling Tasks</h3>
|
||||
<!-- l. 1353 --><p class='noindent'>There are two main ways of running tasks: tasklets and work queues. Tasklets are a
|
||||
<!-- l. 1376 --><p class='noindent'>There are two main ways of running tasks: tasklets and work queues. Tasklets are a
|
||||
quick and easy way of scheduling a single function to be run, for example when
|
||||
triggered from an interrupt, whereas work queues are more complicated but also
|
||||
better suited to running multiple things in a sequence.
|
||||
</p><!-- l. 1355 --><p class='noindent'>
|
||||
</p><!-- l. 1378 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='tasklets'><span class='titlemark'>0.14.1 </span> <a id='x1-540000.14.1'></a>Tasklets</h4>
|
||||
<!-- l. 1357 --><p class='noindent'>Here’s an example tasklet module. The <span class='ecti-1000'>tasklet_fn </span>function runs for a few seconds
|
||||
<!-- l. 1380 --><p class='noindent'>Here’s an example tasklet module. The <span class='ecti-1000'>tasklet_fn </span>function runs for a few seconds
|
||||
and in the mean time execution of the <span class='ecti-1000'>example_tasklet_init </span>function continues to
|
||||
the exit point.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -4237,7 +4239,7 @@ the exit point.
|
||||
<a id='x1-54070r35'></a><span class='ecrm-0500'>35</span>
|
||||
<a id='x1-54072r36'></a><span class='ecrm-0500'>36</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2377'><span class='ectt-0800'>"Tasklet example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-54074r37'></a><span class='ecrm-0500'>37</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2378'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1361 --><p class='indent'> So with this example loaded <span class='ecti-1000'>dmesg </span>should show:
|
||||
<!-- l. 1384 --><p class='indent'> So with this example loaded <span class='ecti-1000'>dmesg </span>should show:
|
||||
|
||||
|
||||
|
||||
@ -4248,11 +4250,11 @@ Example tasklet starts
|
||||
Example tasklet init continues...
|
||||
Example tasklet ends
|
||||
</pre>
|
||||
<!-- l. 1368 --><p class='nopar'>
|
||||
</p><!-- l. 1370 --><p class='noindent'>
|
||||
<!-- l. 1391 --><p class='nopar'>
|
||||
</p><!-- l. 1393 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='work-queues'><span class='titlemark'>0.14.2 </span> <a id='x1-550000.14.2'></a>Work queues</h4>
|
||||
<!-- l. 1372 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
<!-- l. 1395 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4287,18 +4289,18 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
<a id='x1-55058r29'></a><span class='ecrm-0500'>29</span>
|
||||
<a id='x1-55060r30'></a><span class='ecrm-0500'>30</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2402'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-55062r31'></a><span class='ecrm-0500'>31</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2403'><span class='ectt-0800'>"Workqueue example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1376 --><p class='noindent'>
|
||||
<!-- l. 1399 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='interrupt-handlers'><span class='titlemark'>0.15 </span> <a id='x1-560000.15'></a>Interrupt Handlers</h3>
|
||||
<!-- l. 1378 --><p class='noindent'>
|
||||
<!-- l. 1401 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='interrupt-handlers1'><span class='titlemark'>0.15.1 </span> <a id='x1-570000.15.1'></a>Interrupt Handlers</h4>
|
||||
<!-- l. 1380 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we’ve done as a
|
||||
<!-- l. 1403 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we’ve done as a
|
||||
response to a process asking for it, either by dealing with a special file, sending an
|
||||
ioctl(), or issuing a system call. But the job of the kernel isn’t just to respond to
|
||||
process requests. Another job, which is every bit as important, is to speak to the
|
||||
hardware connected to the machine.
|
||||
</p><!-- l. 1382 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
</p><!-- l. 1405 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
computer’s hardware. The first type is when the CPU gives orders to the hardware,
|
||||
the other is when the hardware needs to tell the CPU something. The second, called
|
||||
interrupts, is much harder to implement because it has to be dealt with when
|
||||
@ -4308,14 +4310,14 @@ lost.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1384 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
</p><!-- l. 1407 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
are two types of IRQ’s, short and long. A short IRQ is one which is expected to take
|
||||
a very short period of time, during which the rest of the machine will be blocked and
|
||||
no other interrupts will be handled. A long IRQ is one which can take longer, and
|
||||
during which other interrupts may occur (but not interrupts from the same
|
||||
device). If at all possible, it’s better to declare an interrupt handler to be
|
||||
long.
|
||||
</p><!-- l. 1386 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s
|
||||
</p><!-- l. 1409 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s
|
||||
processing a more important interrupt, in which case it will deal with this one
|
||||
only when the more important one is done), saves certain parameters on
|
||||
the stack and calls the interrupt handler. This means that certain things
|
||||
@ -4327,9 +4329,9 @@ the new information at a later time (this is called the "bottom half") and
|
||||
return. The kernel is then guaranteed to call the bottom half as soon as
|
||||
possible – and when it does, everything allowed in kernel modules will be
|
||||
allowed.
|
||||
</p><!-- l. 1388 --><p class='indent'> The way to implement this is to call <span class='ecbx-1000'>request_irq() </span>to get your interrupt handler
|
||||
</p><!-- l. 1411 --><p class='indent'> The way to implement this is to call <span class='ecbx-1000'>request_irq() </span>to get your interrupt handler
|
||||
called when the relevant IRQ is received.
|
||||
</p><!-- l. 1390 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
</p><!-- l. 1413 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
designed in a way that chains two interrupt controllers, so that all the IRQs
|
||||
from interrupt controller B are cascaded to a certain IRQ from interrupt
|
||||
controller A. Of course that requires that the kernel finds out which IRQ it
|
||||
@ -4343,7 +4345,7 @@ another truckload of problems. It’s not enough to know if a certain IRQs
|
||||
has happend, it’s also important for what CPU(s) it was for. People still
|
||||
interested in more details, might want to do a web search for "APIC" now
|
||||
;)
|
||||
</p><!-- l. 1392 --><p class='indent'> This function receives the IRQ number, the name of the function, flags, a name
|
||||
</p><!-- l. 1415 --><p class='indent'> This function receives the IRQ number, the name of the function, flags, a name
|
||||
for /proc/interrupts and a parameter to pass to the interrupt handler. Usually
|
||||
there is a certain number of IRQs available. How many IRQs there are is
|
||||
hardware-dependent. The flags can include SA_SHIRQ to indicate you’re willing to
|
||||
@ -4354,16 +4356,16 @@ or if you’re both willing to share.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1394 --><p class='noindent'>
|
||||
</p><!-- l. 1417 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='detecting-button-presses'><span class='titlemark'>0.15.2 </span> <a id='x1-580000.15.2'></a>Detecting button presses</h4>
|
||||
<!-- l. 1396 --><p class='noindent'>Many popular single board computers, such as Raspberry Pis or Beagleboards, have
|
||||
<!-- l. 1419 --><p class='noindent'>Many popular single board computers, such as Raspberry Pis or Beagleboards, have
|
||||
a bunch of GPIO pins. Attaching buttons to those and then having a button press do
|
||||
something is a classic case in which you might need to use interrupts so that instead
|
||||
of having the CPU waste time and battery power polling for a change in input state
|
||||
it’s better for the input to trigger the CPU to then run a particular handling
|
||||
function.
|
||||
</p><!-- l. 1398 --><p class='indent'> Here’s an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
</p><!-- l. 1421 --><p class='indent'> Here’s an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
an LED is connected to GPIO 4. You can change those numbers to whatever is
|
||||
appropriate for your board.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -4510,14 +4512,14 @@ appropriate for your board.
|
||||
<a id='x1-58280r140'></a><span class='ecrm-0500'>140</span>
|
||||
<a id='x1-58282r141'></a><span class='ecrm-0500'>141</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2506'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-58284r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2507'><span class='ectt-0800'>"Handle some GPIO interrupts"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1402 --><p class='noindent'>
|
||||
<!-- l. 1425 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='bottom-half'><span class='titlemark'>0.15.3 </span> <a id='x1-590000.15.3'></a>Bottom Half</h4>
|
||||
<!-- l. 1404 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
<!-- l. 1427 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
way to do that without rendering the interrupt unavailable for a significant duration
|
||||
is to combine it with a tasklet. This pushes the bulk of the work off into the
|
||||
scheduler.
|
||||
</p><!-- l. 1406 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
</p><!-- l. 1429 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
when an interrupt is triggered.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4677,10 +4679,10 @@ when an interrupt is triggered.
|
||||
<a id='x1-59308r154'></a><span class='ecrm-0500'>154</span>
|
||||
<a id='x1-59310r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2624'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-59312r156'></a><span class='ecrm-0500'>156</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2625'><span class='ectt-0800'>"Interrupt with top and bottom half"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1410 --><p class='noindent'>
|
||||
<!-- l. 1433 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='crypto'><span class='titlemark'>0.16 </span> <a id='x1-600000.16'></a>Crypto</h3>
|
||||
<!-- l. 1412 --><p class='noindent'>At the dawn of the internet everybody trusted everybody completely…but that didn’t
|
||||
<!-- l. 1435 --><p class='noindent'>At the dawn of the internet everybody trusted everybody completely…but that didn’t
|
||||
work out so well. When this guide was originally written it was a more innocent era
|
||||
in which almost nobody actually gave a damn about crypto - least of all kernel
|
||||
developers. That’s certainly no longer the case now. To handle crypto stuff the kernel
|
||||
@ -4689,10 +4691,10 @@ favourite hash functions.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1414 --><p class='noindent'>
|
||||
</p><!-- l. 1437 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='hash-functions'><span class='titlemark'>0.16.1 </span> <a id='x1-610000.16.1'></a>Hash functions</h4>
|
||||
<!-- l. 1417 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
<!-- l. 1440 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4758,21 +4760,21 @@ demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
<a id='x1-61120r60'></a><span class='ecrm-0500'>60</span>
|
||||
<a id='x1-61122r61'></a><span class='ecrm-0500'>61</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2675'><span class='ectt-0800'>"sha256 hash test"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-61124r62'></a><span class='ecrm-0500'>62</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2676'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1421 --><p class='indent'> Make and install the module:
|
||||
<!-- l. 1444 --><p class='indent'> Make and install the module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb67'><a id='x1-61129r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>make</span>
|
||||
<a id='x1-61131r2'></a><span class='ecrm-0500'>2</span><span class='ectt-1000'>sudo insmod cryptosha256.ko</span>
|
||||
<a id='x1-61133r3'></a><span class='ecrm-0500'>3</span><span class='ectt-1000'>dmesg</span></pre>
|
||||
<!-- l. 1429 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1431 --><p class='indent'> Finally, remove the test module:
|
||||
<!-- l. 1452 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1454 --><p class='indent'> Finally, remove the test module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb68'><a id='x1-61136r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo rmmod cryptosha256</span></pre>
|
||||
<!-- l. 1437 --><p class='noindent'>
|
||||
<!-- l. 1460 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='symmetric-key-encryption'><span class='titlemark'>0.16.2 </span> <a id='x1-620000.16.2'></a>Symmetric key encryption</h4>
|
||||
<!-- l. 1439 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
<!-- l. 1462 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
and a password.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4974,10 +4976,10 @@ and a password.
|
||||
<a id='x1-62392r196'></a><span class='ecrm-0500'>196</span>
|
||||
<a id='x1-62394r197'></a><span class='ecrm-0500'>197</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2823'><span class='ectt-0800'>"Symmetric key encryption example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-62396r198'></a><span class='ecrm-0500'>198</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2824'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1443 --><p class='noindent'>
|
||||
<!-- l. 1466 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='standardising-the-interfaces-the-device-model'><span class='titlemark'>0.17 </span> <a id='x1-630000.17'></a>Standardising the interfaces: The Device Model</h3>
|
||||
<!-- l. 1445 --><p class='noindent'>Up to this point we’ve seen all kinds of modules doing all kinds of things, but there
|
||||
<!-- l. 1468 --><p class='noindent'>Up to this point we’ve seen all kinds of modules doing all kinds of things, but there
|
||||
was no consistency in their interfaces with the rest of the kernel. To impose some
|
||||
consistency such that there is at minimum a standardised way to start, suspend and
|
||||
resume a device a device model was added. An example is show below, and you can
|
||||
@ -5087,19 +5089,19 @@ functions.
|
||||
|
||||
|
||||
|
||||
<!-- l. 1449 --><p class='noindent'>
|
||||
<!-- l. 1472 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='optimizations'><span class='titlemark'>0.18 </span> <a id='x1-640000.18'></a>Optimizations</h3>
|
||||
<!-- l. 1451 --><p class='noindent'>
|
||||
<!-- l. 1474 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='likely-and-unlikely-conditions'><span class='titlemark'>0.18.1 </span> <a id='x1-650000.18.1'></a>Likely and Unlikely conditions</h4>
|
||||
<!-- l. 1453 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible, especially if
|
||||
<!-- l. 1476 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible, especially if
|
||||
it’s handling an interrupt or doing something which might cause noticible
|
||||
latency. If your code contains boolean conditions and if you know that the
|
||||
conditions are almost always likely to evaluate as either <span class='ecti-1000'>true </span>or <span class='ecti-1000'>false</span>, then
|
||||
you can allow the compiler to optimise for this using the <span class='ecti-1000'>likely </span>and <span class='ecti-1000'>unlikely</span>
|
||||
macros.
|
||||
</p><!-- l. 1455 --><p class='indent'> For example, when allocating memory you’re almost always expecting this to
|
||||
</p><!-- l. 1478 --><p class='indent'> For example, when allocating memory you’re almost always expecting this to
|
||||
succeed.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5109,64 +5111,64 @@ succeed.
|
||||
<a id='x1-65014r4'></a><span class='ecrm-0500'>4</span><span class='ectt-0800'> bio = NULL;</span>
|
||||
<a id='x1-65016r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor2902'><span class='ectt-0800'>goto</span></span><span class='ectt-0800'> out;</span>
|
||||
<a id='x1-65018r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 1466 --><p class='indent'> When the <span class='ecti-1000'>unlikely </span>macro is used the compiler alters its machine instruction
|
||||
<!-- l. 1489 --><p class='indent'> When the <span class='ecti-1000'>unlikely </span>macro is used the compiler alters its machine instruction
|
||||
output so that it continues along the false branch and only jumps if the condition is
|
||||
true. That avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
<span class='ecti-1000'>likely </span>macro.
|
||||
</p>
|
||||
<h3 class='sectionHead' id='common-pitfalls'><span class='titlemark'>0.19 </span> <a id='x1-660000.19'></a>Common Pitfalls</h3>
|
||||
<!-- l. 1469 --><p class='noindent'>Before I send you on your way to go out into the world and write kernel modules,
|
||||
<!-- l. 1492 --><p class='noindent'>Before I send you on your way to go out into the world and write kernel modules,
|
||||
there are a few things I need to warn you about. If I fail to warn you and something
|
||||
bad happens, please report the problem to me for a full refund of the amount I was
|
||||
paid for your copy of the book.
|
||||
</p><!-- l. 1471 --><p class='noindent'>
|
||||
</p><!-- l. 1494 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='using-standard-libraries'><span class='titlemark'>0.19.1 </span> <a id='x1-670000.19.1'></a>Using standard libraries</h4>
|
||||
<!-- l. 1473 --><p class='noindent'>You can’t do that. In a kernel module you can only use kernel functions, which are
|
||||
<!-- l. 1496 --><p class='noindent'>You can’t do that. In a kernel module you can only use kernel functions, which are
|
||||
the functions you can see in /proc/kallsyms.
|
||||
</p><!-- l. 1475 --><p class='noindent'>
|
||||
</p><!-- l. 1498 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4 class='subsectionHead' id='disabling-interrupts'><span class='titlemark'>0.19.2 </span> <a id='x1-680000.19.2'></a>Disabling interrupts</h4>
|
||||
<!-- l. 1477 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you don’t
|
||||
<!-- l. 1500 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you don’t
|
||||
enable them afterwards, your system will be stuck and you’ll have to power it
|
||||
off.
|
||||
</p><!-- l. 1479 --><p class='noindent'>
|
||||
</p><!-- l. 1502 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='sticking-your-head-inside-a-large-carnivore'><span class='titlemark'>0.19.3 </span> <a id='x1-690000.19.3'></a>Sticking your head inside a large carnivore</h4>
|
||||
<!-- l. 1481 --><p class='noindent'>I probably don’t have to warn you about this, but I figured I will anyway, just in
|
||||
<!-- l. 1504 --><p class='noindent'>I probably don’t have to warn you about this, but I figured I will anyway, just in
|
||||
case.
|
||||
</p><!-- l. 1483 --><p class='noindent'>
|
||||
</p><!-- l. 1506 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='where-to-go-from-here'><span class='titlemark'>0.20 </span> <a id='x1-700000.20'></a>Where To Go From Here?</h3>
|
||||
<!-- l. 1485 --><p class='noindent'>I could easily have squeezed a few more chapters into this book. I could have added a
|
||||
<!-- l. 1508 --><p class='noindent'>I could easily have squeezed a few more chapters into this book. I could have added a
|
||||
chapter about creating new file systems, or about adding new protocol stacks (as if
|
||||
there’s a need for that – you’d have to dig underground to find a protocol stack
|
||||
not supported by Linux). I could have added explanations of the kernel
|
||||
mechanisms we haven’t touched upon, such as bootstrapping or the disk
|
||||
interface.
|
||||
</p><!-- l. 1487 --><p class='indent'> However, I chose not to. My purpose in writing this book was to provide initiation
|
||||
</p><!-- l. 1510 --><p class='indent'> However, I chose not to. My purpose in writing this book was to provide initiation
|
||||
into the mysteries of kernel module programming and to teach the common
|
||||
techniques for that purpose. For people seriously interested in kernel programming, I
|
||||
recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a> and the <span class='ecti-1000'>Documentation </span>subdirectory within the kernel
|
||||
source code which isn’t always easy to understand but can be a starting point for
|
||||
further investigation. Also, as Linus said, the best way to learn the kernel is to read
|
||||
the source code yourself.
|
||||
</p><!-- l. 1489 --><p class='indent'> If you’re interested in more examples of short kernel modules then searching on
|
||||
</p><!-- l. 1512 --><p class='indent'> If you’re interested in more examples of short kernel modules then searching on
|
||||
sites such as Github and Gitlab is a good way to start, although there is a lot of
|
||||
duplication of older LKMPG examples which may not compile with newer kernel
|
||||
versions. You will also be able to find examples of the use of kernel modules to attack
|
||||
or compromise systems or exfiltrate data and those can be useful for thinking about
|
||||
how to defend systems and learning about existing security mechanisms within the
|
||||
kernel.
|
||||
</p><!-- l. 1491 --><p class='indent'> I hope I have helped you in your quest to become a better programmer, or at
|
||||
</p><!-- l. 1514 --><p class='indent'> I hope I have helped you in your quest to become a better programmer, or at
|
||||
least to have fun through technology. And, if you do write useful kernel modules, I
|
||||
hope you publish them under the GPL, so I can use them too.
|
||||
</p><!-- l. 1493 --><p class='indent'> If you’d like to contribute to this guide or notice anything glaringly wrong, please
|
||||
</p><!-- l. 1516 --><p class='indent'> If you’d like to contribute to this guide or notice anything glaringly wrong, please
|
||||
create an issue at <a class='url' href='https://github.com/sysprog21/lkmpg'><span class='ectt-1000'>https://github.com/sysprog21/lkmpg</span></a>.
|
||||
</p><!-- l. 1495 --><p class='indent'> Happy hacking.
|
||||
</p><!-- l. 1518 --><p class='indent'> Happy hacking.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
238
lkmpg.html
238
lkmpg.html
@ -17,7 +17,7 @@
|
||||
|
||||
<h2 class='titleHead'>The Linux Kernel Module Programming Guide</h2>
|
||||
<div class='author'><span class='ecrm-1200'>Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang</span></div><br />
|
||||
<div class='date'><span class='ecrm-1200'>August 6, 2021</span></div>
|
||||
<div class='date'><span class='ecrm-1200'>August 7, 2021</span></div>
|
||||
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ have contributed new material to this book, you must make the material and sourc
|
||||
|
||||
|
||||
code available for your revisions. Please make revisions and updates available directly
|
||||
to the document maintainer, Peter Jay Salzman <p@dirac.org>. This will allow
|
||||
to the document maintainer, Jim Huang <jserv@ccns.ncku.edu.tw>. This will allow
|
||||
for the merging of updates and provide consistent revisions to the Linux
|
||||
community.
|
||||
</p><!-- l. 63 --><p class='indent'> If you publish or distribute this book commercially, donations, royalties, and/or
|
||||
@ -3133,65 +3133,67 @@ patch.
|
||||
<!-- l. 1230 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='sleep'><span class='titlemark'>0.11.1 </span> <a id='x1-430000.11.1'></a>Sleep</h4>
|
||||
<!-- l. 1232 --><p class='noindent'>What do you do when somebody asks you for something you can’t do right away? If
|
||||
you’re a human being and you’re bothered by a human being, the only thing you can
|
||||
say is: "<span class='ecti-1000'>Not right now, I’m busy. Go away!</span>". But if you’re a kernel module and
|
||||
you’re bothered by a process, you have another possibility. You can put the process
|
||||
to sleep until you can service it. After all, processes are being put to sleep by the
|
||||
kernel and woken up all the time (that’s the way multiple processes appear to run on
|
||||
the same time on a single CPU).
|
||||
</p><!-- l. 1234 --><p class='indent'> This kernel module is an example of this. The file (called <span class='ecbx-1000'>/proc/sleep</span>) can only
|
||||
<!-- l. 1232 --><p class='noindent'>What do you do when somebody asks you for something you can not do right
|
||||
away? If you are a human being and you are bothered by a human being, the
|
||||
only thing you can say is: "<span class='ecti-1000'>Not right now, I’m busy. Go away!</span>". But if you
|
||||
are a kernel module and you are bothered by a process, you have another
|
||||
possibility. You can put the process to sleep until you can service it. After all,
|
||||
processes are being put to sleep by the kernel and woken up all the time (that
|
||||
is the way multiple processes appear to run on the same time on a single
|
||||
CPU).
|
||||
</p><!-- l. 1238 --><p class='indent'> This kernel module is an example of this. The file (called <span class='ecbx-1000'>/proc/sleep</span>) can only
|
||||
be opened by a single process at a time. If the file is already open, the kernel module
|
||||
calls wait_event_interruptible. The easiest way to keep a file open is to open it
|
||||
calls <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>wait_event_interruptible</span></span></span>. The easiest way to keep a file open is to open it
|
||||
with:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb52'><a id='x1-43003r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>tail -f</span></pre>
|
||||
<!-- l. 1240 --><p class='indent'> This function changes the status of the task (a task is the kernel data
|
||||
structure which holds information about a process and the system call it’s in, if
|
||||
<!-- l. 1247 --><p class='indent'> This function changes the status of the task (a task is the kernel data
|
||||
structure which holds information about a process and the system call it is in, if
|
||||
any) to <span class='ecbx-1000'>TASK_INTERRUPTIBLE</span>, which means that the task will
|
||||
not run until it is woken up somehow, and adds it to WaitQ, the queue
|
||||
of tasks waiting to access the file. Then, the function calls the scheduler
|
||||
to context switch to a different process, one which has some use for the
|
||||
CPU.
|
||||
</p><!-- l. 1242 --><p class='indent'> When a process is done with the file, it closes it, and module_close is called. That
|
||||
function wakes up all the processes in the queue (there’s no mechanism
|
||||
</p><!-- l. 1251 --><p class='indent'> When a process is done with the file, it closes it, and <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>module_close</span></span></span> is called.
|
||||
That function wakes up all the processes in the queue (there’s no mechanism
|
||||
to only wake up one of them). It then returns and the process which just
|
||||
closed the file can continue to run. In time, the scheduler decides that that
|
||||
process has had enough and gives control of the CPU to another process.
|
||||
Eventually, one of the processes which was in the queue will be given control
|
||||
of the CPU by the scheduler. It starts at the point right after the call to
|
||||
<span class='ecbx-1000'>module_interruptible_sleep_on</span>.
|
||||
</p><!-- l. 1244 --><p class='indent'> This means that the process is still in kernel mode - as far as the process is
|
||||
concerned, it issued the open system call and the system call hasn’t returned yet.
|
||||
The process doesn’t know somebody else used the CPU for most of the time between
|
||||
the moment it issued the call and the moment it returned.
|
||||
</p><!-- l. 1246 --><p class='indent'> It can then proceed to set a global variable to tell all the other processes that the
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>module_interruptible_sleep_on</span></span></span>.
|
||||
</p><!-- l. 1258 --><p class='indent'> This means that the process is still in kernel mode - as far as the process
|
||||
is concerned, it issued the open system call and the system call has not
|
||||
returned yet. The process does not know somebody else used the CPU for
|
||||
most of the time between the moment it issued the call and the moment it
|
||||
returned.
|
||||
</p><!-- l. 1261 --><p class='indent'> It can then proceed to set a global variable to tell all the other processes that the
|
||||
file is still open and go on with its life. When the other processes get a piece of the
|
||||
CPU, they’ll see that global variable and go back to sleep.
|
||||
</p><!-- l. 1248 --><p class='indent'> So we’ll use tail -f to keep the file open in the background, while trying to
|
||||
</p><!-- l. 1264 --><p class='indent'> So we will use <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>tail -f</span></span></span> to keep the file open in the background, while trying to
|
||||
access it with another process (again in the background, so that we need not
|
||||
switch to a different vt). As soon as the first background process is killed
|
||||
with kill %1 , the second is woken up, is able to access the file and finally
|
||||
terminates.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1250 --><p class='indent'> To make our life more interesting, <span class='ecbx-1000'>module_close </span>doesn’t have a monopoly
|
||||
with kill %1 , the second is woken up, is able to access the file and finally
|
||||
terminates.
|
||||
</p><!-- l. 1267 --><p class='indent'> To make our life more interesting, <span class='ecbx-1000'>module_close </span>does not have a monopoly
|
||||
on waking up the processes which wait to access the file. A signal, such as
|
||||
<span class='ecti-1000'>Ctrl +c </span>(<span class='ecbx-1000'>SIGINT</span>) can also wake up a process. This is because we used
|
||||
<span class='ecbx-1000'>module_interruptible_sleep_on</span>. We could have used <span class='ecbx-1000'>module_sleep_on</span>
|
||||
instead, but that would have resulted in extremely angry users whose <span class='ecti-1000'>Ctrl+c</span>’s are
|
||||
ignored.
|
||||
</p><!-- l. 1252 --><p class='indent'> In that case, we want to return with <span class='ecbx-1000'>-EINTR </span>immediately. This is important so
|
||||
</p><!-- l. 1271 --><p class='indent'> In that case, we want to return with <span class='ecbx-1000'>-EINTR </span>immediately. This is important so
|
||||
users can, for example, kill the process before it receives the file.
|
||||
</p><!-- l. 1254 --><p class='indent'> There is one more point to remember. Some times processes don’t want to sleep,
|
||||
</p><!-- l. 1273 --><p class='indent'> There is one more point to remember. Some times processes don’t want to sleep,
|
||||
they want either to get what they want immediately, or to be told it cannot be done.
|
||||
Such processes use the <span class='ecbx-1000'>O_NONBLOCK </span>flag when opening the file. The kernel is
|
||||
supposed to respond by returning with the error code <span class='ecbx-1000'>-EAGAIN </span>from operations
|
||||
which would otherwise block, such as opening the file in this example. The program
|
||||
cat_noblock, available in the source directory for this chapter, can be used to open a
|
||||
file with <span class='ecbx-1000'>O_NONBLOCK</span>.
|
||||
Such processes use the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>O_NONBLOCK</span></span></span> flag when opening the file. The kernel is supposed
|
||||
to respond by returning with the error code <span class='ecbx-1000'>-EAGAIN </span>from operations which
|
||||
would otherwise block, such as opening the file in this example. The program
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>cat_nonblock</span></span></span>, available in the <span class='ecti-1000'>examples/other </span>directory for this chapter, can be
|
||||
used to open a file with <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>O_NONBLOCK</span></span></span>.
|
||||
|
||||
|
||||
|
||||
@ -3218,7 +3220,7 @@ $ cat_nonblock /proc/sleep
|
||||
Last input:
|
||||
$
|
||||
</pre>
|
||||
<!-- l. 1277 --><p class='nopar'>
|
||||
<!-- l. 1298 --><p class='nopar'>
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb53'><a id='x1-43005r1'></a><span class='ecrm-0500'>1</span><span id='textcolor1628'><span class='ectt-0800'>/*</span></span>
|
||||
@ -3563,13 +3565,13 @@ $
|
||||
<a id='x1-43677r57'></a><span class='ecrm-0500'>57</span>
|
||||
<a id='x1-43679r58'></a><span class='ecrm-0500'>58</span><span class='ectt-0800'> </span><span id='textcolor1921'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0;</span>
|
||||
<a id='x1-43681r59'></a><span class='ecrm-0500'>59</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 1283 --><p class='noindent'>
|
||||
<!-- l. 1304 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='completions'><span class='titlemark'>0.11.2 </span> <a id='x1-440000.11.2'></a>Completions</h4>
|
||||
<!-- l. 1285 --><p class='noindent'>Sometimes one thing should happen before another within a module having multiple
|
||||
threads. Rather than using <span class='ecbx-1000'>/proc/sleep </span>commands the kernel has another way to
|
||||
do this which allows timeouts or interrupts to also happen.
|
||||
</p><!-- l. 1287 --><p class='indent'> In the following example two threads are started, but one needs to start before
|
||||
<!-- l. 1306 --><p class='noindent'>Sometimes one thing should happen before another within a module having multiple
|
||||
threads. Rather than using <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/bin/sleep</span></span></span> commands, the kernel has another way to do
|
||||
this which allows timeouts or interrupts to also happen.
|
||||
</p><!-- l. 1309 --><p class='indent'> In the following example two threads are started, but one needs to start before
|
||||
another.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
|
||||
@ -3652,27 +3654,27 @@ another.
|
||||
<a id='x1-44148r74'></a><span class='ecrm-0500'>74</span>
|
||||
<a id='x1-44150r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor1972'><span class='ectt-0800'>"Completions example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-44152r76'></a><span class='ecrm-0500'>76</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor1973'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1291 --><p class='indent'> The <span class='ecti-1000'>machine </span>structure stores the completion states for the two threads. At the
|
||||
<!-- l. 1313 --><p class='indent'> The <span class='ecti-1000'>machine </span>structure stores the completion states for the two threads. At the
|
||||
exit point of each thread the respective completion state is updated, and
|
||||
<span class='ecti-1000'>wait_for_completion </span>is used by the flywheel thread to ensure that it doesn’t begin
|
||||
prematurely.
|
||||
</p><!-- l. 1293 --><p class='indent'> So even though <span class='ecti-1000'>flywheel_thread </span>is started first you should notice if you load this
|
||||
<span class='obeylines-h'><span class='verb'><span class='ectt-1000'>{wait_for_completion</span></span></span> is used by the flywheel thread to ensure that it does not
|
||||
begin prematurely.
|
||||
</p><!-- l. 1316 --><p class='indent'> So even though <span class='ecti-1000'>flywheel_thread </span>is started first you should notice if you load this
|
||||
module and run <span class='ecti-1000'>dmesg </span>that turning the crank always happens first because the
|
||||
flywheel thread waits for it to complete.
|
||||
</p><!-- l. 1295 --><p class='indent'> There are other variations upon the <span class='ecti-1000'>wait_for_completion </span>function, which include
|
||||
timeouts or being interrupted, but this basic mechanism is enough for many common
|
||||
situations without adding a lot of complexity.
|
||||
</p><!-- l. 1297 --><p class='noindent'>
|
||||
</p><!-- l. 1318 --><p class='indent'> There are other variations upon the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>wait_for_completion</span></span></span> function, which
|
||||
include timeouts or being interrupted, but this basic mechanism is enough for many
|
||||
common situations without adding a lot of complexity.
|
||||
</p><!-- l. 1320 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='avoiding-collisions-and-deadlocks'><span class='titlemark'>0.12 </span> <a id='x1-450000.12'></a>Avoiding Collisions and Deadlocks</h3>
|
||||
<!-- l. 1299 --><p class='noindent'>If processes running on different CPUs or in different threads try to access the same
|
||||
<!-- l. 1322 --><p class='noindent'>If processes running on different CPUs or in different threads try to access the same
|
||||
memory then it’s possible that strange things can happen or your system can lock
|
||||
up. To avoid this various types of mutual exclusion kernel functions are available.
|
||||
These indicate if a section of code is "locked" or "unlocked" so that simultaneous
|
||||
attempts to run it can’t happen.
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='mutex'><span class='titlemark'>0.12.1 </span> <a id='x1-460000.12.1'></a>Mutex</h4>
|
||||
<!-- l. 1302 --><p class='noindent'>You can use kernel mutexes (mutual exclusions) in much the same manner that you
|
||||
<!-- l. 1325 --><p class='noindent'>You can use kernel mutexes (mutual exclusions) in much the same manner that you
|
||||
might deploy them in userland. This may be all that’s needed to avoid collisions in
|
||||
most cases.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -3718,10 +3720,10 @@ most cases.
|
||||
<a id='x1-46078r39'></a><span class='ecrm-0500'>39</span>
|
||||
<a id='x1-46080r40'></a><span class='ecrm-0500'>40</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2014'><span class='ectt-0800'>"Mutex example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-46082r41'></a><span class='ecrm-0500'>41</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2015'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1306 --><p class='noindent'>
|
||||
<!-- l. 1329 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='spinlocks'><span class='titlemark'>0.12.2 </span> <a id='x1-470000.12.2'></a>Spinlocks</h4>
|
||||
<!-- l. 1308 --><p class='noindent'>As the name suggests, spinlocks lock up the CPU that the code is running on,
|
||||
<!-- l. 1331 --><p class='noindent'>As the name suggests, spinlocks lock up the CPU that the code is running on,
|
||||
taking 100% of its resources. Because of this you should only use the spinlock
|
||||
mechanism around code which is likely to take no more than a few milliseconds to
|
||||
run and so won’t noticably slow anything down from the user’s point of
|
||||
@ -3729,7 +3731,7 @@ view.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1310 --><p class='indent'> The example here is <span class='ecti-1000'>"irq safe" </span>in that if interrupts happen during the lock then
|
||||
</p><!-- l. 1333 --><p class='indent'> The example here is <span class='ecti-1000'>"irq safe" </span>in that if interrupts happen during the lock then
|
||||
they won’t be forgotten and will activate when the unlock happens, using the <span class='ecti-1000'>flags</span>
|
||||
variable to retain their state.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -3799,10 +3801,10 @@ variable to retain their state.
|
||||
<a id='x1-47126r63'></a><span class='ecrm-0500'>63</span>
|
||||
<a id='x1-47128r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2072'><span class='ectt-0800'>"Spinlock example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-47130r65'></a><span class='ecrm-0500'>65</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2073'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1314 --><p class='noindent'>
|
||||
<!-- l. 1337 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='read-and-write-locks'><span class='titlemark'>0.12.3 </span> <a id='x1-480000.12.3'></a>Read and write locks</h4>
|
||||
<!-- l. 1316 --><p class='noindent'>Read and write locks are specialised kinds of spinlocks so that you can exclusively
|
||||
<!-- l. 1339 --><p class='noindent'>Read and write locks are specialised kinds of spinlocks so that you can exclusively
|
||||
read from something or write to something. Like the earlier spinlocks example the
|
||||
one below shows an "irq safe" situation in which if other functions were triggered
|
||||
from irqs which might also read and write to whatever you are concerned
|
||||
@ -3867,13 +3869,13 @@ module.
|
||||
<a id='x1-48106r53'></a><span class='ecrm-0500'>53</span>
|
||||
<a id='x1-48108r54'></a><span class='ecrm-0500'>54</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2120'><span class='ectt-0800'>"Read/Write locks example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-48110r55'></a><span class='ecrm-0500'>55</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2121'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1320 --><p class='indent'> Of course if you know for sure that there are no functions triggered by irqs
|
||||
<!-- l. 1343 --><p class='indent'> Of course if you know for sure that there are no functions triggered by irqs
|
||||
which could possibly interfere with your logic then you can use the simpler
|
||||
<span class='ecti-1000'>read_lock(&myrwlock) </span>and <span class='ecti-1000'>read_unlock(&myrwlock) </span>or the corresponding write
|
||||
functions.
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='atomic-operations'><span class='titlemark'>0.12.4 </span> <a id='x1-490000.12.4'></a>Atomic operations</h4>
|
||||
<!-- l. 1323 --><p class='noindent'>If you’re doing simple arithmetic: adding, subtracting or bitwise operations then
|
||||
<!-- l. 1346 --><p class='noindent'>If you’re doing simple arithmetic: adding, subtracting or bitwise operations then
|
||||
there’s another way in the multi-CPU and multi-hyperthreaded world to stop other
|
||||
parts of the system from messing with your mojo. By using atomic operations you
|
||||
can be confident that your addition, subtraction or bit flip did actually happen
|
||||
@ -3958,21 +3960,21 @@ below.
|
||||
|
||||
|
||||
|
||||
<!-- l. 1327 --><p class='noindent'>
|
||||
<!-- l. 1350 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='replacing-print-macros'><span class='titlemark'>0.13 </span> <a id='x1-500000.13'></a>Replacing Print Macros</h3>
|
||||
<!-- l. 1329 --><p class='noindent'>
|
||||
<!-- l. 1352 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='replacement'><span class='titlemark'>0.13.1 </span> <a id='x1-510000.13.1'></a>Replacement</h4>
|
||||
<!-- l. 1331 --><p class='noindent'>In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s
|
||||
<!-- l. 1354 --><p class='noindent'>In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s
|
||||
true for developing kernel modules, but in actual use, you want to be able
|
||||
to send messages to whichever tty the command to load the module came
|
||||
from.
|
||||
</p><!-- l. 1333 --><p class='indent'> "tty" is an abbreviation of <span class='ecti-1000'>teletype</span>: originally a combination keyboard-printer
|
||||
</p><!-- l. 1356 --><p class='indent'> "tty" is an abbreviation of <span class='ecti-1000'>teletype</span>: originally a combination keyboard-printer
|
||||
used to communicate with a Unix system, and today an abstraction for the text
|
||||
stream used for a Unix program, whether it’s a physical terminal, an xterm on an X
|
||||
display, a network connection used with ssh, etc.
|
||||
</p><!-- l. 1335 --><p class='indent'> The way this is done is by using current, a pointer to the currently running task,
|
||||
</p><!-- l. 1358 --><p class='indent'> The way this is done is by using current, a pointer to the currently running task,
|
||||
to get the current task’s tty structure. Then, we look inside that tty structure to find
|
||||
a pointer to a string write function, which we use to write a string to the
|
||||
tty.
|
||||
@ -4061,16 +4063,16 @@ tty.
|
||||
<a id='x1-51162r81'></a><span class='ecrm-0500'>81</span>
|
||||
<a id='x1-51164r82'></a><span class='ecrm-0500'>82</span><span class='ectt-0800'>module_init(print_string_init);</span>
|
||||
<a id='x1-51166r83'></a><span class='ecrm-0500'>83</span><span class='ectt-0800'>module_exit(print_string_exit);</span></pre>
|
||||
<!-- l. 1339 --><p class='noindent'>
|
||||
<!-- l. 1362 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='flashing-keyboard-leds'><span class='titlemark'>0.13.2 </span> <a id='x1-520000.13.2'></a>Flashing keyboard LEDs</h4>
|
||||
<!-- l. 1341 --><p class='noindent'>In certain conditions, you may desire a simpler and more direct way to communicate
|
||||
<!-- l. 1364 --><p class='noindent'>In certain conditions, you may desire a simpler and more direct way to communicate
|
||||
to the external world. Flashing keyboard LEDs can be such a solution: It is an
|
||||
immediate way to attract attention or to display a status condition. Keyboard LEDs
|
||||
are present on every hardware, they are always visible, they do not need any setup,
|
||||
and their use is rather simple and non-intrusive, compared to writing to a tty or a
|
||||
file.
|
||||
</p><!-- l. 1343 --><p class='indent'> The following source code illustrates a minimal kernel module which, when
|
||||
</p><!-- l. 1366 --><p class='indent'> The following source code illustrates a minimal kernel module which, when
|
||||
loaded, starts blinking the keyboard LEDs until it is unloaded.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4167,7 +4169,7 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
|
||||
<a id='x1-52182r91'></a><span class='ecrm-0500'>91</span>
|
||||
<a id='x1-52184r92'></a><span class='ecrm-0500'>92</span><span class='ectt-0800'>module_init(kbleds_init);</span>
|
||||
<a id='x1-52186r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>module_exit(kbleds_cleanup);</span></pre>
|
||||
<!-- l. 1347 --><p class='indent'> If none of the examples in this chapter fit your debugging needs there might yet
|
||||
<!-- l. 1370 --><p class='indent'> If none of the examples in this chapter fit your debugging needs there might yet
|
||||
be some other tricks to try. Ever wondered what CONFIG_LL_DEBUG in
|
||||
make menuconfig is good for? If you activate that you get low level access
|
||||
to the serial port. While this might not sound very powerful by itself, you
|
||||
@ -4180,22 +4182,22 @@ over a serial line. If you find yourself porting the kernel to some new and
|
||||
former unsupported architecture this is usually amongst the first things that
|
||||
should be implemented. Logging over a netconsole might also be worth a
|
||||
try.
|
||||
</p><!-- l. 1349 --><p class='indent'> While you have seen lots of stuff that can be used to aid debugging here, there are
|
||||
</p><!-- l. 1372 --><p class='indent'> While you have seen lots of stuff that can be used to aid debugging here, there are
|
||||
some things to be aware of. Debugging is almost always intrusive. Adding debug code
|
||||
can change the situation enough to make the bug seem to dissappear. Thus you
|
||||
should try to keep debug code to a minimum and make sure it does not show up in
|
||||
production code.
|
||||
</p><!-- l. 1351 --><p class='noindent'>
|
||||
</p><!-- l. 1374 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='scheduling-tasks'><span class='titlemark'>0.14 </span> <a id='x1-530000.14'></a>Scheduling Tasks</h3>
|
||||
<!-- l. 1353 --><p class='noindent'>There are two main ways of running tasks: tasklets and work queues. Tasklets are a
|
||||
<!-- l. 1376 --><p class='noindent'>There are two main ways of running tasks: tasklets and work queues. Tasklets are a
|
||||
quick and easy way of scheduling a single function to be run, for example when
|
||||
triggered from an interrupt, whereas work queues are more complicated but also
|
||||
better suited to running multiple things in a sequence.
|
||||
</p><!-- l. 1355 --><p class='noindent'>
|
||||
</p><!-- l. 1378 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='tasklets'><span class='titlemark'>0.14.1 </span> <a id='x1-540000.14.1'></a>Tasklets</h4>
|
||||
<!-- l. 1357 --><p class='noindent'>Here’s an example tasklet module. The <span class='ecti-1000'>tasklet_fn </span>function runs for a few seconds
|
||||
<!-- l. 1380 --><p class='noindent'>Here’s an example tasklet module. The <span class='ecti-1000'>tasklet_fn </span>function runs for a few seconds
|
||||
and in the mean time execution of the <span class='ecti-1000'>example_tasklet_init </span>function continues to
|
||||
the exit point.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -4237,7 +4239,7 @@ the exit point.
|
||||
<a id='x1-54070r35'></a><span class='ecrm-0500'>35</span>
|
||||
<a id='x1-54072r36'></a><span class='ecrm-0500'>36</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2377'><span class='ectt-0800'>"Tasklet example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-54074r37'></a><span class='ecrm-0500'>37</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2378'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1361 --><p class='indent'> So with this example loaded <span class='ecti-1000'>dmesg </span>should show:
|
||||
<!-- l. 1384 --><p class='indent'> So with this example loaded <span class='ecti-1000'>dmesg </span>should show:
|
||||
|
||||
|
||||
|
||||
@ -4248,11 +4250,11 @@ Example tasklet starts
|
||||
Example tasklet init continues...
|
||||
Example tasklet ends
|
||||
</pre>
|
||||
<!-- l. 1368 --><p class='nopar'>
|
||||
</p><!-- l. 1370 --><p class='noindent'>
|
||||
<!-- l. 1391 --><p class='nopar'>
|
||||
</p><!-- l. 1393 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='work-queues'><span class='titlemark'>0.14.2 </span> <a id='x1-550000.14.2'></a>Work queues</h4>
|
||||
<!-- l. 1372 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
<!-- l. 1395 --><p class='noindent'>To add a task to the scheduler we can use a workqueue. The kernel then uses the
|
||||
Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4287,18 +4289,18 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
|
||||
<a id='x1-55058r29'></a><span class='ecrm-0500'>29</span>
|
||||
<a id='x1-55060r30'></a><span class='ecrm-0500'>30</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2402'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-55062r31'></a><span class='ecrm-0500'>31</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2403'><span class='ectt-0800'>"Workqueue example"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1376 --><p class='noindent'>
|
||||
<!-- l. 1399 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='interrupt-handlers'><span class='titlemark'>0.15 </span> <a id='x1-560000.15'></a>Interrupt Handlers</h3>
|
||||
<!-- l. 1378 --><p class='noindent'>
|
||||
<!-- l. 1401 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='interrupt-handlers1'><span class='titlemark'>0.15.1 </span> <a id='x1-570000.15.1'></a>Interrupt Handlers</h4>
|
||||
<!-- l. 1380 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we’ve done as a
|
||||
<!-- l. 1403 --><p class='noindent'>Except for the last chapter, everything we did in the kernel so far we’ve done as a
|
||||
response to a process asking for it, either by dealing with a special file, sending an
|
||||
ioctl(), or issuing a system call. But the job of the kernel isn’t just to respond to
|
||||
process requests. Another job, which is every bit as important, is to speak to the
|
||||
hardware connected to the machine.
|
||||
</p><!-- l. 1382 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
</p><!-- l. 1405 --><p class='indent'> There are two types of interaction between the CPU and the rest of the
|
||||
computer’s hardware. The first type is when the CPU gives orders to the hardware,
|
||||
the other is when the hardware needs to tell the CPU something. The second, called
|
||||
interrupts, is much harder to implement because it has to be dealt with when
|
||||
@ -4308,14 +4310,14 @@ lost.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1384 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
</p><!-- l. 1407 --><p class='indent'> Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There
|
||||
are two types of IRQ’s, short and long. A short IRQ is one which is expected to take
|
||||
a very short period of time, during which the rest of the machine will be blocked and
|
||||
no other interrupts will be handled. A long IRQ is one which can take longer, and
|
||||
during which other interrupts may occur (but not interrupts from the same
|
||||
device). If at all possible, it’s better to declare an interrupt handler to be
|
||||
long.
|
||||
</p><!-- l. 1386 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s
|
||||
</p><!-- l. 1409 --><p class='indent'> When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s
|
||||
processing a more important interrupt, in which case it will deal with this one
|
||||
only when the more important one is done), saves certain parameters on
|
||||
the stack and calls the interrupt handler. This means that certain things
|
||||
@ -4327,9 +4329,9 @@ the new information at a later time (this is called the "bottom half") and
|
||||
return. The kernel is then guaranteed to call the bottom half as soon as
|
||||
possible – and when it does, everything allowed in kernel modules will be
|
||||
allowed.
|
||||
</p><!-- l. 1388 --><p class='indent'> The way to implement this is to call <span class='ecbx-1000'>request_irq() </span>to get your interrupt handler
|
||||
</p><!-- l. 1411 --><p class='indent'> The way to implement this is to call <span class='ecbx-1000'>request_irq() </span>to get your interrupt handler
|
||||
called when the relevant IRQ is received.
|
||||
</p><!-- l. 1390 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
</p><!-- l. 1413 --><p class='indent'> In practice IRQ handling can be a bit more complex. Hardware is often
|
||||
designed in a way that chains two interrupt controllers, so that all the IRQs
|
||||
from interrupt controller B are cascaded to a certain IRQ from interrupt
|
||||
controller A. Of course that requires that the kernel finds out which IRQ it
|
||||
@ -4343,7 +4345,7 @@ another truckload of problems. It’s not enough to know if a certain IRQs
|
||||
has happend, it’s also important for what CPU(s) it was for. People still
|
||||
interested in more details, might want to do a web search for "APIC" now
|
||||
;)
|
||||
</p><!-- l. 1392 --><p class='indent'> This function receives the IRQ number, the name of the function, flags, a name
|
||||
</p><!-- l. 1415 --><p class='indent'> This function receives the IRQ number, the name of the function, flags, a name
|
||||
for /proc/interrupts and a parameter to pass to the interrupt handler. Usually
|
||||
there is a certain number of IRQs available. How many IRQs there are is
|
||||
hardware-dependent. The flags can include SA_SHIRQ to indicate you’re willing to
|
||||
@ -4354,16 +4356,16 @@ or if you’re both willing to share.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1394 --><p class='noindent'>
|
||||
</p><!-- l. 1417 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='detecting-button-presses'><span class='titlemark'>0.15.2 </span> <a id='x1-580000.15.2'></a>Detecting button presses</h4>
|
||||
<!-- l. 1396 --><p class='noindent'>Many popular single board computers, such as Raspberry Pis or Beagleboards, have
|
||||
<!-- l. 1419 --><p class='noindent'>Many popular single board computers, such as Raspberry Pis or Beagleboards, have
|
||||
a bunch of GPIO pins. Attaching buttons to those and then having a button press do
|
||||
something is a classic case in which you might need to use interrupts so that instead
|
||||
of having the CPU waste time and battery power polling for a change in input state
|
||||
it’s better for the input to trigger the CPU to then run a particular handling
|
||||
function.
|
||||
</p><!-- l. 1398 --><p class='indent'> Here’s an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
</p><!-- l. 1421 --><p class='indent'> Here’s an example where buttons are connected to GPIO numbers 17 and 18 and
|
||||
an LED is connected to GPIO 4. You can change those numbers to whatever is
|
||||
appropriate for your board.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
@ -4510,14 +4512,14 @@ appropriate for your board.
|
||||
<a id='x1-58280r140'></a><span class='ecrm-0500'>140</span>
|
||||
<a id='x1-58282r141'></a><span class='ecrm-0500'>141</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2506'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-58284r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2507'><span class='ectt-0800'>"Handle some GPIO interrupts"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1402 --><p class='noindent'>
|
||||
<!-- l. 1425 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='bottom-half'><span class='titlemark'>0.15.3 </span> <a id='x1-590000.15.3'></a>Bottom Half</h4>
|
||||
<!-- l. 1404 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
<!-- l. 1427 --><p class='noindent'>Suppose you want to do a bunch of stuff inside of an interrupt routine. A common
|
||||
way to do that without rendering the interrupt unavailable for a significant duration
|
||||
is to combine it with a tasklet. This pushes the bulk of the work off into the
|
||||
scheduler.
|
||||
</p><!-- l. 1406 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
</p><!-- l. 1429 --><p class='indent'> The example below modifies the previous example to also run an additional task
|
||||
when an interrupt is triggered.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4677,10 +4679,10 @@ when an interrupt is triggered.
|
||||
<a id='x1-59308r154'></a><span class='ecrm-0500'>154</span>
|
||||
<a id='x1-59310r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2624'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-59312r156'></a><span class='ecrm-0500'>156</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2625'><span class='ectt-0800'>"Interrupt with top and bottom half"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1410 --><p class='noindent'>
|
||||
<!-- l. 1433 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='crypto'><span class='titlemark'>0.16 </span> <a id='x1-600000.16'></a>Crypto</h3>
|
||||
<!-- l. 1412 --><p class='noindent'>At the dawn of the internet everybody trusted everybody completely…but that didn’t
|
||||
<!-- l. 1435 --><p class='noindent'>At the dawn of the internet everybody trusted everybody completely…but that didn’t
|
||||
work out so well. When this guide was originally written it was a more innocent era
|
||||
in which almost nobody actually gave a damn about crypto - least of all kernel
|
||||
developers. That’s certainly no longer the case now. To handle crypto stuff the kernel
|
||||
@ -4689,10 +4691,10 @@ favourite hash functions.
|
||||
|
||||
|
||||
|
||||
</p><!-- l. 1414 --><p class='noindent'>
|
||||
</p><!-- l. 1437 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='hash-functions'><span class='titlemark'>0.16.1 </span> <a id='x1-610000.16.1'></a>Hash functions</h4>
|
||||
<!-- l. 1417 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
<!-- l. 1440 --><p class='noindent'>Calculating and checking the hashes of things is a common operation. Here is a
|
||||
demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4758,21 +4760,21 @@ demonstration of how to calculate a sha256 hash within a kernel module.
|
||||
<a id='x1-61120r60'></a><span class='ecrm-0500'>60</span>
|
||||
<a id='x1-61122r61'></a><span class='ecrm-0500'>61</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2675'><span class='ectt-0800'>"sha256 hash test"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-61124r62'></a><span class='ecrm-0500'>62</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2676'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1421 --><p class='indent'> Make and install the module:
|
||||
<!-- l. 1444 --><p class='indent'> Make and install the module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb67'><a id='x1-61129r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>make</span>
|
||||
<a id='x1-61131r2'></a><span class='ecrm-0500'>2</span><span class='ectt-1000'>sudo insmod cryptosha256.ko</span>
|
||||
<a id='x1-61133r3'></a><span class='ecrm-0500'>3</span><span class='ectt-1000'>dmesg</span></pre>
|
||||
<!-- l. 1429 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1431 --><p class='indent'> Finally, remove the test module:
|
||||
<!-- l. 1452 --><p class='indent'> And you should see that the hash was calculated for the test string.
|
||||
</p><!-- l. 1454 --><p class='indent'> Finally, remove the test module:
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
<pre class='fancyvrb' id='fancyvrb68'><a id='x1-61136r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>sudo rmmod cryptosha256</span></pre>
|
||||
<!-- l. 1437 --><p class='noindent'>
|
||||
<!-- l. 1460 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='symmetric-key-encryption'><span class='titlemark'>0.16.2 </span> <a id='x1-620000.16.2'></a>Symmetric key encryption</h4>
|
||||
<!-- l. 1439 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
<!-- l. 1462 --><p class='noindent'>Here is an example of symmetrically encrypting a string using the AES algorithm
|
||||
and a password.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -4974,10 +4976,10 @@ and a password.
|
||||
<a id='x1-62392r196'></a><span class='ecrm-0500'>196</span>
|
||||
<a id='x1-62394r197'></a><span class='ecrm-0500'>197</span><span class='ectt-0800'>MODULE_DESCRIPTION(</span><span id='textcolor2823'><span class='ectt-0800'>"Symmetric key encryption example"</span></span><span class='ectt-0800'>);</span>
|
||||
<a id='x1-62396r198'></a><span class='ecrm-0500'>198</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor2824'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
|
||||
<!-- l. 1443 --><p class='noindent'>
|
||||
<!-- l. 1466 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='standardising-the-interfaces-the-device-model'><span class='titlemark'>0.17 </span> <a id='x1-630000.17'></a>Standardising the interfaces: The Device Model</h3>
|
||||
<!-- l. 1445 --><p class='noindent'>Up to this point we’ve seen all kinds of modules doing all kinds of things, but there
|
||||
<!-- l. 1468 --><p class='noindent'>Up to this point we’ve seen all kinds of modules doing all kinds of things, but there
|
||||
was no consistency in their interfaces with the rest of the kernel. To impose some
|
||||
consistency such that there is at minimum a standardised way to start, suspend and
|
||||
resume a device a device model was added. An example is show below, and you can
|
||||
@ -5087,19 +5089,19 @@ functions.
|
||||
|
||||
|
||||
|
||||
<!-- l. 1449 --><p class='noindent'>
|
||||
<!-- l. 1472 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='optimizations'><span class='titlemark'>0.18 </span> <a id='x1-640000.18'></a>Optimizations</h3>
|
||||
<!-- l. 1451 --><p class='noindent'>
|
||||
<!-- l. 1474 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='likely-and-unlikely-conditions'><span class='titlemark'>0.18.1 </span> <a id='x1-650000.18.1'></a>Likely and Unlikely conditions</h4>
|
||||
<!-- l. 1453 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible, especially if
|
||||
<!-- l. 1476 --><p class='noindent'>Sometimes you might want your code to run as quickly as possible, especially if
|
||||
it’s handling an interrupt or doing something which might cause noticible
|
||||
latency. If your code contains boolean conditions and if you know that the
|
||||
conditions are almost always likely to evaluate as either <span class='ecti-1000'>true </span>or <span class='ecti-1000'>false</span>, then
|
||||
you can allow the compiler to optimise for this using the <span class='ecti-1000'>likely </span>and <span class='ecti-1000'>unlikely</span>
|
||||
macros.
|
||||
</p><!-- l. 1455 --><p class='indent'> For example, when allocating memory you’re almost always expecting this to
|
||||
</p><!-- l. 1478 --><p class='indent'> For example, when allocating memory you’re almost always expecting this to
|
||||
succeed.
|
||||
</p><!-- l. 1 --><p class='indent'>
|
||||
</p>
|
||||
@ -5109,64 +5111,64 @@ succeed.
|
||||
<a id='x1-65014r4'></a><span class='ecrm-0500'>4</span><span class='ectt-0800'> bio = NULL;</span>
|
||||
<a id='x1-65016r5'></a><span class='ecrm-0500'>5</span><span class='ectt-0800'> </span><span id='textcolor2902'><span class='ectt-0800'>goto</span></span><span class='ectt-0800'> out;</span>
|
||||
<a id='x1-65018r6'></a><span class='ecrm-0500'>6</span><span class='ectt-0800'>}</span></pre>
|
||||
<!-- l. 1466 --><p class='indent'> When the <span class='ecti-1000'>unlikely </span>macro is used the compiler alters its machine instruction
|
||||
<!-- l. 1489 --><p class='indent'> When the <span class='ecti-1000'>unlikely </span>macro is used the compiler alters its machine instruction
|
||||
output so that it continues along the false branch and only jumps if the condition is
|
||||
true. That avoids flushing the processor pipeline. The opposite happens if you use the
|
||||
<span class='ecti-1000'>likely </span>macro.
|
||||
</p>
|
||||
<h3 class='sectionHead' id='common-pitfalls'><span class='titlemark'>0.19 </span> <a id='x1-660000.19'></a>Common Pitfalls</h3>
|
||||
<!-- l. 1469 --><p class='noindent'>Before I send you on your way to go out into the world and write kernel modules,
|
||||
<!-- l. 1492 --><p class='noindent'>Before I send you on your way to go out into the world and write kernel modules,
|
||||
there are a few things I need to warn you about. If I fail to warn you and something
|
||||
bad happens, please report the problem to me for a full refund of the amount I was
|
||||
paid for your copy of the book.
|
||||
</p><!-- l. 1471 --><p class='noindent'>
|
||||
</p><!-- l. 1494 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='using-standard-libraries'><span class='titlemark'>0.19.1 </span> <a id='x1-670000.19.1'></a>Using standard libraries</h4>
|
||||
<!-- l. 1473 --><p class='noindent'>You can’t do that. In a kernel module you can only use kernel functions, which are
|
||||
<!-- l. 1496 --><p class='noindent'>You can’t do that. In a kernel module you can only use kernel functions, which are
|
||||
the functions you can see in /proc/kallsyms.
|
||||
</p><!-- l. 1475 --><p class='noindent'>
|
||||
</p><!-- l. 1498 --><p class='noindent'>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4 class='subsectionHead' id='disabling-interrupts'><span class='titlemark'>0.19.2 </span> <a id='x1-680000.19.2'></a>Disabling interrupts</h4>
|
||||
<!-- l. 1477 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you don’t
|
||||
<!-- l. 1500 --><p class='noindent'>You might need to do this for a short time and that is OK, but if you don’t
|
||||
enable them afterwards, your system will be stuck and you’ll have to power it
|
||||
off.
|
||||
</p><!-- l. 1479 --><p class='noindent'>
|
||||
</p><!-- l. 1502 --><p class='noindent'>
|
||||
</p>
|
||||
<h4 class='subsectionHead' id='sticking-your-head-inside-a-large-carnivore'><span class='titlemark'>0.19.3 </span> <a id='x1-690000.19.3'></a>Sticking your head inside a large carnivore</h4>
|
||||
<!-- l. 1481 --><p class='noindent'>I probably don’t have to warn you about this, but I figured I will anyway, just in
|
||||
<!-- l. 1504 --><p class='noindent'>I probably don’t have to warn you about this, but I figured I will anyway, just in
|
||||
case.
|
||||
</p><!-- l. 1483 --><p class='noindent'>
|
||||
</p><!-- l. 1506 --><p class='noindent'>
|
||||
</p>
|
||||
<h3 class='sectionHead' id='where-to-go-from-here'><span class='titlemark'>0.20 </span> <a id='x1-700000.20'></a>Where To Go From Here?</h3>
|
||||
<!-- l. 1485 --><p class='noindent'>I could easily have squeezed a few more chapters into this book. I could have added a
|
||||
<!-- l. 1508 --><p class='noindent'>I could easily have squeezed a few more chapters into this book. I could have added a
|
||||
chapter about creating new file systems, or about adding new protocol stacks (as if
|
||||
there’s a need for that – you’d have to dig underground to find a protocol stack
|
||||
not supported by Linux). I could have added explanations of the kernel
|
||||
mechanisms we haven’t touched upon, such as bootstrapping or the disk
|
||||
interface.
|
||||
</p><!-- l. 1487 --><p class='indent'> However, I chose not to. My purpose in writing this book was to provide initiation
|
||||
</p><!-- l. 1510 --><p class='indent'> However, I chose not to. My purpose in writing this book was to provide initiation
|
||||
into the mysteries of kernel module programming and to teach the common
|
||||
techniques for that purpose. For people seriously interested in kernel programming, I
|
||||
recommend <a href='https://kernelnewbies.org'>kernelnewbies.org</a> and the <span class='ecti-1000'>Documentation </span>subdirectory within the kernel
|
||||
source code which isn’t always easy to understand but can be a starting point for
|
||||
further investigation. Also, as Linus said, the best way to learn the kernel is to read
|
||||
the source code yourself.
|
||||
</p><!-- l. 1489 --><p class='indent'> If you’re interested in more examples of short kernel modules then searching on
|
||||
</p><!-- l. 1512 --><p class='indent'> If you’re interested in more examples of short kernel modules then searching on
|
||||
sites such as Github and Gitlab is a good way to start, although there is a lot of
|
||||
duplication of older LKMPG examples which may not compile with newer kernel
|
||||
versions. You will also be able to find examples of the use of kernel modules to attack
|
||||
or compromise systems or exfiltrate data and those can be useful for thinking about
|
||||
how to defend systems and learning about existing security mechanisms within the
|
||||
kernel.
|
||||
</p><!-- l. 1491 --><p class='indent'> I hope I have helped you in your quest to become a better programmer, or at
|
||||
</p><!-- l. 1514 --><p class='indent'> I hope I have helped you in your quest to become a better programmer, or at
|
||||
least to have fun through technology. And, if you do write useful kernel modules, I
|
||||
hope you publish them under the GPL, so I can use them too.
|
||||
</p><!-- l. 1493 --><p class='indent'> If you’d like to contribute to this guide or notice anything glaringly wrong, please
|
||||
</p><!-- l. 1516 --><p class='indent'> If you’d like to contribute to this guide or notice anything glaringly wrong, please
|
||||
create an issue at <a class='url' href='https://github.com/sysprog21/lkmpg'><span class='ectt-1000'>https://github.com/sysprog21/lkmpg</span></a>.
|
||||
</p><!-- l. 1495 --><p class='indent'> Happy hacking.
|
||||
</p><!-- l. 1518 --><p class='indent'> Happy hacking.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
Loading…
x
Reference in New Issue
Block a user