Linux Device Drivers Notes

Linux Device Drivers book notes

Last Updated: December 31, 2018 by Pepe Sandoval

Want to show support?

If you find the information in this page useful and want to show your support, you can make a donation

Use PayPal


Use/Enable Monetization

Not Monetized

This will help me create more stuff and fix the existent content...

Chapter 1


  • Device Driver make a particular piece of hardware respond to a well-defined internal programming interface
  • Hide completely the details of how the device works
  • Drivers can be built separately from the rest of the kernel
  • Drivers can be plugged in at runtime when needed
  • The role of a device driver is providing mechanism, not policy (policy-free)
  • Mechanism
    • Refers to what capabilities are to be provided
    • Give access to HW
    • Access to the hardware capabilities without adding constraints
  • Policy
    • how those capabilities can be used - define how to use the HW
  • Policy-free characteristics:
    • synchronous and asynchronous operation
    • the ability to be opened multiple times
    • the ability to exploit the full capabilities of the hardware

Processes attend to different tasks and each process can request system resources (CPU time, memory, network connectivity, etc.) The kernel is the executable code in charge of handling these requests

kernel tasks

  1. Process Management
    1. Create/destroy processes
    • Handle a process connection to the outside world (I/O)
    • The communications among process
    • Scheduler, administration of CPU time
  • Memory Management
    1. Responsible for building virtual addressing space that abstract the actual physical resources
  • File-Systems
    • Responsible for building a structures FS to create a file abstraction
  • Networking
    • Handling the asynchronous incoming packets, collect, identify and dispatch the packets. In other words deliver data packets across program

Loadable Modules

  • A loadable module is a piece of code that can be added or removed to the kernel at run-time
  • A device driver is a type of loadable module
  • Loadable modules are made up of object code (not linked into a complete executable) that can be dynamically linked to the running kernel by the insmod program and can be unlinked by the rmmod program.

Classes of Devices

Also referred as Classes of Modules, Type of Device

  1. Character Devices
    1. it can be accessed as a stream of bytes (like a file)
    • Usually implement at least open, close,
    • Access by means of FS nodes
    • Functions as data channels that you can access mostly sequentially but also as an area read and write
  • Block Devices
    1. Devices that can host a filesystem
    • Access by means of FS nodes
    • Can only handle I/O operations that transfer one or more blocks of data (usually of size 512 bytes)
  • Network Interfaces
    1. A network interface is device that is able to exchange data with other hosts (usually a HW device).
    • A network interface is in charge of sending and receiving packets.
    • they are not stream oriented so they are not mapped to a node in the FS.

Chapter 2

Kernel modules vs App

  • Every kernel module just registers itself in order to serve future requests, it needs to prepare for later invocation of the module's functions
  • A module is linked only to the kernel, and the only functions it can call are the ones exported by the kernel; there are no libraries to link to.
  • Because no library is linked to modules, source files should never include the usual header files
  • related to the kernel is declared in headers found in the kernel source tree (include/linux and include/asm)
  • Segmentation fault in a Kernel modules at least kill the process currently running

Modes of execution kernel space and user space

  • The role of the operating system is to:

    • Provide programs with a consistent view of the computer’s hardware.
    • Account for independent operation of programs
    • Provide protection against unauthorized access to resources.
  • The CPU enforces protection of system software from the applications and the way to implement this it through different operating CPU modalities (levels or rings)

  • kernel executes in the highest level (supervisor mode), where everything is allowed, whereas applications execute in the lowest level (user mode), where the processor regulates direct access to hardware and unauthorized access to memory.

  • We usually refer to the execution modes as kernel space and user space. Each mode can have its own memory mapping—its own address space

  • Unix transfers execution from user space to kernel space whenever an application issues a system call or is suspended by a hardware interrupt

Concurrency Considerations

  • Modules must be Reentrant — it must be capable of running in more than one context at the same time.

  • Data structures must be carefully designed to keep multiple threads of execution separate, and the code must take care to access shared data in ways that prevent corruption of the data

  • Most actions performed by the kernel are done on behalf of a specific process

  • Modules are strongly tied to the data structures and function prototypes defined in a particular kernel version.

  • Module's code has to be recompiled for each version of the kernel that it is linked to

  • The kernel will make calls into your module while your initialization function is still running.

  • Consider what happens if your initialization function decides to fail, but some part of the kernel is already making use of a functionality your module has registered

The Kernel Symbol Table

  • It's a table that contains the addresses of global kernel items (functions and variables)

  • When a module is loaded, any symbol exported by the module becomes part of the kernel symbol table which can be used by other modules

  • initialization function registers any functionality offered by the module

  • sys/module is a sysfs directory hierarchy containing information on currently-loaded modules

