mirror of
https://github.com/sysprog21/lkmpg.git
synced 2024-11-22 10:28:13 +08:00
Merge pull request #66 from CyrilBrulebois/master
Proofreading and small improvements
This commit is contained in:
commit
48cb100473
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* hello-1.c - The simplest kernel module.
|
||||
*/
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
#include <linux/kernel.h> /* Needed for pr_info() */
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
|
||||
int init_module(void)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* This is preferred over using init_module() and cleanup_module().
|
||||
*/
|
||||
#include <linux/init.h> /* Needed for the macros */
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
#include <linux/kernel.h> /* Needed for pr_info() */
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
|
||||
static int __init hello_2_init(void)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* hello-3.c - Illustrating the __init, __initdata and __exit macros.
|
||||
*/
|
||||
#include <linux/init.h> /* Needed for the macros */
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
#include <linux/kernel.h> /* Needed for pr_info() */
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
|
||||
static int hello3_data __initdata = 3;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* hello-4.c - Demonstrates module documentation.
|
||||
*/
|
||||
#include <linux/init.h> /* Needed for the macros */
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
#include <linux/kernel.h> /* Needed for pr_info() */
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
40
lkmpg.tex
40
lkmpg.tex
|
@ -331,7 +331,7 @@ clean:
|
|||
Now have a look at \src{drivers/char/Makefile} for a real world example.
|
||||
As you can see, some things get hardwired into the kernel (\verb|obj-y|) but where are all those \verb|obj-m| gone?
|
||||
Those familiar with shell scripts will easily be able to spot them.
|
||||
For those not, the \verb|obj-$(CONFIG_FOO)| entries you see everywhere expand into \verb|obj-y| or \verb|obj-m|, depending on whether the \verb|CONFIG_FOO| variable has been set to y or m.
|
||||
For those not, the \verb|obj-$(CONFIG_FOO)| entries you see everywhere expand into \verb|obj-y| or \verb|obj-m|, depending on whether the \verb|CONFIG_FOO| variable has been set to \verb|y| or \verb|m|.
|
||||
While we are at it, those were exactly the kind of variables that you have set in the \verb|.config| file in the top-level directory of Linux kernel source tree, the last time when you said \sh|make menuconfig| or something like that.
|
||||
|
||||
\subsection{The \_\_init and \_\_exit Macros}
|
||||
|
@ -488,7 +488,7 @@ Now, if you just install a kernel source tree, use it to compile your kernel mod
|
|||
insmod: error inserting 'poet_atkm.ko': -1 Invalid module format
|
||||
\end{verbatim}
|
||||
|
||||
Less cryptical information are logged to the systemd journal:
|
||||
Less cryptic information is logged to the systemd journal:
|
||||
|
||||
\begin{verbatim}
|
||||
Jun 4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
|
||||
|
@ -512,7 +512,7 @@ name: hello_4
|
|||
vermagic: 5.4.0-70-generic SMP mod_unload modversions
|
||||
\end{verbatim}
|
||||
|
||||
To overcome this problem we could resort to the \verb|--force-vermagic| option, but this solution is potentially unsafe, and unquestionably inacceptable in production modules.
|
||||
To overcome this problem we could resort to the \verb|--force-vermagic| option, but this solution is potentially unsafe, and unquestionably unacceptable in production modules.
|
||||
Consequently, we want to compile our module in an environment which was identical to the one in which our precompiled kernel was built.
|
||||
How to do this, is the subject of the remainder of this chapter.
|
||||
|
||||
|
@ -522,7 +522,7 @@ Usually, this is available in your current \verb|boot| directory, under a name l
|
|||
You may just want to copy it to your kernel source tree: \sh|cp /boot/config-`uname -r` .config|.
|
||||
|
||||
Let's focus again on the previous error message: a closer look at the version magic strings suggests that, even with two configuration files which are exactly the same, a slight difference in the version magic could be possible, and it is sufficient to prevent insertion of the module into the kernel.
|
||||
That slight difference, namely the custom string which appears in the module's version magic and not in the kernel's one, is due to a modification with respect to the original, in the makefile that some distribution include.
|
||||
That slight difference, namely the custom string which appears in the module's version magic and not in the kernel's one, is due to a modification with respect to the original, in the makefile that some distributions include.
|
||||
Then, examine your \verb|Makefile|, and make sure that the specified version information matches exactly the one used for your current kernel.
|
||||
For example, you makefile could start as follows:
|
||||
|
||||
|
@ -606,7 +606,7 @@ int main(void)
|
|||
\end{code}
|
||||
|
||||
with \sh|gcc -Wall -o hello hello.c|.
|
||||
Run the exectable with \sh|strace ./hello|.
|
||||
Run the executable with \sh|strace ./hello|.
|
||||
Are you impressed?
|
||||
Every line you see corresponds to a system call.
|
||||
\href{https://strace.io/}{strace} is a handy program that gives you details about what system calls a program is making, including which call is made, what its arguments are and what it returns.
|
||||
|
@ -620,7 +620,7 @@ The 2nd man section is devoted to system calls (like \cpp|kill()| and \cpp|read(
|
|||
The 3rd man section is devoted to library calls, which you would probably be more familiar with (like \cpp|cosh()| and \cpp|random()|).
|
||||
|
||||
You can even write modules to replace the kernel's system calls, which we will do shortly.
|
||||
Crackers often make use of this sort of thing for backdoors or trojans, but you can write your own modules to do more benign things, like have the kernel write Tee hee, that tickles! everytime someone tries to delete a file on your system.
|
||||
Crackers often make use of this sort of thing for backdoors or trojans, but you can write your own modules to do more benign things, like have the kernel write Tee hee, that tickles! every time someone tries to delete a file on your system.
|
||||
|
||||
\subsection{User Space vs Kernel Space}
|
||||
\label{sec:user_kernl_space}
|
||||
|
@ -646,7 +646,7 @@ In large projects, effort must be made to remember reserved names, and to find w
|
|||
|
||||
When writing kernel code, even the smallest module will be linked against the entire kernel, so this is definitely an issue.
|
||||
The best way to deal with this is to declare all your variables as static and to use a well-defined prefix for your symbols.
|
||||
By convention, all kernel prefixes are lowercase. If you do not want to declare everything as static, another option is to declare a symbol table and register it with a kernel.
|
||||
By convention, all kernel prefixes are lowercase. If you do not want to declare everything as static, another option is to declare a symbol table and register it with the kernel.
|
||||
We will get to this later.
|
||||
|
||||
The file \verb|/proc/kallsyms| holds all the symbols that the kernel knows about and which are therefore accessible to your modules since they share the kernel's codespace.
|
||||
|
@ -938,7 +938,7 @@ In version \verb|a.b.c| of the kernel, the value of this macro would be \(2^{16}
|
|||
\section{The /proc File System}
|
||||
\label{sec:procfs}
|
||||
In Linux, there is an additional mechanism for the kernel and kernel modules to send information to processes --- the \verb|/proc| file system.
|
||||
Originally designed to allow easy access to information about processes (hence the name), it is now used by every bit of the kernel which has something interesting to report, such as \verb|/proc/modules| which provides the list of modules and \verb|/proc/meminfo| which stats memory usage statistics.
|
||||
Originally designed to allow easy access to information about processes (hence the name), it is now used by every bit of the kernel which has something interesting to report, such as \verb|/proc/modules| which provides the list of modules and \verb|/proc/meminfo| which gathers memory usage statistics.
|
||||
|
||||
The method to use the proc file system is very similar to the one used with device drivers --- a structure is created with all the information needed for the \verb|/proc| file, including pointers to any handler functions (in our case there is only one, the one called when somebody attempts to read from the \verb|/proc| file).
|
||||
Then, \cpp|init_module| registers the structure with the kernel and \cpp|cleanup_module| unregisters it.
|
||||
|
@ -956,7 +956,7 @@ The \verb|/proc/helloworld| is created when the module is loaded with the functi
|
|||
The return value is a \cpp|struct proc_dir_entry|, and it will be used to configure the file \verb|/proc/helloworld| (for example, the owner of this file).
|
||||
A null return value means that the creation has failed.
|
||||
|
||||
Each time, everytime the file \verb|/proc/helloworld| is read, the function \cpp|procfile_read| is called.
|
||||
Every time the file \verb|/proc/helloworld| is read, the function \cpp|procfile_read| is called.
|
||||
Two parameters of this function are very important: the buffer (the second parameter) and the offset (the fourth one).
|
||||
The content of the buffer will be returned to the application which read it (for example the \sh|cat| command).
|
||||
The offset is the current position in the file.
|
||||
|
@ -1076,7 +1076,7 @@ Of course, you can still use the same way as in the previous example.
|
|||
If you want more information, you can read this web page:
|
||||
|
||||
\begin{itemize}
|
||||
\item \url{http://lwn.net/Articles/22355/}
|
||||
\item \url{https://lwn.net/Articles/22355/}
|
||||
\item \url{https://kernelnewbies.org/Documents/SeqFileHowTo}
|
||||
\end{itemize}
|
||||
|
||||
|
@ -1138,7 +1138,7 @@ In the following example, this is implemented by \cpp|device_write|.
|
|||
This is not always enough.
|
||||
Imagine you had a serial port connected to a modem (even if you have an internal modem, it is still implemented from the CPU's perspective as a serial port connected to a modem, so you don't have to tax your imagination too hard).
|
||||
The natural thing to do would be to use the device file to write things to the modem (either modem commands or data to be sent through the phone line) and read things from the modem (either responses for commands or the data received through the phone line).
|
||||
However, this leaves open the question of what to do when you need to talk to the serial port itself, for example to send the rate at which data is sent and received.
|
||||
However, this leaves open the question of what to do when you need to talk to the serial port itself, for example to configure the rate at which data is sent and received.
|
||||
|
||||
The answer in Unix is to use a special function called \cpp|ioctl| (short for Input Output ConTroL).
|
||||
Every device can have its own \cpp|ioctl| commands, which can be read ioctl's (to send information from a process to the kernel), write ioctl's (to return information to a process), both or neither.
|
||||
|
@ -1153,8 +1153,7 @@ This header file should then be included both by the programs which will use ioc
|
|||
In the example below, the header file is chardev.h and the program which uses it is ioctl.c.
|
||||
|
||||
If you want to use ioctls in your own kernel modules, it is best to receive an official ioctl assignment, so if you accidentally get somebody else's ioctls, or if they get yours, you'll know something is wrong.
|
||||
% FIXME: use the right entry about ioctl assignment
|
||||
For more information, consult the kernel source tree at \src{Documentation/driver-api/ioctl.rst}.
|
||||
For more information, consult the kernel source tree at \src{Documentation/userspace-api/ioctl/ioctl-number.rst}.
|
||||
|
||||
\samplec{examples/chardev2.c}
|
||||
|
||||
|
@ -1173,7 +1172,7 @@ If you are not being sensible and using a virtual machine then this is where ker
|
|||
While writing the example below, I killed the \cpp|open()| system call.
|
||||
This meant I could not open any files, I could not run any programs, and I could not shutdown the system.
|
||||
I had to restart the virtual machine.
|
||||
No important files got anihilated, but if I was doing this on some live mission critical system then that could have been a possible outcome.
|
||||
No important files got annihilated, but if I was doing this on some live mission critical system then that could have been a possible outcome.
|
||||
To ensure you do not lose any files, even within a test environment, please run \sh|sync| right before you do the \sh|insmod| and the \sh|rmmod|.
|
||||
|
||||
Forget about \verb|/proc| files, forget about device files.
|
||||
|
@ -1223,12 +1222,12 @@ At first glance, it appears we could solve this particular problem by checking i
|
|||
When A is removed, it sees that the system call was changed to \cpp|B_open| so that it is no longer pointing to \cpp|A_open|, so it will not restore it to \cpp|sys_open| before it is removed from memory.
|
||||
Unfortunately, \cpp|B_open| will still try to call \cpp|A_open| which is no longer there, so that even without removing B the system would crash.
|
||||
|
||||
Note that all the related problems make syscall stealing unfeasiable for production use.
|
||||
Note that all the related problems make syscall stealing unfeasible for production use.
|
||||
In order to keep people from doing potential harmful things \cpp|sys_call_table| is no longer exported.
|
||||
This means, if you want to do something more than a mere dry run of this example, you will have to patch your current kernel in order to have \cpp|sys_call_table| exported.
|
||||
In the example directory you will find a README and the patch.
|
||||
As you can imagine, such modifications are not to be taken lightly.
|
||||
Do not try this on valueable systems (ie systems that you do not own - or cannot restore easily).
|
||||
Do not try this on valuable systems (ie systems that you do not own - or cannot restore easily).
|
||||
You will need to get the complete sourcecode of this guide as a tarball in order to get the patch and the README.
|
||||
Depending on your kernel version, you might even need to hand apply the patch.
|
||||
|
||||
|
@ -1341,7 +1340,7 @@ This may be all that is needed to avoid collisions in most cases.
|
|||
\subsection{Spinlocks}
|
||||
\label{sec:spinlock}
|
||||
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 will not noticably slow anything down from the user's point of view.
|
||||
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 will not noticeably slow anything down from the user's point of view.
|
||||
|
||||
The example here is \verb|"irq safe"| in that if interrupts happen during the lock then they will not be forgotten and will activate when the unlock happens, using the \cpp|flags| variable to retain their state.
|
||||
|
||||
|
@ -1463,7 +1462,7 @@ Of course, that requires that the kernel finds out which IRQ it really was after
|
|||
To take advantage of them requires handlers to be written in assembler, so they do not really fit into the kernel.
|
||||
They can be made to work similar to the others, but after that procedure, they are no longer any faster than "common" IRQs.
|
||||
SMP enabled kernels running on systems with more than one processor need to solve another truckload of problems.
|
||||
It is not enough to know if a certain IRQs has happend, it's also important for what CPU(s) it was for.
|
||||
It is not enough to know if a certain IRQs has happened, it's also important to know what CPU(s) it was for.
|
||||
People still interested in more details, might want to refer to "APIC" now.
|
||||
|
||||
This function receives the IRQ number, the name of the function, flags, a name for \verb|/proc/interrupts| and a parameter to be passed to the interrupt handler.
|
||||
|
@ -1534,7 +1533,7 @@ Here is an example of symmetrically encrypting a string using the AES algorithm
|
|||
\label{sec:device_model}
|
||||
Up to this point we have 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 standardized way to start, suspend and resume a device a device model was added.
|
||||
An example is show below, and you can use this as a template to add your own suspend, resume or other interface functions.
|
||||
An example is shown below, and you can use this as a template to add your own suspend, resume or other interface functions.
|
||||
|
||||
\samplec{examples/devicemodel.c}
|
||||
|
||||
|
@ -1542,10 +1541,9 @@ An example is show below, and you can use this as a template to add your own sus
|
|||
\label{sec:optimization}
|
||||
\subsection{Likely and Unlikely conditions}
|
||||
\label{sec:likely_unlikely}
|
||||
Sometimes you might want your code to run as quickly as possible, especially if it is handling an interrupt or doing something which might cause noticible latency.
|
||||
Sometimes you might want your code to run as quickly as possible, especially if it is handling an interrupt or doing something which might cause noticeable latency.
|
||||
If your code contains boolean conditions and if you know that the conditions are almost always likely to evaluate as either \cpp|true| or \cpp|false|,
|
||||
then you can allow the compiler to optimize for this using the \cpp|likely| and \cpp|unlikely| macros.
|
||||
|
||||
For example, when allocating memory you are almost always expecting this to succeed.
|
||||
|
||||
\begin{code}
|
||||
|
|
Loading…
Reference in New Issue
Block a user