Linux Driver 入门 - Introduction to Device Drivers

:  

Linux Driver

 

 

Device Major and Minor Numbers

 

he Internal Representation of Device Numbers Within the kernel, the dev_t type (defined in <linux/types.h>) is used to hold device numbers—both the major and minor parts.

As of Version 2.6.0 of the kernel, dev_t is a 32-bit quantity with 12 bits set aside for the major number and 20 for the minor number. Your code should, of course, never make any assumptions about the internal organization of device numbers; it should, instead, make use of a set of macros found in   <linux/kdev_t.h>.

To obtain the major or minor parts of a dev_t, use:

  MAJOR(dev_t dev);

  MINOR(dev_t dev);

If, instead, you have the major and minor numbers and need to turn them into a dev_t, use:

   MKDEV(int major, int minor);

Two Main Types of Device Drivers

Character Device Drivers

Character devices can be compared to normal files in which we can read/write arbitrary bytes at a time. Character device work with a stream of bytes.

The only relevant difference between a char device and a regular file is that you can always move back and forth in the regular file, whereas most char devices are just data channels, which yoiu can only access sequentially.

Examples of character device drivers are:

> Serial port

>Text console

> Mice

> Parallel printer ports

 

Char devices are accessed by means of filesystem nodes, such as /dev/tty1 and /dev/lp0

 

writing/reading character by character

operate in blocking mode; synchronous with operations

most common of all device drivers

Find all the devices  in the system

$ ls /dev

$ ls -l /dev/tty0
crw--w---- 1 root tty 4, 0 Mar 10 09:17 /dev/tty0

$ ls -l /dev/tty1
crw--w---- 1 gdm tty 4, 1 Mar 10 09:17 /dev/tty1

 

 The major number of tty0 is 4, and the minor number is 0.

Block Device Drivers

writing/reading block by block

CPU intensive and operations take a long time to complete, asynchronous with operations

Block devices, on the other hand, operate on blocks of data, not on arbitrary bytes. The usual block size is 512 bytes or larger powers of two.  As a result, block and char devices differ only in the way data managed internally by the kernel. Like a char device, each block device is accessed through a filesystem node, and the difference between them is transparent to the user.

Examples of block device drivers include

> Hard drives

>CD-ROM drives

Create a new device node

mknod [OPTION]... NAME TYPE [MAJOR MINOR]

 

yubao@yubao-ThinkPad-E560:/dev$ sudo mknod /dev/myDevice c 900 1
[sudo] password for yubao:
yubao@yubao-ThinkPad-E560:/dev$ ls -l myDevice
crw-r--r-- 1 root root 900, 1 Mar 10 10:00 myDevice

 

 Location of Linux Kernel Modules

Usually, all Linux kernel modules (drivers) are stored in the module directory located that /lib/modules/$(uname -r) directory.

To see current modules, type:

yubao@yubao-ThinkPad-E560:~$ ls /lib/modules/$(uname -r)
build   modules.alias      modules.builtin.bin  modules.devname  modules.symbols
initrd  modules.alias.bin  modules.dep          modules.order    modules.symbols.bin
kernel  modules.builtin    modules.dep.bin      modules.softdep  vdso

 

list all drivers for various devices:

yubao@yubao-ThinkPad-E560:~$ ls /lib/modules/$(uname -r)/kernel/drivers
acpi        dax       hid         isdn       mmc      platform    scsi         vfio
ata         dca       hsi         leds       mtd      power       spi          vhost
atm         dma       hv          lightnvm   net      powercap    spmi         video
auxdisplay  edac      hwmon       macintosh  nfc      pps         ssb          virtio
base        extcon    hwspinlock  mailbox    ntb      ptp         staging      vme
bcma        firewire  hwtracing   mcb        nvdimm   pwm         target       w1
block       firmware  i2c         md         nvme     rapidio     thermal      watchdog
bluetooth   fmc       iio         media      parport  regulator   thunderbolt  xen
char        fpga      infiniband  memstick   pci      remoteproc  tty
clk         fsi       input       message    pcmcia   reset       uio
cpufreq     gpio      iommu       mfd        phy      rpmsg       usb
crypto      gpu       ipack       misc       pinctrl  rtc         uwb

 

How Symbols are Exported?

Exporting Kernel Symbols is typically done with:

> EXPORT_SYMBOL(), which exports a given symbol to all loadable modules

>EXPORT_SYMBOL_GPL(), which exports a given symbol to only those modules that have a GPL-compatible license.

 

Kernal Symbol Table

Definition:

Kernal symbol table is nothing but a look-up table between symbol names and their addresses in memory.

When a module is loaded into Kernel memory using insmod or modprobe utility, any symbol exported by the module becomes part of Kernal Symbol table. Exported symbols will become public Kernel Symbols.

 

 The most common and most frustrating failure in loading an LKM is an unresolved symbol, like:

insmod: error inserting 'XXX.ko": -l Unknown sybol in module

To debug this error:

> use nm utility

$nm XXX.ko will display all the symbol table of this module

> Know symbol definitions

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ nm hello.ko
0000000000000020 T cleanup_module
                 U __fentry__
0000000000000020 t hello_exit
0000000000000000 t hello_init
0000000000000000 T init_module
0000000000000040 r __module_depends
                 U printk
0000000000000000 D __this_module
0000000000000000 r __UNIQUE_ID_license8
0000000000000049 r __UNIQUE_ID_name9
0000000000000018 r __UNIQUE_ID_srcversion10
0000000000000054 r __UNIQUE_ID_vermagic8

Symbol types in Module

 Check https://linux.die.net/man/1/nm for details.

The characters that identify symbol type describe 

  • A :  Global absolute symbol.
  • a  :  Local absolute symbol.
  • B : Global bss symbol.
  • b : Local bss symbol.
  • D : Global data symbol.
  • d : Local data symbol.
  • f : Source file name symbol.
  • L : Global thread-local symbol (TLS).
  • l : Static thread-local symbol (TLS).
  • T : Global text symbol.
  • t  : Local text symbol.
  • U : Undefined symbol.

 How to check all the symbols?

$ cat /proc/kallsyms |more

 

System.map

 In Linux, the System.map file is a symbol table used by the kernel.

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/SybolError$ locate System.map
/boot/System.map-4.13.0-32-generic
/boot/System.map-4.13.0-36-generic
/boot/System.map-4.4.0-040400-generic
/boot/System.map-4.4.0-64-generic
/boot/System.map-4.4.64-040464-generic

 

 

References

  1. Linux Device Drivers, Third Edition, https://lwn.net/Kernel/LDD3/

 

posted on 2018-03-10 17:50  LiuYubao  阅读(644)  评论(0编辑  收藏  举报

导航