0% found this document useful (0 votes)
4 views

Linux Drivers notes

The document outlines essential concepts and techniques for Linux device driver development, emphasizing the role of device drivers as a bridge between the Linux kernel and hardware. It covers topics such as module development, debugging techniques, concurrency, and communication with hardware, along with specific driver types like character, block, network, and USB drivers. Key takeaways include the importance of abstraction, kernel integration, concurrency management, debugging skills, and maintaining portability in driver coding.

Uploaded by

Suhas KR
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Linux Drivers notes

The document outlines essential concepts and techniques for Linux device driver development, emphasizing the role of device drivers as a bridge between the Linux kernel and hardware. It covers topics such as module development, debugging techniques, concurrency, and communication with hardware, along with specific driver types like character, block, network, and USB drivers. Key takeaways include the importance of abstraction, kernel integration, concurrency management, debugging skills, and maintaining portability in driver coding.

Uploaded by

Suhas KR
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

1.

Introduction & Core Concepts

 Device Drivers as a Bridge: The book emphasizes that device


drivers are crucial for allowing the Linux kernel to interact with
hardware. As stated in the Preface, "...somebody is going to have to
make all those new gadgets work with Linux."

 Kernel Internals: Beyond just driver writing, the book aims to


illuminate how the kernel operates and how developers can tailor it
to their needs, promoting accessibility for a broader community of
developers.

 Open System: Linux is positioned as an open system, and the


book's goal is to make it "...more open and accessible to a larger
community of developers."

 Module Parameters: Modules can accept parameters, allowing


user customisation at load time. These parameters have types (e.g.
bool, int, charp) and default values. They are exposed via sysfs,
controlled by permissions (e.g. S_IRUGO for read-only, S_IRUGO|
S_IWUSR for read/write by root). However, the module is not actively
notified when sysfs changes the parameter, so writable parameters
should be handled carefully.

 Block vs. Char Devices: Both are accessed via nodes in /dev. The
key distinction is how data is managed internally by the kernel.
Block devices typically handle I/O in fixed-size blocks (often 512
bytes or larger multiples), while char devices permit transfer of any
number of bytes at a time. Although Linux allows applications to
read/write block devices like character devices the core differences
mean they have completely different kernel interfaces.

 Device Numbers: Internally, the kernel uses dev_t to hold device


numbers. As of kernel 2.6.0, this is a 32-bit number, with 12 bits for
the major number and 20 for the minor number. Macros are
provided in <linux/kdev_t.h> (MAJOR(), MINOR(), MKDEV()) to
access major/minor numbers reliably.

2. Module Development

 Hello World Example: A basic "Hello World" module is used as an


introduction to kernel module creation, demonstrating the
differences between kernel modules and user space applications.

 printk function: This function (analogous to printf) is the standard


way to output messages from kernel code. It supports different
levels of logging (e.g., KERN_DEBUG, KERN_WARNING).
 Dynamic Device Numbers: Modules can request dynamic major
numbers. Tools like awk can then extract these numbers from
/proc/devices and be used to create the correct /dev entries.

 Module Loading Script: The scull_load script illustrates how a


module can be loaded and the appropriate device nodes created, a
process usually performed at boot time or manually by an
administrator.

 Module parameters: These are set using the module_param


macro, allowing configuration of behaviour during module load.

3. Character Driver Fundamentals (using the scull driver as an


example)

 scull_open: This function acquires device information using


container_of. It uses the f_flags to check if it was opened in write-
only mode and, if so, will trim the memory to zero.

 scull_read & scull_write: These functions are responsible for


transferring data between the kernel and user space, using
copy_to_user and copy_from_user respectively. They interact with a
device's underlying memory, moving data in quantum sized blocks.

 scull_llseek: If a driver requires seek operations that map to a


physical action of the device a custom llseek method can be
supplied for custom logic.

4. Debugging Techniques

 Print Debugging: The printk function is a primary tool for


