Try   HackMD

研讀 The Linux Kernel Module Programming Guide

https://sysprog21.github.io/lkmpg/

Pre

kernel modules 至少要有兩個函式:

  • init_module() which is called when insmod
  • cleanup_module() which is called when rmmod

cleanup_module() is supported to undo whatever init_module() did.

  • kernel coding style about indentation is tabs not spaces.
  • print macros : pr_info(), pr_debug()
  • To learn how to compile modules which are not offical, see Documentation/kbuild/modules.rst.
  • details about Makefiles for kernel modules, see Documentation/kbuild/makefile.rst.

init_module()cleanup_module() 可以改成用 macro module_init()module_exit() 來做, macro 傳入值為進入/離開的 function name。

__init, __exit

Passing command line arguments to a module with macros:

  • module_param()
  • module_param_array()
  • module_param_string()

Library functions are used in user mode.
System calls are provided by the kernel itself.

工具: strace

Unix uses only two rings

  • ring 0, supervisor mode
  • ring 1, user node

When writing kernel code, every module will be linked against entire kernel, thus namespace pollution is a problem. We should

  • use static qualifier
  • use prefix for symbols

The file /proc/kallsyms holds all symbols that kernel knows.

(剛剛開了本地的,發現有 235827 行

Since a module is code which can be dynamically inserted and removed in the kernel, it shares the kernel's codespace rather than having its own.


Device drivers are one class of module, which provides functionality for hardware.

They are located in /dev.

crw-------   1 root      root     10,   126  3月 11 11:46 ecryptfs
crw-rw----   1 root      video    29,     0  3月 11 11:46 fb0
lrwxrwxrwx   1 root      root            13  3月 11 11:46 fd -> /proc/self/fd
crw-------   1 root      root    505,     0  3月 11 13:10 fibonacci

逗號第一個數字是 major number ,第二個是 minor number 。

Each driver is assigned a unique major number.

All device files with the same major number are controlled by the same driver. The minor number is used by the driver to distinguish between the various hardware it controls.

The kernel doesn't care minor number.
The drivers care.

Devices have two types

  • character devices :列表中以 c 開頭的
  • block devices :列表中以 b 開頭的

Block devices

  • 有自己的 buffer 可以決定先處理哪個 request
  • only accept input and return output in fixed block size

Character Device Drivers

linux/fs.h

file_operations structure holds pointers to functions defined by the driver.

The unused entries should be set to NULL.

Since Linux v5.6, the proc_ops structure was introduced to replace the use of file_operations when registering proc handlers.

  • A file is a kernel level structure and never appears in a user space program.
  • A FILE is defined by glibc and would never appear in a kernel space function.

inode, filp

Register and Unregister

Adding a driver means registering in with kernel

static inline int register_chrdev(unsigned int major, const char *name,
				  const struct file_operations *fops)

If pass major of 0 to register_chrdev(), the number will be dynamically allocated.

register_chrdev would occupy a range of minor numbers associated to the major.

recommend to use cdev interface


We can not allow the kernel module to be rmmod'ed whenever root feels like it. We should check the refcnt. The check will be performed by sys_deleta_module() defined in linux/syscall.h.

The counter should not be used directly. We should use the interface in linux/module.h :

  • try_module_get()
  • module_put()
  • module_refcount()

chardev.c sample

page pointer : 35