Once you have a running Linux system, it is useful to know which device drivers are loaded and what state they are in. You can find out a lot by reading the files in /proc
and /sys
.
First of all, you can list the character and block device drivers currently loaded and active by reading /proc/devices
:
# cat /proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 /dev/vc/0 4 tty 4 ttyS 5 /dev/tty 5 /dev/console 5 /dev/ptmx 7 vcs 10 misc 13 input 29 fb 81 video4linux 89 i2c 90 mtd 116 alsa 128 ptm 136 pts 153 spi 180 usb 189 usb_device 204 ttySC 204 ttyAMA 207 ttymxc 226 drm 239 ttyLP 240 ttyTHS 241 ttySiRF 242 ttyPS 243 ttyWMT 244 ttyAS 245 ttyO 246 ttyMSM 247 ttyAML 248 bsg 249 iio 250 watchdog 251 ptp 252 pps 253 media 254 rtc Block devices: 259 blkext 7 loop 8 sd 11 sr 31 mtdblock 65 sd 66 sd 67 sd 68 sd 69 sd 70 sd 71 sd 128 sd 129 sd 130 sd 131 sd 132 sd 133 sd 134 sd 135 sd 179 mmc
For each driver, you can see the major number and the base name. However, this does not tell you how many devices each driver is attached to. It only shows ttyAMA
but gives you no clue that it is attached to four real UARTS. I will come back to that later when I look at sysfs
. If you are using a device manager such as mdev
, udev
, or devtmpfs
, you can list the character and block device interfaces by looking in /dev
.
You can also list network interfaces using ifconfig
or ip
:
# ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT qlen 1000 link/ether 54:4a:16:bb:b7:03 brd ff:ff:ff:ff:ff:ff 3: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether aa:fb:7f:5e:a8:d5 brd ff:ff:ff:ff:ff:ff
You can also find out about devices attached to USB or PCI buses using the well-known commands lsusb
and lspci
. There is information about them in the respective manuals and plenty of online guides, so I will not describe them any further here.
The really interesting information is in sysfs
, which is the next topic.
You can define sysfs
in a pedantic way as a representation of kernel objects, attributes and relationships. A kernel object is a directory, an attribute is a file, and a relationship is a symbolic link from one object to another.
From a more practical point of view, since the Linux device driver model, which was introduced in version 2.6, represents all devices and drivers as kernel objects. You can see the kernel's view of the system laid out before you by looking in /sys
, as shown here:
# ls /sys block bus class dev devices firmware fs kernel module power
In the context of discovering information about devices and drivers, I will look at three of the directories: devices
, class
, and block
.
This is the kernel's view of the devices discovered since boot and how they are connected to each other. It is organized at the top level by the system bus, so what you see varies from one system to another. This is the QEMU emulation of the Versatile Express:
# ls /sys/devices armv7_cortex_a9 platform system breakpoint software virtual
There are three directories that are present on all systems:
system
: This contains devices at the heart of the system, including CPUs and clocks.virtual
: This contains devices that are memory-based. You will find the memory devices that appear as /dev/null
, /dev/random
, and /dev/zero
in virtual/mem
. You will find the loopback device, lo
, in virtual/net
.platform
: This is a catch-all for devices that are not connected via a conventional hardware bus. This may be almost everything on an embedded device.The other devices appear in directories that correspond to actual system buses. For example, the PCI root bus, if there is one, appears as pci0000:00
.
Navigating this hierarchy is quite hard because it requires some knowledge of the topology of your system and the pathnames become quite long and hard to remember. To make life easier, /sys/class
and /sys/block
offer two different views of the devices.
This is a view of the device drivers presented by their type, in other words, it is a software view rather than a hardware view. Each of the subdirectories represents a class of driver and is implemented by a component of the driver framework. For example, UART devices are managed by the tty
layer and you will find them in /sys/class/tty
. Likewise, you will find network devices in /sys/class/net
, input devices such as the keyboard, the touchscreen, and the mouse in /sys/class/input
, and so on.
There is a symbolic link in each subdirectory for each instance of that type of device pointing to its representation in /sys/device
.
To take a concrete example, let's look at /sys/class/tty/ttyAMA0
:
# cd /sys/class/tty/ttyAMA0/ # ls close_delay flags line uartclk closing_wait io_type port uevent custom_divisor iomem_base power xmit_fifo_size dev iomem_reg_shift subsystem device irq type
The link device
references the hardware node for the device and subsystem
points back to /sys/class/tty
. The others are attributes of the device. Some are specific to a UART, such as xmit_fifo_size
and others apply to many types of device such as the interrupt number, irq
, and the device number dev
. Some attribute files are writable and allow you to tune parameters in the driver at runtime.
The dev
attribute is particularly interesting. If you look at its value, you will find the following:
# cat /sys/class/tty/ttyAMA0/dev 204:64
These are the major and minor numbers of this device. This attribute is created when the driver registered this interface and it is from this file that udev
and mdev
read that information if they are being used without the help of devtmpfs
.
There is one more view of the device model that is important: the block driver view that you will find in /sys/block
. There is a subdirectory for each block device. This example is taken from a BeagleBone Black:
# ls /sys/block/ loop0 loop4 mmcblk0 ram0 ram12 ram2 ram6 loop1 loop5 mmcblk1 ram1 ram13 ram3 ram7 loop2 loop6 mmcblk1boot0 ram10 ram14 ram4 ram8 loop3 loop7 mmcblk1boot1 ram11 ram15 ram5 ram9
If you look into mmcblk1
, which is the eMMC chip on this board, you can see the attributes of the interface and the partitions within it:
# cd /sys/block/mmcblk1 # ls alignment_offset ext_range mmcblk1p1 ro bdi force_ro mmcblk1p2 size capability holders power slaves dev inflight queue stat device mmcblk1boot0 range subsystem discard_alignment mmcblk1boot1 removable uevent
The conclusion, then, is that you can learn a lot about the devices (the hardware) and the drivers (the software) that are present on a system by reading sysfs
.