mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-13 20:12:26 +00:00
67 lines
2.9 KiB
Markdown
67 lines
2.9 KiB
Markdown
# Introduction
|
|
|
|
There are things which are hard to do from regular user programs such as directly talking to hardware.
|
|
|
|
Some operations can be done via system calls, but if you want flexibility and speed, using the kernel ring is fundamental
|
|
|
|
However:
|
|
|
|
- it would be very complicated to recompile the kernel and reboot every time you make some modification
|
|
- the kernel would be huge if it were to support all possible hardware
|
|
|
|
Modules overcome those two problems exactly because they can be loaded into the kernel *while it is running* and use symbols that the kernel chooses to export TODO which
|
|
|
|
It then runs in the same address space as the kernel and with the same permissions as the kernel (basically do anything)
|
|
|
|
Compiled modules are special object files that have a `.ko` extension instead of `.o` they also contain module specific metadata
|
|
|
|
Device drivers (programs that enables the computer to talk to hardware) are one specific type of kernel modules
|
|
|
|
Two devices can map to the same hardware!
|
|
|
|
## Stable kernel interface
|
|
|
|
Kernel modules can use any internal interface of the kernel, although some are more visible than others.
|
|
|
|
But there is no stable kernel API for modules: if you don't add your driver to the kernel tree, it can break any time: <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/stable_api_nonsense.txt?id=v4.0>
|
|
|
|
## Configuration files
|
|
|
|
If file it gets read, if dir, all files in dir get read:
|
|
|
|
sudo ls /etc/modprobe.d
|
|
sudo ls /etc/modprobe.conf
|
|
|
|
Modules loaded at boot:
|
|
|
|
sudo cat /etc/modules
|
|
|
|
## Hardware communication
|
|
|
|
Talking to hardware always comes down to writing bytes in specific registers at a given memory addresses.
|
|
|
|
Some processors implement a single address space for memory and other hardware devices, and others do not.
|
|
|
|
However, since x86 is the most popular and it separates address spaces, every architecture must at least mimic this separation.
|
|
|
|
On x86, the following specialized instructions exist for port IO:
|
|
|
|
- `IN`: Read from a port
|
|
- `OUT`: Write to a port
|
|
- `INS/INSB`: Input string from port/Input byte string from port
|
|
- `INS/INSW`: Input string from port/Input word string from port
|
|
- `INS/INSD`: Input string from port/Input `doubleword` string from port
|
|
- `OUTS/OUTSB`: Output string to port/Output byte string to port
|
|
- `OUTS/OUTSW`: Output string to port/Output word string to port
|
|
- `OUTS/OUTSD`: Output string to port/Output `doubleword` string to port
|
|
|
|
However, you should avoid using those instructions directly in your device driver code since Linux functions abstract over multiple architectures (when possible) making your code more portable.
|
|
|
|
Those instructions cannot be used from an user space program since the kernel prevents those from accessing hardware directly.
|
|
|
|
The memory space for non-memory locations is called I/O ports or I/O space.
|
|
|
|
To use a port, you must first reserve it. To see who reserved what:
|
|
|
|
sudo cat /proc/ioports
|