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:
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!
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
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
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 portOUT
: Write to a portINS/INSB
: Input string from port/Input byte string from portINS/INSW
: Input string from port/Input word string from portINS/INSD
: Input string from port/Input doubleword
string from portOUTS/OUTSB
: Output string to port/Output byte string to portOUTS/OUTSW
: Output string to port/Output word string to portOUTS/OUTSD
: Output string to port/Output doubleword
string to portHowever, 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