more detailed steps for \href{https://wiki.debian.org/SecureBoot}{SecureBoot} can be explored and followed.
\end{enumerate}
-\section{Headers}
+\chapter{Headers}
\label{sec:headers}
- Before you can build anything you'll need to install the header files for your kernel.
+ Before building anything, it is necessary to install the header files for the kernel.
On Ubuntu/Debian GNU/Linux:
\begin{codebash}
\label{sec:examples}
All the examples from this document are available within the \verb|examples| subdirectory.
- If there are any compile errors then you might have a more recent kernel version or need to install the corresponding kernel header files.
+ Should compile errors occur, it may be due to a more recent kernel version being in use,
+ or there might be a need to install the corresponding kernel header files.
-\section{Hello World}
+\chapter{Hello World}
\label{sec:helloworld}
-\subsection{The Simplest Module}
+\section{The Simplest Module}
\label{sec:org2d3e245}
- Most people learning programming start out with some sort of "\emph{hello world}" example.
- I don't know what happens to people who break with this tradition, but I think it is safer not to find out.
- We will start with a series of hello world programs that demonstrate the different aspects of the basics of writing a kernel module.
+ Most individuals beginning their programming journey typically start with some variant of a \emph{hello world} example.
+ It is unclear what the outcomes are for those who deviate from this tradition, but it seems prudent to adhere to it.
+ The learning process will begin with a series of hello world programs that illustrate various fundamental aspects of writing a kernel module.
- Here is the simplest module possible.
+ Presented next is the simplest possible module.
Make a test directory:
\begin{codebash}
If you do not desire to actually compile the kernel, you can interrupt the build process (CTRL-C) just after the SPLIT line, because at that time, the files you need are ready.
Now you can turn back to the directory of your module and compile it: It will be built exactly according to your current kernel settings, and it will load into it without any errors.
-\section{Preliminaries}
-\subsection{How modules begin and end}
+\chapter{Preliminaries}
+\section{How modules begin and end}
\label{sec:module_init_exit}
- A program usually begins with a \cpp|main()| function, executes a bunch of instructions and terminates upon completion of those instructions.
- Kernel modules work a bit differently. A module always begin with either the \cpp|init_module| or the function you specify with \cpp|module_init| call.
- This is the entry function for modules; it tells the kernel what functionality the module provides and sets up the kernel to run the module's functions when they are needed.
- Once it does this, entry function returns and the module does nothing until the kernel wants to do something with the code that the module provides.
-
- All modules end by calling either \cpp|cleanup_module| or the function you specify with the \cpp|module_exit| call.
- This is the exit function for modules; it undoes whatever entry function did.
- It unregisters the functionality that the entry function registered.
-
- Every module must have an entry function and an exit function.
- Since there's more than one way to specify entry and exit functions, I will try my best to use the terms ``entry function'' and ``exit function'', but if I slip and simply refer to them as \cpp|init_module| and \cpp|cleanup_module|, I think you will know what I mean.
+ A typical program starts with a |main()| function, executes a series of instructions,
+ and terminates after completing these instructions.
+ Kernel modules, however, follow a different pattern.
+ A module always begins with either the \cpp|init_module| function or a function designated by the \cpp|module_init| call.
+ This function acts as the module's entry point,
+ informing the kernel of the module's functionalities and preparing the kernel to utilize the module's functions when necessary.
+ After performing these tasks, the entry function returns, and the module remains inactive until the kernel requires its code.
+
+ All modules conclude by invoking either \cpp|cleanup_module| or a function specified through the \cpp|module_exit |call.
+ This serves as the module's exit function, reversing the actions of the entry function by unregistering the previously registered functionalities.
+
+ It is mandatory for every module to have both an entry and an exit function.
+ While there are multiple methods to define these functions, the terms ``entry function'' and ``exit function'' are generally used.
+ However, they may occasionally be referred to as \cpp|init_module| and \cpp|cleanup_module|,
+ which are understood to mean the same.
-\subsection{Functions available to modules}
+\section{Functions available to modules}
\label{sec:avail_func}
Programmers use functions they do not define all the time.
A prime example of this is \cpp|printf()|.
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! every time someone tries to delete a file on your system.
-\subsection{User Space vs Kernel Space}
+\section{User Space vs Kernel Space}
\label{sec:user_kernl_space}
- A kernel is all about access to resources, whether the resource in question happens to be a video card, a hard drive or even memory.
- Programs often compete for the same resource. As I just saved this document, updatedb started updating the locate database.
- My vim session and updatedb are both using the hard drive concurrently.
- The kernel needs to keep things orderly, and not give users access to resources whenever they feel like it.
- To this end, a CPU can run in different modes.
- Each mode gives a different level of freedom to do what you want on the system.
- The Intel 80386 architecture had 4 of these modes, which were called rings. Unix uses only two rings; the highest ring (ring 0, also known as ``supervisor mode'' where everything is allowed to happen) and the lowest ring, which is called ``user mode''.
+ The kernel primarily manages access to resources, be it a video card, hard drive, or memory.
+ Programs frequently vie for the same resources.
+ For instance, as a document is saved, updatedb might commence updating the locate database.
+ Sessions in editors like vim and processes like updatedb can simultaneously utilize the hard drive.
+ The kernel's role is to maintain order, ensuring that users do not access resources indiscriminately.
+
+ To manage this, CPUs operate in different modes, each offering varying levels of system control.
+ The Intel 80386 architecture, for example, featured four such modes, known as rings.
+ Unix, however, utilizes only two of these rings: the highest ring (ring 0, also known as ``supervisor mode'',
+ where all actions are permissible) and the lowest ring, referred to as ``user mode''.
Recall the discussion about library functions vs system calls.
Typically, you use a library function in user mode.
And if you start writing over data because of an off-by-one error, then you're trampling on kernel data (or code).
This is even worse than it sounds, so try your best to be careful.
- By the way, I would like to point out that the above discussion is true for any operating system which uses a monolithic kernel.
- This is not quite the same thing as \emph{"building all your modules into the kernel"}, although the idea is the same.
- There are things called microkernels which have modules which get their own codespace.
- The \href{https://www.gnu.org/software/hurd/}{GNU Hurd} and the \href{https://fuchsia.dev/fuchsia-src/concepts/kernel}{Zircon kernel} of Google Fuchsia are two examples of a microkernel.
+ It should be noted that the aforementioned discussion applies to any operating system utilizing a monolithic kernel.
+ This concept differs slightly from \emph{``building all your modules into the kernel''},
+ although the underlying principle is similar.
+ In contrast, there are microkernels, where modules are allocated their own code space.
+ Two notable examples of microkernels include the \href{https://www.gnu.org/software/hurd/}{GNU Hurd} and the \href{https://fuchsia.dev/fuchsia-src/concepts/kernel}{Zircon kernel} of Google's Fuchsia.
-\subsection{Device Drivers}
+\section{Device Drivers}
\label{sec:device_drivers}
One class of module is the device driver, which provides functionality for hardware like a serial port.
On Unix, each piece of hardware is represented by a file located in \verb|/dev| named a device file which provides the means to communicate with the hardware.
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.
- \samplec{examples/syscall.c}
+ \samplec{examples/syscall-steal.c}
-\section{Blocking Processes and threads}
+\chapter{Blocking Processes and threads}
\label{sec:blocking_process_thread}
-\subsection{Sleep}
+\section{Sleep}
\label{sec:sleep}
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: "\emph{Not right now, I'm busy. Go away!}".
\label{sec:disabling_interrupts}
You might need to do this for a short time and that is OK, but if you do not enable them afterwards, your system will be stuck and you will have to power it off.
-\section{Where To Go From Here?}
+\chapter{Where To Go From Here?}
\label{sec:where_to_go}
- For people seriously interested in kernel programming, I recommend \href{https://kernelnewbies.org}{kernelnewbies.org} and the \src{Documentation} subdirectory within the kernel source code which is not always easy to understand but can be a starting point for further investigation.
- Also, as Linus Torvalds said, the best way to learn the kernel is to read the source code yourself.
-
- If you would like to contribute to this guide or notice anything glaringly wrong, please create an issue at \url{https://github.com/sysprog21/lkmpg}.
- Your pull requests will be appreciated.
+ For those deeply interested in kernel programming,
+ \href{https://kernelnewbies.org}{kernelnewbies.org} and the \src{Documentation} subdirectory within the kernel source code are highly recommended.
+ Although the latter may not always be straightforward, it serves as a valuable initial step for further exploration.
+ Echoing Linus Torvalds' perspective, the most effective method to understand the kernel is through personal examination of the source code.
+
+ Contributions to this guide are welcome, especially if there are any significant inaccuracies identified.
+ To contribute or report an issue, please initiate an issue at \url{https://github.com/sysprog21/lkmpg}.
+ Pull requests are greatly appreciated.
Happy hacking!
\end{document}