Skip to content

Commit 2d36821

Browse files
committed
Introduce \src to generate Linux kernel source hyperlinks
The new command \src was introduced for preliminary hyperlink generation which points to Linux kernel source code. At present, stable/linux.git was referred: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git We might switch to specific LTS kernels once requested.
1 parent da3dd34 commit 2d36821

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

lib/kernelsrc.tex

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
\newcommand*{\src}[2][]{\href{https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/#2}%
2+
{\ifthenelse{\equal{#1}{}}{#2}{#1}}}

lkmpg.tex

+22-20
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
\usepackage{graphicx}
66
\usepackage{fancyhdr}
77
\usepackage{xparse}
8+
\usepackage{ifthen}
89

910
% tikz settings
1011
\usepackage{tikz}
@@ -33,6 +34,7 @@
3334
}
3435

3536
\input{lib/codeblock}
37+
\input{lib/kernelsrc}
3638

3739
\author{Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang}
3840
\date{\today}
@@ -284,17 +286,17 @@ \subsection{The Simplest Module}
284286
In the beginning there was \cpp|printk|, usually followed by a priority such as \cpp|KERN_INFO| or \cpp|KERN_DEBUG|.
285287
More recently this can also be expressed in abbreviated form using a set of print macros, such as \cpp|pr_info| and \cpp|pr_debug|.
286288
This just saves some mindless keyboard bashing and looks a bit neater.
287-
They can be found within \verb|include/linux/printk.h|.
289+
They can be found within \src{include/linux/printk.h}.
288290
Take time to read through the available priority macros.
289291

290292
\item About Compiling.
291293
Kernel modules need to be compiled a bit differently from regular userspace apps.
292294
Former kernel versions required us to care much about these settings, which are usually stored in Makefiles.
293295
Although hierarchically organized, many redundant settings accumulated in sublevel Makefiles and made them large and rather difficult to maintain.
294296
Fortunately, there is a new way of doing these things, called kbuild, and the build process for external loadable modules is now fully integrated into the standard kernel build mechanism.
295-
To learn more on how to compile modules which are not part of the official kernel (such as all the examples you will find in this guide), see file \verb|Documentation/kbuild/modules.rst|.
297+
To learn more on how to compile modules which are not part of the official kernel (such as all the examples you will find in this guide), see file \src{Documentation/kbuild/modules.rst}.
296298

297-
Additional details about Makefiles for kernel modules are available in \verb|Documentation/kbuild/makefiles.rst|. Be sure to read this and the related files before starting to hack Makefiles. It will probably save you lots of work.
299+
Additional details about Makefiles for kernel modules are available in \src{Documentation/kbuild/makefiles.rst}. Be sure to read this and the related files before starting to hack Makefiles. It will probably save you lots of work.
298300

299301
\begin{quote}
300302
Here is another exercise for the reader.
@@ -307,7 +309,7 @@ \subsection{The Simplest Module}
307309
\subsection{Hello and Goodbye}
308310
\label{hello_n_goodbye}
309311
In early kernel versions you had to use the \cpp|init_module| and \cpp|cleanup_module| functions, as in the first hello world example, but these days you can name those anything you want by using the \cpp|module_init| and \cpp|module_exit| macros.
310-
These macros are defined in \verb|include/linux/init.h|.
312+
These macros are defined in \src{include/linux/init.h}.
311313
The only requirement is that your init and cleanup functions must be defined before calling the those macros, otherwise you'll get compilation errors.
312314
Here is an example of this technique:
313315

@@ -326,7 +328,7 @@ \subsection{Hello and Goodbye}
326328
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
327329
\end{code}
328330

329-
Now have a look at \verb|drivers/char/Makefile| for a real world example.
331+
Now have a look at \src{drivers/char/Makefile} for a real world example.
330332
As you can see, some things get hardwired into the kernel (\verb|obj-y|) but where are all those \verb|obj-m| gone?
331333
Those familiar with shell scripts will easily be able to spot them.
332334
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.
@@ -344,7 +346,7 @@ \subsection{The \_\_init and \_\_exit Macros}
344346
The \cpp|__exit| macro causes the omission of the function when the module is built into the kernel, and like \cpp|__init|, has no effect for loadable modules.
345347
Again, if you consider when the cleanup function runs, this makes complete sense; built-in drivers do not need a cleanup function, while loadable modules do.
346348

347-
These macros are defined in \verb|include/linux/init.h| and serve to free up kernel memory.
349+
These macros are defined in \src{include/linux/init.h} and serve to free up kernel memory.
348350
When you boot your kernel and see something like Freeing unused kernel memory: 236k freed, this is precisely what the kernel is freeing.
349351

350352
\samplec{examples/hello-3.c}
@@ -361,7 +363,7 @@ \subsection{Licensing and Module Documentation}
361363

362364
You can use a few macros to indicate the license for your module.
363365
Some examples are "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MIT/GPL", "Dual MPL/GPL" and "Proprietary".
364-
They are defined within \verb|include/linux/module.h|.
366+
They are defined within \src{include/linux/module.h}.
365367

366368
To reference what license you're using a macro is available called \cpp|MODULE_LICENSE|.
367369
This and a few other macros describing the module are illustrated in the below example.
@@ -372,7 +374,7 @@ \subsection{Passing Command Line Arguments to a Module}
372374
\label{modparam}
373375
Modules can take command line arguments, but not with the argc/argv you might be used to.
374376

375-
To allow arguments to be passed to your module, declare the variables that will take the values of the command line arguments as global and then use the \cpp|module_param()| macro, (defined in \verb|include/linux/moduleparam.h|) to set the mechanism up.
377+
To allow arguments to be passed to your module, declare the variables that will take the values of the command line arguments as global and then use the \cpp|module_param()| macro, (defined in \src{include/linux/moduleparam.h}) to set the mechanism up.
376378
At runtime, \sh|insmod| will fill the variables with any command line arguments that are given, like \sh|insmod ./mymodule.ko myvariable=5|.
377379
The variable declarations and macros should be placed at the beginning of the module for clarity.
378380
The example code should clear up my admittedly lousy explanation.
@@ -712,7 +714,7 @@ \subsection{Device Drivers}
712714
crw-rw---- 1 root dial 4, 67 Jul 5 2000 /dev/ttyS3
713715
\end{verbatim}
714716

715-
If you want to see which major numbers have been assigned, you can look at \verb|Documentation/admin-guide/devices.txt|.
717+
If you want to see which major numbers have been assigned, you can look at \src{Documentation/admin-guide/devices.txt}.
716718

717719
When the system was installed, all of those device files were created by the \sh|mknod| command.
718720
To create a new char device named \verb|coffee| with major/minor number 12 and 2, simply do \sh|mknod /dev/coffee c 12 2|.
@@ -744,7 +746,7 @@ \section{Character Device drivers}
744746
\label{sec:chardev}
745747
\subsection{The file\_operations Structure}
746748
\label{sec:file_operations}
747-
The \cpp|file_operations| structure is defined in \verb|include/linux/fs.h|, and holds pointers to functions defined by the driver that perform various operations on the device.
749+
The \cpp|file_operations| structure is defined in \src{include/linux/fs.h}, and holds pointers to functions defined by the driver that perform various operations on the device.
748750
Each field of the structure corresponds to the address of some function defined by the driver to handle a requested operation.
749751

750752
For example, every character driver needs to define a function that reads from the device.
@@ -831,7 +833,7 @@ \subsection{The file\_operations Structure}
831833
\subsection{The file structure}
832834
\label{sec:file_struct}
833835

834-
Each device is represented in the kernel by a file structure, which is defined in \verb|include/linux/fs.h|.
836+
Each device is represented in the kernel by a file structure, which is defined in \src{include/linux/fs.h}.
835837
Be aware that a file is a kernel level structure and never appears in a user space program.
836838
It is not the same thing as a \cpp|FILE|, which is defined by glibc and would never appear in a kernel space function.
837839
Also, its name is a bit misleading; it represents an abstract open `file', not a file on a disk, which is represented by a structure named inode.
@@ -864,7 +866,7 @@ \subsection{Registering A Device}
864866
That is because the kernel doesn't care about the minor number; only our driver uses it.
865867

866868
Now the question is, how do you get a major number without hijacking one that's already in use?
867-
The easiest way would be to look through \verb|Documentation/admin-guide/devices.txt| and pick an unused one.
869+
The easiest way would be to look through \src{Documentation/admin-guide/devices.txt} and pick an unused one.
868870
That is a bad way of doing things because you will never be sure if the number you picked will be assigned later.
869871
The answer is that you can ask the kernel to assign you a dynamic major number.
870872

@@ -888,8 +890,8 @@ \subsection{Unregistering A Device}
888890
However, there is a counter which keeps track of how many processes are using your module.
889891
You can see what its value is by looking at the 3rd field of \verb|/proc/modules|.
890892
If this number isn't zero, \sh|rmmod| will fail.
891-
Note that you do not have to check the counter from within \cpp|cleanup_module| because the check will be performed for you by the system call \cpp|sys_delete_module|, defined in \verb|include/linux/syscalls.h|.
892-
You should not use this counter directly, but there are functions defined in \verb|include/linux/module.h| which let you increase, decrease and display this counter:
893+
Note that you do not have to check the counter from within \cpp|cleanup_module| because the check will be performed for you by the system call \cpp|sys_delete_module|, defined in \src{include/linux/syscalls.h}.
894+
You should not use this counter directly, but there are functions defined in \src{include/linux/module.h} which let you increase, decrease and display this counter:
893895

894896
\begin{itemize}
895897
\item \cpp|try_module_get(THIS_MODULE)|: Increment the use count.
@@ -966,7 +968,7 @@ \section{The /proc File System}
966968

967969
\subsection{The proc\_ops Structure}
968970
\label{sec:proc_ops}
969-
The \cpp|proc_ops| structure is defined in \verb|include/linux/proc_fs.h| in Linux v5.6+.
971+
The \cpp|proc_ops| structure is defined in \src{include/linux/proc\_fs.h} in Linux v5.6+.
970972
In older kernels, it used \cpp|file_operations| for custom hooks in \verb|/proc| file system, but it contains some members that are unnecessary in VFS, and every time VFS expands \cpp|file_operations| set, \verb|/proc| code comes bloated.
971973
On the other hand, not only the space, but also some operations were saved by this structure to improve its performance.
972974
For example, the file which never disappears in \verb|/proc| can set the \cpp|proc_flag| as \cpp|PROC_ENTRY_PERMANENT| to save 2 atomic ops, 1 allocation, 1 free in per open/read/close sequence.
@@ -1074,7 +1076,7 @@ \subsection{Manage /proc file with seq\_file}
10741076
\item \url{https://kernelnewbies.org/Documents/SeqFileHowTo}
10751077
\end{itemize}
10761078

1077-
You can also read the code of \verb|fs/seq_file.c| in the linux kernel.
1079+
You can also read the code of \src{fs/seq\_file.c} in the linux kernel.
10781080

10791081
\section{sysfs: Interacting with your module}
10801082
\label{sec:sysfs}
@@ -1148,7 +1150,7 @@ \section{Talking To Device Files}
11481150

11491151
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.
11501152
% FIXME: use the right entry about ioctl assignment
1151-
For more information, consult the kernel source tree at \verb|Documentation/driver-api/ioctl.rst|.
1153+
For more information, consult the kernel source tree at \src{Documentation/driver-api/ioctl.rst}.
11521154

11531155
\samplec{examples/chardev2.c}
11541156

@@ -1275,7 +1277,7 @@ \subsection{Sleep}
12751277

12761278
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.
12771279
Such processes use the \cpp|O_NONBLOCK| flag when opening the file.
1278-
The kernel is supposed to respond by returning with the error code \cpp|-EAGAIN| from operations which would otherwise block, such as opening the file in this example. The program \verb|cat_nonblock|, available in the \textit{examples/other} directory for this chapter, can be used to open a file with \cpp|O_NONBLOCK|.
1280+
The kernel is supposed to respond by returning with the error code \cpp|-EAGAIN| from operations which would otherwise block, such as opening the file in this example. The program \sh|cat_nonblock|, available in the \verb|examples/other| directory, can be used to open a file with \cpp|O_NONBLOCK|.
12791281

12801282
\begin{verbatim}
12811283
$ sudo insmod sleep.ko
@@ -1386,7 +1388,7 @@ \subsection{Flashing keyboard LEDs}
13861388
If none of the examples in this chapter fit your debugging needs there might yet be some other tricks to try.
13871389
Ever wondered what \cpp|CONFIG_LL_DEBUG| in make menuconfig is good for?
13881390
If you activate that you get low level access to the serial port.
1389-
While this might not sound very powerful by itself, you can patch \verb|kernel/printk.c| or any other essential syscall to print ASCII characters, thus makeing it possible to trace virtually everything what your code does over a serial line.
1391+
While this might not sound very powerful by itself, you can patch \src{kernel/printk.c} or any other essential syscall to print ASCII characters, thus makeing it possible to trace virtually everything what your code does over a serial line.
13901392
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.
13911393
Logging over a netconsole might also be worth a try.
13921394

@@ -1567,7 +1569,7 @@ \subsection{Disabling interrupts}
15671569

15681570
\section{Where To Go From Here?}
15691571
\label{sec:where_to_go}
1570-
For people seriously interested in kernel programming, I recommend \href{https://kernelnewbies.org}{kernelnewbies.org} and the \verb|Documentation| subdirectory within the kernel source code which is not always easy to understand but can be a starting point for further investigation.
1572+
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.
15711573
Also, as Linus Torvalds said, the best way to learn the kernel is to read the source code yourself.
15721574

15731575
If you are 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.

0 commit comments

Comments
 (0)