This project is the 2nd project in the Kernel specialization of 42 School. It is a series of challenges inspired by Eudyptula.
Instructions:
- Download Linus' latest git tree from git.kernel.org, build, compile and boot it.
- Enable CONFIG_LOCALVERSION_AUTO=y
Notes:
CONFIG_LOCALVERSION
andCONFIG_LOCALVERSION_AUTO
in the.config
file andEXTRAVERSION
in theMakefile
are used to specify version information for the kernel.- With the
CONFIG_LOCALVERSION
option, you can set a custom string that will be appended to the kernel version (like theEXTRAVERSION
in theMakefile
), allowing you to identify custom builds. - You can find the
CONFIG_LOCALVERSION_AUTO
option in the menuconfig through this path:General setup ---> [ ] Automatically append version information to the version string
- For
CONFIG_LOCALVERSION_AUTO=y
to work properly the kernel directory must contain the.git
folder. - After the build and boot of the kernel with new configs you can see the
CONFIG_LOCALVERSION_AUTO=y
result with theuname -r
command or in the first lines in/var/log/kern.log
file (which we need to include to our repo as the task requires).
Instructions:
- Build a "Hello World module" that outputs specific messages on load and unload.
% sudo insmod main.ko % dmesg | tail -1 [Wed May 13 12:59:18 2015] Hello world ! % sudo rmmod main.ko % dmesg | tail -1 [Wed May 13 12:59:24 2015] Cleaning up module. %
- It must compile on any system
Notes:
-
If you want to record the "Hello world!\n" message to logs with the KERN_INFO option you need to decrease the console log level to 6 or smaller, to reach the above result (i.e. running
insmod main.ko
orrmmod main.ko
without showing log message). For that, you need to do the following.The default console log level when the computer is rebooted or is turning on is always reset to this:
% cat /proc/sys/kernel/printk 7 4 1 7
Where the first number is Console log level, 2 - Default log level, 3 - Minimum log level, 4 - Boot-time default log level.
To change Console log level permanently we need to run:
sudo echo 'LOGLEVEL="6"' >> /etc/sysconfig/console
Now, the result always will be:
% cat /proc/sys/kernel/printk 6 4 1 7
Alternatively for this method, you can increase the "Hello world !" message's log level from KERN_INFO to KERN_DEBUG. But I think the message is informative in nature and it is not a debugging message so this is not the preferred version.
In
/usr/src/<your_kernel_version>/include/linux/kern_levels.h
file you can see the log levels and their descriptions:#define KERN_EMERG "0" // system is unusable #define KERN_ALERT "1" // action must be taken immediately #define KERN_CRIT "2" // critical conditions #define KERN_ERR "3" // error conditions #define KERN_WARNING "4" // warning conditions #define KERN_NOTICE "5" // normal but significant condition #define KERN_INFO "6" // informational #define KERN_DEBUG "7" // debug-level messages
-
The
dmesg
command prints the logs prefixed by a raw timestamp. Like this:% dmesg | tail -1 [ 2523.841538 ] Hello world !
Despite the goal here is to write a basic driver that is able to write a message, we can fake dmesg by modifying the
.bashrc
file and adding this line to achieve the desired results:alias dmesg="dmesg -T --color=always"
Now, the result will be (thanks to the -T option):
% dmesg | tail -1 [Wed May 13 12:59:18 2023] Hello world !
-
__init
and__exit
keywords (from the<linux/init.h>
) put the functions in a specific section of the module binary. This section is unloaded after module initialization, in order to not waste RAM. It is not mandatory but it is a good practice for sure.
Useful commands:
insmod main.ko
lsmod
modinfo main.ko
rmmod main.ko
dmesg
dmesg -T
dmesg --color=always
dmesg | tail -1
Instructions:
- Take the same kernel git tree as in ex00 and modify it to have -thor_kernel in the version string
- Make a patch for the change, it has to be compliant with Linux standards
Notes:
- Documentation
- You can check your patches with the patch style checker:
scripts/checkpatch.pl
. - How to Patch Linux Kernel
- Best Practices to Getting Your Patches Accepted
- See also
man patch
Instructions:
- Take a given file and modify it to match the Linux coding style.
Notes
- Linux coding style
- For checking coding style use this command:
/usr/src/<kernel>/scripts/checkpatch.pl main.c -no-tree -file --strict
Instructions:
- Take the kernel module written for ex01 and modify it so that when any USB keyboard is plugged in, the module will be automatically loaded
- Write a rules file for hotplug userspace tools, if needed.
Notes
-
Udev is a device manager that dynamically manages device nodes in the /dev/ directory. The
/etc/udev/rules.d/
directory is where you can define custom rules for udev to follow.A brief explanation of what you can do with this directory:
- Device Naming: You can create rules that specify the names of device nodes. For example, you can set a specific name for a particular USB device or network interface.
- Permissions: You can use udev rules to set the permissions on device nodes. This allows you to control which users or groups have access to a device.
- Triggering Actions: Udev rules can be used to trigger certain actions when a specific device is connected or disconnected. For instance, you can run a script or a program when a particular USB device is plugged in.
- Attributes and Labels: You can use rules to set or modify device attributes and labels. This is useful for making devices easily identifiable.
Instructions:
- Take the kernel module written for ex01 and modify it to be a misc char device driver.
- The misc device should be created with a dynamic minor number.
- The misc device node should show up in /dev/fortytwo.
- The misc device should be registered when the module is loaded, and unregistered when it is unloaded.
- Make it behave specifically on reads and writes.
Notes
- Major and Minor numbers
- Creating Device File
- File Operations
- Real Device Driver
- Misc Device Driver
- For testing, you can use the
test.c
file or these commands:cat < /dev/fortytwo
echo -n vismaily > /dev/fortytwo
Instructions:
- Download the linux-next kernel, build it, compile it, and boot it.
Notes
Instructions:
- Write a kernel module that uses debugfs.
- You have to create a subdirectory in which you can find 3 special files handled by your driver.
- They all must have specific access rights and behavior.
Notes
- To create a directory in /sys/kernel/debug we first need to mount debugfs using this command:
mount -t debugfs none /sys/kernel/debug/
- Kernel documentation about debugfs
- Jiffies
- Mutex
Instructions:
- Take a given file, fix the coding style, and fix the code's behavior.
Notes
- Linux coding style
- For checking coding style use this command:
/usr/src/<kernel>/scripts/checkpatch.pl main.c -no-tree -file --strict
Instructions:
- Write a kernel module that exposes a file called mymounts on the root of the procfs.
- It has to list mount points on the system and their associated names.
Notes
- Procfs
- Linked lists in the kernel
- Linked lists in the kernel (Tutorial 1)
- Linked lists in the kernel (Tutorial 2)
- Linked lists in the kernel (detailed implementation)
- list_for_each_entry
- Mounts
- Documentation of seq_file
1) Coding style
2) printk
3) Linux Device Drivers, 3rd edition (chapter 14)
4) Linux Device Driver Tutorials
5) The Linux Kernel documentation
6) Building External Modules (documentation)