Driver fundamentals: learn to write and debug Linux kernel device drivers step by step.
Hands-on practice with modules, character devices, kernel logs and APIs.
Explore memory management, interrupts and synchronization in real examples.
Gain practical experience via labs (~70%) building and testing drivers on Linux.
How this helps: understand kernel-user boundaries and driver development best practices.
Who it’s for: designed for individuals with C/Linux basics who want kernel-level skills.
By the end you’ll build working drivers and debug them with confidence.
Curriculum
Introduction
- Kernel versions
- Kernel sources and the use of git
- Rolling your own kernel
- Platforms
- Types of device drivers
- Elements of an embedded Linux project (high-level overview)
Device drivers
- Types of devices; mechanism vs. policy; avoiding binary blobs
- How applications use device drivers
- The system call mechanism
- Error numbers
- printk()
- devres: managed device resources
- Modules and device drivers: module_driver() macros, modules and hot plug
Memory management and allocation
- Virtual and physical memory
- Memory zones
- Page tables
- kmalloc(), __get_free_pages(), vmalloc()
- Slabs and cache allocations
Character devices
- Device nodes
- Major and minor numbers; reserving numbers
- Accessing the device node
- Registering the device
- udev
- dev_printk() and related functions
- file_operations structure
- Driver entry points
- The file and inode structures
Transferring between user and kernel space
- User-space vs. kernel-space; system calls; process context
- The linked list and other data structures
- put(get)_user() and copy_to(from)_user()
- Direct transfer: Kernel I/O and memory mapping
- User-space functions for mmap()
- Driver entry point for mmap()
Interrupts and exceptions
- Interrupts and exceptions
- Asynchronous interrupts
- MSI
- Enabling / disabling interrupts
- What not to do at interrupt time
- IRQ data structures
- Installing an interrupt handler
Timing measurements
- Types of measurements
- Jiffies
- Getting the current time
- Clock sources
- Programmable interval timer
- Time stamp counter
- HPET
- Tickless kernels
Kernel timers
- Inserting delays
- Low resolution timers
- High resolution timers
ioctls
- Driver entry points for ioctls
- Locked and lockless ioctls
- Defining ioctls
Unified device model and sysfs
- Basic data structures
- Real devices
- sysfs
- kset and kobject examples
Sleeping and wait queues
- Going to sleep and waking up
- Exclusive sleeping
- Polling
Interrupt handling
- Top and bottom halves
- Deferrable functions and softirqs
- Tasklets
- Work queues
- Threaded interrupt handlers
- Interrupt handling in user-space
Hardware I/O
- Buses and ports
- Memory barriers
- Registering I/O ports
- Accessing I/O registers and I/O memory
- Access by user: ioperm(), iopl(), /dev/port
Application (if time allows)
- Implementing a LED driver
- Implementing a temperature sensor driver
Course Day Structure
- Part 1: 09:00–10:30
- Break: 10:30–10:45
- Part 2: 10:45–12:15
- Lunch break: 12:15–13:15
- Part 3: 13:15–15:15
- Break: 15:15–15:30
- Part 4: 15:30–17:30