
Linux Kernel Modules, Virtual Filesystem, Device Filesystem, and Device Classes
Explore the essence of Linux kernel modules, virtual filesystems, device filesystems, and device classes in this informative guide. Learn about the role of kernel modules in extending system functionality, the structure of virtual filesystems, accessing devices via the device filesystem, and the various device classes available in the Linux kernel.
Uploaded on | 2 Views
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
Linux Kernel Modules and Kernel I/O CMSC 421 Section 02 March 24, 2020 Adapted from slides from Professor Jason Tang (UMBC)
Linux Virtual Filesystem The Linux Virtual Filesystem allows for a variety of non-file objects to be set up in the filesystem Memory-backed files, such as those in /tmp (via tmpfs) and shared memory files (via shmfs) are two examples of this Devices also have a presence in the filesystem on /dev, through devfs Virtual files generated by the kernel such as those in /proc (procfs), /sys (sysfs), and /sys/debug (debugfs) are also available
Device Filesystem The /dev filesystem is where one can access various attached devices through their device driers Accessing a given file within the /dev filesystem will match the kernel driver of the file and pass off access to the appropriate module (or part of the kernel code) Examples: /dev/mem, /dev/zero call into the memory driver of the kernel /dev/random, /dev/urandom call into the kernel s random driver Devices can be read-only, write-only, or read-write Hotplug devices are typically represented in /sys, not in /dev (but not always)
Device Classes There are a variety of different types of device classes available in the Linux kernel Character devices are those that are accessed through a stream of bytes /dev/console, /dev/random, /dev/ttyS2 Block devices are those that are accessed as a set of blocks, where reads and writes take place in block-sized increments (often 512 bytes at a time) /dev/sda, /dev/sr0, /dev/cdrom Network devices are those that perform I/O over a network interface These do not have entries in /dev, typically
Kernel Modules A kernel module is a piece of code that can be added to the kernel at runtime to extend its functionality. Often, device drivers for proprietary devices are provided this way Like the kernel itself, device drivers are written in C89/C90/ANSI C No // comments, no mixed declarations and code, etc. No variable-length arrays Floating-point arithmetic is not allowed within the kernel! Requires library support, which is part of user-space, not the kernel
Example Hello World kernel module #include <linux/kernel.h> #include <linux/module.h> MODULE_LICENSE("GPL"); static int __init hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit);
Creating Kernel Modules Kernel modules are part of the kernel itself (once loaded) and thus cannot use user-space libraries Normal exported kernel library functions are available (like kmalloc, printk, etc) Some exported functions require that the module be licensed under the GPL, which can be signaled by the MODULE_LICENSE( GPL ) line in the previous example These are usually only internal interfaces most useful functions have no such restriction Like with any other kernel code, you are responsible for your own memory management You MUST ensure that you free all memory allocated in your module before it is unloaded Kernel modules, like other kernel code, often use goto statements for error handling
Creating Kernel Modules Kernel modules can create threads to run, however typically modules are implemented in an event-driven architecture In the initializer, you will typically register callbacks into some kernel system to happen on various events When the event occurs, the kernel will call your callback function automatically Initializers are specified using the module_init() macro A cleanup function that is run when the module is unloaded can be specified with the module_exit() macro
Synchronization and Concurrency As the kernel itself is multithreaded (and various applications can call into the kernel at the same time), care must be taken to properly handle concurrency within kernel module code The kernel provides various locking mechanisms like mutexes, semaphores, condition variables, reader/writer locks, reader/writer semaphores As well as lower-level primitives like the futex, rcu_lock, or spinlock
Compiling/Loading Modules Modules can be built in the kernel tree or out of the kernel tree In-tree modules can usually also be built-in to the kernel A Makefile must be provided to build a kernel module An example is provided on the next slide Modules are loaded into the kernel by the insmod program insmod my_module.ko Modules can be unloaded by the rmmod program rmmod my_module
Kernel Module Makefile obj-m += my_module.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Linux Devices and Drivers In Linux, devices are represented internally as a device number consisting of a major number and a minor number Major number: type of device Minor number: instance of device The kernel can instantiate multiple copies of a device driver to handle multiple instances of a given type of device See the include/uapi/linux/major.h file in the kernel source code for a mapping of major device numbers to various types of devices
Device Setup and Cleanup Device drivers include a probe function to handle setup for multiple instances A remove function is provided to be called when a device is removed (such as being unplugged) Should clean up whatever the probe function initialized for that instance When a device driver module is loaded, the kernel calls the module s init function, which sets up the probe/remove callbacks Each time a device matching the driver is detected, the probe function will be called When a module is unloaded, its exit function will be called The remove function will be called for every initialized instance of the device first!
Device Operations Device drivers typically have three parts: registration, interrupt handling, and user-space interactions Registration is required, the others are usually provided Registration is to set up the kernel s callbacks for the device Interrupt handling deals with low-level hardware interrupts and DMA User-space interactions are to provide entries in /dev, respond to system calls for device status, and otherwise interact with the user
Creating Device Nodes In order to interact with user-space, drivers typically create a device node in devfs to allow the user to perform various operations This requires registering a set of callbacks that provide for the system calls involved to call on the driver Registration of the callbacks happens in the probe function Creation of a device node requires the major/minor numbers of the device, its name, and permission bits
Miscellaneous Devices There are many steps involved in creating devices The kernel provides an interface called miscdevice that can automate some of the boilerplate for you for creating simple character devices Each miscdevice instance is implemented using a struct miscdevice Include/linux/miscdevice.h Callbacks for file system calls are provided with a struct file_operations Miscellaneous devices all share major number 10 The kernel usually dynamically assigns minor numbers to misc devices For an example, see the kernel s real-time clock (rtc) driver