debugging. The PDEBUG macro can conditionally enable/disable
debugging messages for both kernel and user space.

 /proc Filesystem: Device drivers can expose information via the


/proc filesystem. Example code to dump scull device info is shown.

 Kernel Oops: The book covers interpreting "oops" messages from


the kernel, caused by events like dereferencing a null pointer,
providing the example of a NULL pointer dereference using *(int*)0
= 0;.

 Using gdb: The gdb debugger can be used to examine variables


within loadable modules. The book suggests a script (gdbline) to
ease the creation of necessary commands (add-symbol-file).

 kdb Kernel Debugger: An example session using kdb is provided


for examination of in kernel data structures.

5. Concurrency and Locking


 Race Conditions: The scull device is used to demonstrate potential
race conditions, emphasising that shared resources require careful
management of concurrent access.

 Locking Mechanisms: The book outlines various locking


techniques:

 Semaphores and Mutexes: For protecting critical sections of code


that might sleep.

 Completions: A lightweight method for synchronisation.

 Spinlocks: For short, critical sections where sleeping is not


permitted.

 Atomic Variables: Used to implement atomic operations without


requiring locking for simple counter-like operations. Includes
functions like atomic_set, atomic_read, atomic_add, atomic_sub, etc.

 Bit Operations: The text mentions bit-level operations


(test_and_set_bit, test_and_clear_bit) that can be used for creating
low-level locks.

 Locking Traps: Discusses problems to avoid when implementing


locking, including lock ordering issues, which can lead to deadlocks.

6. Advanced Character Driver Operations

 ioctl: This function provides a mechanism for sending control


commands and data to devices (beyond basic read/write). Example
code shows accessing it from user-space using ioctl system calls.

 Blocking I/O: Covers using wait queues and the


wait_event_interruptible function to implement blocking I/O.

 poll and select: These system calls allow monitoring of multiple


file descriptors for readability or writeability.

 Asynchronous Notification: Discusses how drivers can notify user


space about events using signals.

7. Time, Delays, and Deferred Work

 Time Measurement: Covers time measurements within the kernel


using "jiffies" and functions like get_cycles to access the timestamp
counter. Conversion macros like jiffies_to_msecs are mentioned.

 Delays: Short delays can be achieved using functions like udelay,


ndelay, mdelay, and msleep. It notes that udelay and ndelay have
upper limits on values, and an unresolved symbol, __bad_udelay can
be a result of calling it with too high a number.
 Kernel Timers: Timers enable functions to be scheduled to run
after a specific delay, and provides functions like add_timer,
mod_timer and del_timer_sync.

 Tasklets: Tasklets are a mechanism for performing deferred work


(specifically, actions that can occur shortly, but not immediately),
within the kernel. They are serialized with respect to themselves and
always run on the same CPU that scheduled them.

 Workqueues: Workqueues provide a general-purpose way to defer


work in the kernel, often to process data from interrupt handlers.
They run in a separate process context, allowing potentially blocking
calls.

8. Memory Allocation

 kmalloc: Discusses the real story of kmalloc (as it is not always the
best way to allocate memory).

 Lookaside Caches: Used for efficient allocation of frequently used


objects of a fixed size.

 get_free_page and vmalloc: Methods for allocating page-sized


and larger memory blocks.

 Per-CPU Variables: Used for storing data that is specific to a


particular CPU core.

9. Communicating with Hardware

 I/O Ports and Memory: Hardware interaction is performed via I/O


ports or memory-mapped I/O.

 request_region: Used to claim exclusive access to specific I/O port


ranges.

 ioremap: Required to map physical memory addresses into the


kernel's virtual address space. Functions like iowrite8, ioread32, are
used to access memory-mapped I/O after it has been mapped with
ioremap.

10. Interrupt Handling

 Interrupt Handler Installation: Drivers must install interrupt


