mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-25 19:21:35 +01:00
0
This commit is contained in:
66
introduction.md
Normal file
66
introduction.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user