You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -707,17 +708,21 @@ \subsection{Building modules for a precompiled kernel}
707
708
\section{Preliminaries}
708
709
\subsection{How modules begin and end}
709
710
\label{sec:module_init_exit}
710
-
A program usually begins with a \cpp|main()| function, executes a bunch of instructions and terminates upon completion of those instructions.
711
-
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.
712
-
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.
713
-
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.
714
-
715
-
All modules end by calling either \cpp|cleanup_module| or the function you specify with the \cpp|module_exit| call.
716
-
This is the exit function for modules; it undoes whatever entry function did.
717
-
It unregisters the functionality that the entry function registered.
718
-
719
-
Every module must have an entry function and an exit function.
720
-
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.
711
+
A typical program starts with a |main()| function, executes a series of instructions,
712
+
and terminates after completing these instructions.
713
+
Kernel modules, however, follow a different pattern.
714
+
A module always begins with either the \cpp|init_module| function or a function designated by the \cpp|module_init| call.
715
+
This function acts as the module's entry point,
716
+
informing the kernel of the module's functionalities and preparing the kernel to utilize the module's functions when necessary.
717
+
After performing these tasks, the entry function returns, and the module remains inactive until the kernel requires its code.
718
+
719
+
All modules conclude by invoking either \cpp|cleanup_module| or a function specified through the \cpp|module_exit |call.
720
+
This serves as the module's exit function, reversing the actions of the entry function by unregistering the previously registered functionalities.
721
+
722
+
It is mandatory for every module to have both an entry and an exit function.
723
+
While there are multiple methods to define these functions, the terms ``entry function'' and ``exit function'' are generally used.
724
+
However, they may occasionally be referred to as \cpp|init_module| and \cpp|cleanup_module|,
725
+
which are understood to mean the same.
721
726
722
727
\subsection{Functions available to modules}
723
728
\label{sec:avail_func}
@@ -768,13 +773,16 @@ \subsection{Functions available to modules}
768
773
769
774
\subsection{User Space vs Kernel Space}
770
775
\label{sec:user_kernl_space}
771
-
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.
772
-
Programs often compete for the same resource. As I just saved this document, updatedb started updating the locate database.
773
-
My vim session and updatedb are both using the hard drive concurrently.
774
-
The kernel needs to keep things orderly, and not give users access to resources whenever they feel like it.
775
-
To this end, a CPU can run in different modes.
776
-
Each mode gives a different level of freedom to do what you want on the system.
777
-
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''.
776
+
The kernel primarily manages access to resources, be it a video card, hard drive, or memory.
777
+
Programs frequently vie for the same resources.
778
+
For instance, as a document is saved, updatedb might commence updating the locate database.
779
+
Sessions in editors like vim and processes like updatedb can simultaneously utilize the hard drive.
780
+
The kernel's role is to maintain order, ensuring that users do not access resources indiscriminately.
781
+
782
+
To manage this, CPUs operate in different modes, each offering varying levels of system control.
783
+
The Intel 80386 architecture, for example, featured four such modes, known as rings.
784
+
Unix, however, utilizes only two of these rings: the highest ring (ring 0, also known as ``supervisor mode'',
785
+
where all actions are permissible) and the lowest ring, referred to as ``user mode''.
778
786
779
787
Recall the discussion about library functions vs system calls.
780
788
Typically, you use a library function in user mode.
@@ -812,10 +820,11 @@ \subsection{Code space}
812
820
And if you start writing over data because of an off-by-one error, then you're trampling on kernel data (or code).
813
821
This is even worse than it sounds, so try your best to be careful.
814
822
815
-
By the way, I would like to point out that the above discussion is true for any operating system which uses a monolithic kernel.
816
-
This is not quite the same thing as \emph{"building all your modules into the kernel"}, although the idea is the same.
817
-
There are things called microkernels which have modules which get their own codespace.
818
-
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.
823
+
It should be noted that the aforementioned discussion applies to any operating system utilizing a monolithic kernel.
824
+
This concept differs slightly from \emph{``building all your modules into the kernel''},
825
+
although the underlying principle is similar.
826
+
In contrast, there are microkernels, where modules are allocated their own code space.
827
+
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.
819
828
820
829
\subsection{Device Drivers}
821
830
\label{sec:device_drivers}
@@ -872,14 +881,14 @@ \subsection{Device Drivers}
872
881
However, when creating a device file for testing purposes, it is probably OK to place it in your working directory where you compile the kernel module.
873
882
Just be sure to put it in the right place when you're done writing the device driver.
874
883
875
-
I would like to make a few last points which are implicit from the above discussion, but I would like to make them explicit just in case.
876
-
When a device file is accessed, the kernel uses the major number of the file to determine which driver should be used to handle the access.
877
-
This means that the kernel doesn't really need to use or even know about the minor number.
878
-
The driver itself is the only thing that cares about the minor number.
879
-
It uses the minor number to distinguish between different pieces of hardware.
884
+
A few final points, although implicit in the previous discussion, are worth stating explicitly for clarity.
885
+
When a device file is accessed, the kernel utilizes the file's major number to identify the appropriate driver for handling the access.
886
+
This indicates that the kernel does not necessarily rely on or need to be aware of the minor number.
887
+
It is the driver that concerns itself with the minor number, using it to differentiate between various pieces of hardware.
880
888
881
-
By the way, when I say \emph{"hardware"}, I mean something a bit more abstract than a PCI card that you can hold in your hand.
882
-
Look at these two device files:
889
+
It is important to note that when referring to \emph{``hardware''},
890
+
the term is used in a slightly more abstract sense than just a physical PCI card that can be held in hand.
891
+
Consider the following two device files:
883
892
884
893
\begin{verbatim}
885
894
$ ls -l /dev/sda /dev/sdb
@@ -1408,12 +1417,12 @@ \section{System Calls}
1408
1417
But what if you want to do something unusual, to change the behavior of the system in some way?
1409
1418
Then, you are mostly on your own.
1410
1419
1411
-
If you are not being sensible and using a virtual machine then this is where kernel programming can become hazardous.
1412
-
While writing the example below, I killed the \cpp|open()| system call.
1413
-
This meant I could not open any files, I could not run any programs, and I could not shutdown the system.
1414
-
I had to restart the virtual machine.
1415
-
No important files got annihilated, but if I was doing this on some live missioncritical system then that could have been a possible outcome.
1416
-
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|.
1420
+
Should one choose not to use a virtual machine, kernel programming can become risky.
1421
+
For example, while writing the code below, the \cpp|open()| system call was inadvertently disrupted.
1422
+
This resulted in an inability to open any files, run programs, or shut down the system, necessitating a restart of the virtual machine.
1423
+
Fortunately, no critical files were lost in this instance.
1424
+
However, if such modifications were made on a live, mission-critical system, the consequences could be severe.
1425
+
To mitigate the risk of file loss, even in a test environment, it is advised to execute \sh|sync| right before using \sh|insmod| and \sh|rmmod|.
1417
1426
1418
1427
Forget about \verb|/proc| files, forget about device files.
0 commit comments