Problem Statement
This project focuses on building a Linux character device driver that functions as a device accessible from user space. The driver should check
the running kernel version before loading to ensure compatibility. Once loaded, the driver will support basic read and write operations, allowing
data to be exchanged between user space and the device. The messages must appear in the kernel log to confirm interactions.
Methodology
To achieve these objectives, the driver was built by defining properties needed for a character device and then implementing methods to handle
user interactions. The code first sets up the necessary device properties, including defining the name, device number, and buffer space where
data is temporarily stored. The driver should only load if it matches the running kernel version, iso we declare kernel version parameters.
The interaction between user space and the driver is achieved through the standard character device functions open, read, write, and release.
Each of these functions is defined in the driver code to handle specific operations and manage user requests. The read and write functions use
copy_to_user and copy_from_user to ensure that data is safely transferred between the user and the kernel.
In kernel version check, the sscanf function is used to parse the kernel version from the utsname()->release field, which the driver then
compares with the specified parameters. This check prevents the driver from loading if the kernel version does not match. If there is a
mismatch, the module will output an error message in the kernel log and abort the insertion process.
The initialization and cleanup functions are responsible for registering and unregistering the device. During initialization, the driver allocates a
device number, creates the associated device file, and links it to the operations defined in the file operations structure. Any error in the setup
process results in immediate cleanup and an error message.
Detailed Explanation
In the my_open function, the driver logs a message when a user opens the device, ensuring the developer knows when access has occurred.
The my_release function similarly logs when a user closes the device. The my_read function is designed to transfer data from the kernel buffer
to user space, taking care to manage the end of the file by checking the file position pointer (*ppos). This function also confirms that only the
available data in the buffer is read, preventing errors that may arise if a user tries to read beyond the end of the stored data.
For writing, the my_write function allows data from user space to be copied into the device buffer. This data is null-terminated so it can be
handled as a string, making it more flexible and easier to process. The buffer also has a defined size to prevent buffer overflow. Testing of the
driver is done by using standard commands like echo to write to the device and cat to read from it.
Logging with printk is implemented throughout the driver to provide feedback for each function’s activity. Messages such as “Read function
called” or “Device opened” are printed to the kernel log (viewable using the dmesg command), making it easier to verify functionality and debug
as needed. This driver thus provides a simple but effective interface for interacting with the device, allowing read and write operations to be
easily tested and verified.