user space drivers
  • The full C library can be linked in. The driver can perform many exotic tasks without resorting to external programs
  • are debuggable using a conventional debugger
  • memory swappable
  • interrupts are not available
  • direct memory access require mapping
  • Access to IO ports is restricted/limited

There's list of repositories that is in a file that can be used to install a package so we use apt-get update so that the head of each repo in that list points to the most recent commit of that repo to add a repo we use PPAs (personal package archives) which are identifiers of repos sudo add-apt-repository ppa:

Major and Minor Numbers

  • Traditionally, the major number identifies the driver associated with the device
  • The minor number is used by the kernel to determine exactly which device is being referred to.

Important Data Structures

Most of the fundamental driver operations involve three important kernel data structures: file_operations, file, and inode

  • A collection of function pointers
  • A file_operations structure or a pointer to one is called fops
  • Each field in the structure must point to the function in the driver that implements a specific operation
  • Fields
    • struct module *owner
      • it is a pointer to the module that “owns” the structure.
    • loff_t (*llseek) (struct file *, loff_t, int);
      • used to change the current read/write position in a file.
    • ssize_t (*read) (struct file *, char _ _user *, size_t, loff_t *);
      • Used to retrieve data from the device.
    • ssize_t (*aio_read)(struct kiocb *, char _ _user *, size_t, loff_t);
      • Initiates an asynchronous read operation.
    • ssize_t (*write) (struct file *, const char _ _user *, size_t, loff_t *);
      • Used to send data to the device.
    • ssize_t (*aio_write)(struct kiocb *, const char _ _user *, size_t, loff_t *);
      • Initiates an asynchronous write operation.
    • int (*readdir) (struct file *, void *, filldir_t);
      • it is used for reading directories and is useful only for filesystems.
    • unsigned int (*poll) (struct file *, struct poll_table_struct *);
      • query whether a read or write to one or more file descriptors would block
    • int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
      • The ioctl system call offers a way to issue device-specific commands
    • int (*mmap) (struct file *, struct vm_area_struct *);
      • used to request a mapping of device memory to a process’s address space
    • int (*open) (struct inode *, struct file *);
      • zzzzz
    • int (*flush) (struct file *);
      • zzzz
    • int (*release) (struct inode *, struct file *);
      • Invoked when the file structure is being released
    • int (*fsync) (struct file *, struct dentry *, int);
      • This method is the back end of the fsync system call
    • int (*aio_fsync)(struct kiocb *, int);
      • This is the asynchronous version of the fsync
    • int (*fasync) (int, struct file *, int);
      • Asynchronous notification to notify the device of a change in its FASYNC flag
    • ssize_t (*readv/*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
      • These methods implement scatter/gather read and write operations
    • ssize_t (*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void *);
      • This method implements the read side of the sendfile system call
    • ssize_t (*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void *);
      • Other half of sendfile; it is called to send data, one page at a time, to the corresponding file

Asynchronous operations might or might not complete before their function returns.

file structure

  • The file structure represents an open file

  • It is created by the kernel on open and is passed to any function that operates on the file.

  • After all instances of the file are closed, the kernel releases the data structure

  • Fields

    • mode_t f_mode;
      • Identifies the file as either readable or writable (or both),
    • loff_t f_pos;
      • The current reading or writing position. Used to know the current position in the file
    • unsigned int f_flags;
      • These are the file flags
    • struct file_operations *f_op;
      • The operations associated with the file
    • void *private_data;
      • You are free to make its own use of the field or to ignore it; you can use the field to point to allocated data
    • struct dentry *f_dentry;

inode structure

  • The inode structure is used by the kernel internally to represent files.

  • There can be numerous file structures representing multiple open descriptors on a single file, but they all point to a single inode structure

    • dev_t i_rdev;
      • For inodes that represent device files, this field contains the actual device number.
    • struct cdev *i_cdev;
      • kernel’s internal structure that represents char devices; this field contains a pointer to that structure when the inode refers to a char device file.
  • user space & kernel space addresses

  • User space pointer cannot be dereferenced

    • the pointer may not be valid while running in kernel mode , there may be no mapping for that address
  • user-space memory is paged (it might not be in RAM )

sysfs dev proc sys


parallel port driver modules? kernel mode and user mode memory is paged? a page fault? system call?

/proc ? device nodes?


FS = a way of organizing data on a physical medium Network interface =

some types of drivers work with additional layers of kernel support functions for a given type of device

It is also possible to disable the loading of kernel modules after system boot via the capability mechanism

_ _init and _ _initdat tokens are hints to the kernel that the given function or data are only used used only at initialization time then the module loader drops the function or data loaded, making its memory available for other uses.

cat /proc/version

Want to show support?

If you find the information in this page useful and want to show your support, you can make a donation

Use PayPal


Use/Enable Monetization

Not Monetized

This will help me create more stuff and fix the existent content...