handlers (using functions like request_irq) to respond to
asynchronous hardware events.

 Top and Bottom Halves: Introduces the concept of separating


interrupt handling into fast "top halves" and slower "bottom halves"
(often tasklets or workqueues) to avoid delays.
11. Data Types in the Kernel

 Explicit Sizing: It is important to use fixed size data types like u8,
u16, u32, and u64 instead of the more general types like int to
ensure portability across different architectures.

 Endianness: Portability problems due to differences between


endian architectures are noted.

12. PCI Drivers

 PCI Interface: Discusses the PCI bus and how to access hardware
on it. Mentions other PC buses such as ISA, PC/104, SBus and
NuBus.

13. USB Drivers

 USB Basics: Introduces core USB concepts (endpoints, URBs, etc.)

 USB Transfers: Covers different types of USB transfers, including


bulk and interrupt transfers.

 USB Device Model: Discusses how USB devices are exposed via
sysfs.

14. The Linux Device Model

 kobjects and ksets: Key components of the Linux device model.

 Sysfs: Describes the role of sysfs in representing the device model.

 Buses, Devices, and Drivers: Highlights the relationships


between these elements.

 Hotplug: Discusses handling of device hotplug events via a


/sbin/hotplug utility.

15. Memory Mapping and DMA

 Memory Management: Introduces concepts of how Linux


manages memory, including virtual address spaces.

 mmap Device Operation: Allows mapping of device memory into


user-space process memory.

 Direct I/O: How to perform I/O operations directly into user space
buffers.

 Direct Memory Access (DMA): DMA mechanisms for hardware to


access system memory directly, without involving the main
processor. dma_alloc_coherent is mentioned.

16. Block Drivers


 Block Concepts: Introduces the concepts of blocks and sectors,
and notes that the kernel uses 512-byte sectors internally.

 gendisk Structure: How the kernel represents a block device.


Functions for creating (alloc_disk) and adding (add_disk) this
structure are covered.

 Request Queues: Block drivers use request queues to handle I/O


operations.

 Ioctl: Block devices may implement ioctl calls for control.

 Request processing: Details how block requests are handled by a


device driver, and examples given.

 Tagged command queueing: Mention of initialising tagged


command queueing.

17. Network Drivers

 net_device Structure: The core structure for network device


representation. alloc_netdev is used to create the structure.

 Snull Example: The snull driver is used as an example of a simple


virtual network driver, and covers how devices are registered.

 Packet Transmission/Reception: The driver must handle the


transmission and reception of network packets, using dev_alloc_skb
to allocate socket buffers. netif_receive_skb delivers the buffer to
the networking layer.

 Interrupts: How to handle network device interrupts, often by


queuing data to be processed in bottom halves.

 Polling: Using the poll method to process queued network packets.

 Socket Buffers (sk_buffs): Structure used to manage and pass


network data.

18. TTY Drivers

 TTY Concepts: An overview of TTY devices (terminals) is provided.

 tty_driver and tty_operations: Data structures that describe a


TTY device and its associated functions.

 TTY Line Settings: How TTY devices are configured (e.g., baud
rate, parity)

 ioctl: The ioctl function can be used to implement TTY specific


control features, and examples given.
Key Takeaways:

 Abstraction: Linux device drivers are a layer of abstraction,


allowing a consistent interface for higher layers of the system to
interact with hardware.

 Kernel Integration: Drivers must integrate tightly with the kernel


through specific interfaces.

 Concurrency: Developers must understand and handle


concurrency issues that arise when multiple processes access a
device simultaneously.

 Debugging: Solid debugging skills are essential, and knowledge of


kernel debugging techniques is crucial.

 Portability: Careful coding practices and using the correct data


types are important for maintaining device driver portability.

This briefing document summarises the core concepts and important


details extracted from the provided material. It provides a foundation for
further exploration of the intricate world of Linux device driver
development.

You might also like