📚 Kernel Module Parameters:
In Linux kernel programming, just like how command-line parameters (argc/argv
) give flexibility in C programs, kernel modules can also receive parameters at insertion time using module_param
macro. This enhances the module's versatility.
-
Advantages:
-
It grants adaptability, so a single driver/module can have multiple behaviors based on the supplied parameters.
-
You can configure things like I/O addresses, enabling/disabling debugging logs, setting operating modes, etc., without recompiling the module.
-
🖥️ Using module_param
Macro:
module_param
allows kernel modules to accept command-line parameters. Its usage is as follows:
-
name: Name of the variable. This is how the parameter will be recognized when you use
insmod
ormodprobe
. -
type: Type of the variable. The kernel provides predefined types to interpret the data correctly.
-
perm: Determines the permissions of the corresponding entry in sysfs. It can control who can view or modify this parameter once the module is loaded.
For instance, if you have a module parameter like this:
int my_address = 0;
module_param(my_address, int, S_IRUGO);
You can load the module and set this parameter with:
insmod my_module.ko my_address=5
Curiousity
❓ Question 1: What is the purpose of passing parameters to a kernel module?
📝 Answer: Passing parameters to a kernel module allows users to configure and adjust its behavior without modifying the code or recompiling. It offers flexibility, making it possible for the module to adapt to various situations, such as different I/O addresses, enabling debug logs, or setting different operational modes.
❓ Question 2: How does the perm
argument in module_param
affect the module parameter once it's loaded?
📝 Answer: The perm
argument in module_param
sets the permissions for the module parameter's entry in sysfs
. This determines who can read or modify the parameter.
- For instance, a permission of
S_IRUGO
allows any user to read the parameter, while a permission of0
means the parameter won't have a sysfs entry at all.
❓ Question 3: If a kernel module has a charp
parameter type, what kind of data is it expecting?
📝 Answer: A charp
parameter type in a kernel module expects a character pointer
, which typically means it's expecting a string.
🌟 In Simple Words:
Think of a kitchen blender 🍹. This blender has buttons for different modes like "Pulse", "Grind", "Blend", etc. You can also adjust the speed or decide whether to see the blending process (like a debug log). Instead of having different blenders for each task, you have one blender with various settings you can adjust.
Similarly, with module_param
, you have one kernel module, but you can adjust its behavior based on the "settings" (parameters) you provide when you load it. It's like choosing the blending mode and speed before hitting the start button!
📚 Passing Parameters to Kernel Modules:
-
Inserting Modules with Parameters: Using the
insmod
command, parameters can be passed to a module during insertion. For instance:sudo insmod ./argument.ko name="EMBED" loop_count=5
If you pass the wrong data type, for instance, a string to
loop_count
which expects an integer, you'll typically get an error. -
Checking Parameter Values of Loaded Modules: The
/sys
filesystem provides a mechanism to access details of modules. To find out the value of a parameter for a loaded module:cat /sys/modules/<module_name>/parameters/<parameter_name>
This works if the
perm
attribute in the module'smodule_param
macro is set to a non-zero value, allowing sysfs visibility.
-
Passing Parameters to Builtin Modules: Builtin modules (modules integrated into the kernel) receive parameters through the kernel command line during boot-up.
The syntax is:
<module_name>.<parameter_name>=value
-
Passing Parameters via Modprobe:
modprobe
is a tool that adds or removes modules, considering dependencies. It can be configured to pass parameters to modules by reading configurations from/etc/modprobe.conf
or files in/etc/modprobe.d/
.
Curiosity
❓ Question 1: What's the difference between a builtin module and an external module?
📝 Answer: A builtin module is integrated into the kernel binary, meaning it loads and runs automatically during system boot-up. An external module, on the other hand, is separate from the kernel binary and can be loaded or unloaded as needed using commands like insmod
or rmmod
.
❓ Question 2: What would happen if you pass an incorrect data type as a parameter value when loading a module using insmod
?
📝 Answer: If you pass an incorrect data type for a module parameter using insmod
, the kernel will typically throw an error indicating an unrecognized or inappropriate parameter value.
❓ Question 3: Why might you need to pass parameters to a module using modprobe
instead of insmod
?
📝 Answer: modprobe
is intelligent and can automatically handle module dependencies.
- When you load a module that relies on other modules,
modprobe
will load all necessary dependencies first. Passing parameters usingmodprobe
allows you to set configurations - while also ensuring all dependent modules are properly loaded.
🌟 In Simple Words:
Imagine building a toy 🚂 train set.
-
Inserting Modules with Parameters: It's like adding a new train car with specific features, like a horn sound or a light. If you try to add a feature the car doesn't support, it won't work!
-
Checking Parameter Values: This is similar to checking the settings of a specific train car, like seeing if its light is on or off.
-
Builtin Modules: Some train cars are always attached and come as part of the train set. Changing their features requires adjusting the main train controls.
-
Modprobe: Imagine a master control that knows exactly which cars need to be connected and in what order, and it can also set their features at the same time!
So, with these tools, you have the flexibility to customize your train set (or module) just the way you like! 🚂🛤️
📚 Passing Arguments to Kernel Modules:
When you load a kernel module using insmod
, you can also pass arguments to the module. These arguments typically modify the module's behavior at runtime.
For instance, consider that a module argument.ko
has a module parameter called name
. You can provide a value to this parameter while loading the module.
However, spaces in command line arguments can be interpreted as the start of a new argument. So, when you run:
insmod argument.ko name="Linux World"
The shell treats "Linux World" as two separate arguments because of the space. As a result, the kernel only recognizes name="Linux
and the second word World
is seen as an unknown parameter, thus causing the error in dmesg
.
Section 2: Technical Interview Questions & Answers
❓ Question 1: How can you pass a string with spaces as an argument to a kernel module using insmod
?
📝 Answer: To pass a string with spaces as an argument to a kernel module, you can enclose the entire argument (both the parameter name and its value) in single quotes. Like this:
insmod argument.ko 'name=Linux World'
❓ Question 2: Why do spaces in command line arguments cause issues when loading kernel modules with insmod
?
📝 Answer: Spaces are typically used to separate different command line arguments. So, when a space is encountered without any encapsulation (like quotes), the shell interprets it as the beginning of a new argument, leading to potential misinterpretation of the intended input.
❓ Question 3: If a kernel module does not recognize a passed parameter, how does the module usually handle it?
📝 Answer: If a kernel module doesn't recognize a passed parameter, it generally ignores it and may log an error or warning message in dmesg
indicating the unrecognized parameter.
Section 3: Simplify the concept
🌟 In Simple Words:
Imagine you're trying to send a text message to a friend, saying: "Let's meet at the park." But you accidentally send two separate messages: "Let's meet at" and "the park". Your friend might be confused because the second message doesn't make sense on its own.
Similarly, when you use insmod
and put a space in the argument without proper encapsulation, the command sees it as two separate messages. To make sure your full message (or command) is understood as intended, you need to wrap it up (in quotes) so it's received as one complete instruction.📱✉️
If we run the following command: "insmod argument.ko name="Linux World" We get the error "Unknown parameter 'World' ignored" in dmesg
📚 Handling Quotes in the Shell:
The shell (like bash
or sh
) has specific behaviors when it comes to interpreting quotes. Double quotes (" "
) allow for variable expansion and command substitution, but they don't prevent word splitting (which is caused by spaces). On the other hand, single quotes (' '
) prevent both variable expansion and word splitting.
When you use:
insmod argument.ko name='"Linux World"'
The inner double quotes are preserved by the outer single quotes. This results in the entire string, including the double quotes, being passed to insmod
as one argument. insmod
then gets the argument as name="Linux World"
, preserving the space.
Curiousity
❓ Question 1: What is the difference between using double quotes and single quotes in the shell?
📝 Answer: In the shell, double quotes allow for variable expansion and command substitution but do not prevent word splitting due to spaces. Single quotes, on the other hand, prevent both variable expansion and word splitting, treating everything between them as a literal string.
❓ Question 2: How would the shell interpret the following command? echo '$HOME and "Hello World"'
📝 Answer: The shell would print the literal string $HOME and "Hello World"
, without expanding $HOME
to the user's home directory because everything inside the single quotes is treated as a literal string.
❓ Question 3: Why might you want to use both single and double quotes together in a shell command, as seen in the insmod
example?
📝 Answer: Using both single and double quotes together can be helpful when you want to preserve certain characters (like spaces) using double quotes, but also ensure that the entire argument is treated as a single unit by the shell. The outer single quotes ensure the entire string is passed as one argument, while the inner double quotes preserve the structure of the string.
🌟 In Simple Words:
Imagine you're mailing a package 📦. You place an item (let's say a toy) inside a smaller box (representing the double quotes). You then put this smaller box inside a larger box (representing the single quotes) for extra protection.
In this scenario, the small box (double quotes) makes sure the toy stays intact, while the large box (single quotes) ensures everything stays together during delivery. Similarly, in the command, the inner double quotes keep the space intact in "Linux World", while the outer single quotes ensure the entire string is passed as one piece to insmod
. 📬🎁