Explore Hardware Devices in Linux

CompTIABeginner
Practice Now

Introduction

In this lab, you will learn the essential skills to explore, identify, and inspect hardware devices within a Linux environment. You will gain hands-on experience with powerful command-line utilities to understand how the operating system interacts with physical components. The objective is to build a foundational understanding of hardware management in Linux, which is crucial for system administration, performance tuning, and troubleshooting.

You will start by listing block devices using lsblk and lshw to get an overview of storage. Following that, you will use udevadm to inspect detailed device properties and rules. The lab will then guide you through viewing the PCI and SCSI bus hierarchies to see how devices are connected. Finally, you will delve into low-level system information by examining the /proc and /sys virtual filesystems, giving you a comprehensive view of your system's hardware from the kernel's perspective.

List Block Devices with lsblk and lshw

In this step, you will learn how to identify and list the block devices connected to your system. Block devices are storage devices that transfer data in fixed-size blocks, such as hard drives, solid-state drives, and USB flash drives. We will use two common commands for this purpose: lsblk and lshw.

First, let's use the lsblk command to get a tree-like view of all available block devices. This command reads the sysfs filesystem and udev database to gather information.

Execute the lsblk command in your terminal:

lsblk

You will see an output similar to this, listing the devices and any partitions they contain.

NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0    7:0    0  89.4M  1 loop /snap/lxd/31333
loop1    7:1    0     4K  1 loop /snap/bare/5
loop2    7:2    0  63.9M  1 loop /snap/core20/2318
loop3    7:3    0 242.9M  1 loop /snap/firefox/2710
loop4    7:4    0 244.5M  1 loop /snap/firefox/2800
loop5    7:5    0 349.7M  1 loop /snap/gnome-3-38-2004/140
loop6    7:6    0 349.7M  1 loop /snap/gnome-3-38-2004/143
loop7    7:7    0  91.7M  1 loop /snap/gtk-common-themes/1535
loop9    7:9    0    87M  1 loop /snap/lxd/28373
loop10   7:10   0  73.9M  1 loop /snap/core22/2010
loop11   7:11   0  38.8M  1 loop /snap/snapd/21759
loop12   7:12   0  50.9M  1 loop /snap/snapd/24718
loop13   7:13   0  63.8M  1 loop /snap/core20/2599
vda    252:0    0    40G  0 disk
├─vda1 252:1    0     1M  0 part
├─vda2 252:2    0   200M  0 part /boot/efi
└─vda3 252:3    0  39.8G  0 part /var/snap/firefox/common/host-hunspell
                                 /

Your primary disk name may be vda, sda, or nvme0n1 depending on the VM image. In the next steps, always use the disk name that lsblk shows for the device mounted at /.

Here's a brief explanation of the columns:

  • NAME: The device name.
  • MAJ:MIN: The major and minor device numbers, used by the kernel to identify the device.
  • RM: Removable device (1 if yes, 0 if no).
  • SIZE: The size of the device.
  • RO: Read-only device (1 if yes, 0 if no).
  • TYPE: The type of device (e.g., disk, part, loop).
  • MOUNTPOINTS: Where the device is mounted in the filesystem.

While lsblk is great for a quick overview, the lshw (list hardware) command can provide much more detailed information. The lshw command may not be installed by default. Let's install it first.

sudo apt-get update && sudo apt-get install -y lshw

Once the installation is complete, you can use lshw to get detailed information about specific classes of hardware. For example, to see details about storage controllers (like your SATA or NVMe controller), you can use the -class storage option.

sudo lshw -class storage

The output will show information about the storage interface itself.

  *-pnp00:03
       product: PnP device PNP0700
       physical id: 3
       capabilities: pnp
  *-ide
       description: IDE interface
       product: 82371SB PIIX3 IDE [Natoma/Triton II]
       vendor: Intel Corporation
       physical id: 1.1
       bus info: pci@0000:00:01.1
       version: 00
       width: 32 bits
       clock: 33MHz
       capabilities: ide isa_compat_mode bus_master
       configuration: driver=ata_piix latency=0
       resources: irq:0 ioport:1f0(size=8) ioport:3f6 ioport:170(size=8) ioport:376 ioport:c060(size=16)
  *-scsi
       description: SCSI storage controller
       product: Virtio block device
       vendor: Red Hat, Inc.
       physical id: 4
       bus info: pci@0000:00:04.0
       version: 00
       width: 64 bits
       clock: 33MHz
       capabilities: scsi msix bus_master cap_list
       configuration: driver=virtio-pci latency=0
       resources: irq:0 memory:fe000000-fe000fff memory:fe001000-fe001fff

To get more detailed information about the partitions and logical volumes, which is comparable but more detailed than lsblk, use the -class volume option.

sudo lshw -class volume

This command provides a wealth of information, including logical names, serial numbers, and capabilities of each partition.

  *-volume:0
       description: BIOS Boot partition
       vendor: EFI
       physical id: 1
       bus info: scsi@0:0.0.0,1
       logical name: /dev/vda1
       serial: xxxx-xxxx
       size: 1MiB
       capacity: 1MiB
       capabilities: primary
  *-volume:1
       description: EFI partition
       vendor: EFI
       physical id: 2
       bus info: scsi@0:0.0.0,2
       logical name: /dev/vda2
       serial: XXXX-XXXX
       size: 200MiB
       capacity: 200MiB
       capabilities: boot fat initialized
       configuration: FATs=32 filesystem=fat mount.fstype=vfat mount.options=rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro state=mounted
  *-volume:2
       description: Linux filesystem
       physical id: 3
       bus info: scsi@0:0.0.0,3
       logical name: /dev/vda3
       size: 39GiB
       capacity: 39GiB
       capabilities: primary ext4 initialized
       configuration: filesystem=ext4 lastmountpoint=/ modified=2024-xx-xx mounted=2024-xx-xx state=mounted

By using lsblk and lshw, you can get both a high-level and a detailed, low-level view of the storage devices on your Linux system.

Inspect Device Properties with udevadm

In the previous step, you learned how to list block devices. Now, you'll dive deeper and inspect the specific properties of these devices using the udevadm command. udev is the device manager for the Linux kernel, which dynamically manages device nodes in the /dev directory. The udevadm command is the control tool for udev, allowing you to query the udev database for detailed device information. This is particularly useful before creating custom udev rules to manage devices automatically.

Let's inspect the properties of the main disk that contains your root filesystem. First, identify the root partition and its parent disk:

ROOT_PARTITION=$(findmnt -n -o SOURCE /)
DISK_NAME=$(lsblk -no PKNAME "$ROOT_PARTITION")
echo "$ROOT_PARTITION -> /dev/$DISK_NAME"

To display the properties of that disk in a simple key-value format, execute the following command. The -q property flag tells udevadm to query the database for all known properties of the device, and -n "/dev/$DISK_NAME" specifies the device node name.

udevadm info -q property -n "/dev/$DISK_NAME"

The output will be a list of environment variables that describe the device. Your exact values will differ, but the output should look similar to this:

DEVPATH=/devices/pci0000:00/0000:00:04.0/nvme/nvme0/nvme0n1
DEVNAME=/dev/nvme0n1
DEVTYPE=disk
MAJOR=259
MINOR=0
SUBSYSTEM=block
USEC_INITIALIZED=xxxxxxxxx
ID_MODEL=Alibaba Cloud Elastic Block Storage
ID_REVISION=1.0
ID_SERIAL=Alibaba_Cloud_Elastic_Block_Storage_xxxxxxxxxxxx
ID_SERIAL_SHORT=xxxxxxxxxxxx
ID_TYPE=disk
ID_PATH=pci-0000:00:04.0-nvme-1
ID_PATH_TAG=pci-0000_00_04_0-nvme-1
DEVLINKS=/dev/disk/by-id/nvme-... /dev/disk/by-path/pci-0000:00:04.0-nvme-1
TAGS=:systemd:

This output provides valuable details such as the ID_MODEL, ID_PATH, and a unique ID_SERIAL. These properties are often used to write udev rules that apply to a specific device, regardless of the order it was detected by the kernel.

For an even more detailed, hierarchical view, you can query the device using its sysfs path. First, find the sysfs path for the disk you selected:

udevadm info -q path -n "/dev/$DISK_NAME"

The output will be the device's path within the /sys filesystem:

/devices/pci0000:00/0000:00:04.0/nvme/nvme0/nvme0n1

Now, use this path with the -a (attribute walk) and -p (path) flags to see all device attributes from the parent devices up to the specified device. This gives a complete picture of the device and its parent controllers.

udevadm info -a -p "$(udevadm info -q path -n "/dev/$DISK_NAME")"

This command produces a much longer output, showing attributes for the block device itself, as well as its parent storage controller and PCI device. This level of detail is essential for advanced device management and troubleshooting. We won't show the full output here due to its length, but feel free to explore it.

View the PCI and SCSI Bus Hierarchy

In this step, you'll explore how devices are organized on system buses. A bus is a communication system that transfers data between components inside a computer. We will focus on two important buses: PCI (Peripheral Component Interconnect) and SCSI (Small Computer System Interface). Understanding their hierarchy helps in diagnosing hardware issues and understanding how devices like your hard drive are connected to the system.

First, let's examine the PCI bus, which connects most of the high-speed components on the motherboard. The lspci command is the standard tool for this. The pciutils package which provides this command is usually pre-installed, but we'll ensure it is.

sudo apt-get update && sudo apt-get install -y pciutils

Now, to display the PCI bus hierarchy in a tree-like structure, use the lspci command with the -t option.

lspci -t

The output will look something like this, showing the connections between buses and devices:

-[0000:00]-+-00.0
           +-01.0
           +-01.1
           +-01.3
           +-04.0
           \-05.0

This tree shows the connections, but not what the devices are. To make it more useful, add the -v (verbose) option. This will include device names and the kernel driver in use for each device. Since the output can be long, we'll pipe it to more so you can scroll through it. Press the spacebar to scroll down and q to quit.

lspci -tv | more

The output will be much more detailed:

-[0000:00]-+-00.0  Intel Corporation 440FX - 82441FX PMC [Natoma]
           +-01.0  Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
           +-01.3  Intel Corporation 82371AB/EB/MB PIIX4 ACPI
           +-02.0  Cirrus Logic GD 5446
           +-03.0  Red Hat, Inc. Virtio console
           +-04.0  Intel Corporation QEMU NVM Express Controller
           +-05.0  Red Hat, Inc. Virtio network device
           \-06.0  Red Hat, Inc. Virtio memory balloon

From this output, you can see the specific hardware components connected to the PCI bus, such as the NVMe storage controller and other virtual devices.

Next, let's look at the SCSI bus. In this VM, the main disk may be exposed through NVMe instead of Virtio or SCSI, but you can still explore any SCSI devices that are present. A user-friendly way to view this information is with the systool command. Let's install the sysfsutils package that provides it.

sudo apt-get install -y sysfsutils

Now, use systool with the -b scsi option to list devices on the SCSI bus.

systool -b scsi

This command will show the devices attached to the SCSI bus:

Bus = "scsi"

  Device = "host0"
  Device = "host1"

Examine Low-Level System Resources in /proc

In this step, you will delve into the /proc virtual filesystem to inspect low-level system resources. The /proc filesystem doesn't contain real files on disk; instead, it's a direct interface to the kernel's data structures. By reading files in /proc, you can get a real-time look at how the system is managing hardware resources like DMA channels, interrupts, and I/O ports.

First, let's look at Direct Memory Access (DMA) channels. DMA allows certain hardware devices to access system memory directly, without involving the CPU, which improves performance. To see which DMA channels are currently in use, you can view the contents of the /proc/dma file.

cat /proc/dma

The output is typically very simple, especially on modern or virtualized systems.

 4: cascade

This output shows the registered DMA channels. The cascade channel is used to chain older-style interrupt controllers and is often the only one listed on modern hardware.

Next, let's examine interrupt requests (IRQs). When a hardware device needs the CPU's attention, it sends an interrupt signal. The /proc/interrupts file provides statistics on how many interrupts have been received for each IRQ number.

cat /proc/interrupts

The output shows a detailed breakdown of interrupt activity per CPU core.

           CPU0
  0:         10   IO-APIC   2-edge      timer
  1:          2   IO-APIC   1-edge      i8042
  8:          1   IO-APIC   8-edge      rtc0
  9:          0   IO-APIC   9-fasteoi   acpi
 11:        ...   IO-APIC  11-fasteoi   ata_piix, uhci_hcd
 12:          4   IO-APIC  12-edge      i8042
NMI:          0   Non-maskable interrupts
LOC:      ...   Local timer interrupts
...

Here's what the columns mean:

  • The first column is the IRQ number.
  • The CPU0 column (and other CPU columns if present) shows the number of interrupts handled by that CPU core.
  • The last column shows the name of the device driver associated with that interrupt. This is very useful for debugging hardware conflicts.

Finally, let's look at I/O ports. These are special memory addresses that the CPU uses to communicate directly with hardware devices. The /proc/ioports file lists the I/O port regions that are currently reserved for devices. Since the list can be long, it's best to view it with less. You can scroll with the arrow keys and press q to exit.

less /proc/ioports

You will see a list of memory ranges and the devices using them.

0000-0cf7 : PCI Bus 0000:00
  0020-0021 : PIC1
  0040-0043 : timer0
  0050-0053 : timer1
  0060-0060 : keyboard
  0064-0064 : keyboard
  0070-0077 : rtc0
  0080-008f : dma page reg
  00a0-00a1 : PIC2
  00c0-00df : dma2
  00f0-00ff : fpu
0170-0177 : 0000:00:01.1
  0170-0177 : ata_piix
01f0-01f7 : 0000:00:01.1
  01f0-01f7 : ata_piix
...

This output shows the memory address range and the device that has claimed it. For example, you can see ranges for the keyboard, timers, and the ata_piix disk controller we saw in the previous step.

Explore Device Information in the /sys Filesystem

In this final step, you will explore the sysfs filesystem, mounted at /sys. While /proc provides information about processes and some hardware resources, /sys offers a more structured view of the system's device model. It exports a hierarchical representation of kernel objects, devices, and drivers. Many of the tools you've used in previous steps, like lsblk and udevadm, get their information by reading from /sys.

First, let's look at how block devices are represented. The /sys/block directory contains a subdirectory for each block device known to the system.

List the contents of /sys/block to see the devices:

ls -l /sys/block

The output shows the block devices, including the loop devices and your main disk. Notice that these are symbolic links pointing to their actual locations within the /sys/devices hierarchy.

total 0
lrwxrwxrwx 1 root root 0 Jan  1 00:00 loop0 -> ../devices/virtual/block/loop0
lrwxrwxrwx 1 root root 0 Jan  1 00:00 loop1 -> ../devices/virtual/block/loop1
...
lrwxrwxrwx 1 root root 0 Jan  1 00:00 nvme0n1 -> ../devices/pci0000:00/0000:00:04.0/nvme/nvme0/nvme0n1

Find the parent disk for your root filesystem again, then inspect that directory. This directory contains various files that represent the attributes of the device.

ROOT_PARTITION=$(findmnt -n -o SOURCE /)
DISK_NAME=$(lsblk -no PKNAME "$ROOT_PARTITION")
ls /sys/block/"$DISK_NAME"

You will see a list of files and directories:

alignment_offset  diskseq  holders  nvme0n1p2  ro       uevent
bdi               events   inflight nvme0n1p3  size     wwid
capability        events_async integrity power  slaves
dev               events_poll_msecs mq    queue  stat
device            ext_range nsid    range  subsystem
discard_alignment hidden    nvme0n1p1 removable trace

Each file holds a specific piece of information. For example, to find the size of the disk, you can read the size file.

cat /sys/block/"$DISK_NAME"/size

The output will be a number:

83886080

This number represents the size of the device in 512-byte sectors. You can also see directories for each partition, such as nvme0n1p1, nvme0n1p2, and nvme0n1p3, which contain their own sets of attributes. On other images, the partition names may use a different device prefix.

Next, let's explore how devices are organized by bus type in the /sys/bus directory. This provides an alternative way to navigate the device hierarchy.

ls /sys/bus

You'll see a list of different bus types supported by the kernel:

acpi  amba  clocksource  container  cpu  event_source  hid  i2c  i8042  ide  mdio_bus  memory  pci  pci_express  platform  scsi  serial  serio  soc  system  usb  virtio  workqueue

Even if your storage disk is not a Virtio block device, the VM may still expose other Virtio devices. Let's look inside the /sys/bus/virtio/devices directory to list them.

ls -l /sys/bus/virtio/devices

The output shows the Virtio devices, identified by their device IDs. These are also symbolic links pointing back to the main device tree.

total 0
lrwxrwxrwx 1 root root 0 Jan  1 00:00 virtio0 -> ../../../devices/pci0000:00/0000:00:05.0/virtio0
lrwxrwxrwx 1 root root 0 Jan  1 00:00 virtio1 -> ../../../devices/pci0000:00/0000:00:04.0/virtio1

By exploring /sys, you can directly access the raw data that higher-level tools use to report on system hardware. It's a powerful way to understand how the Linux kernel sees and organizes devices.

Summary

In this lab, you learned to identify and inspect hardware devices in a Linux environment. You practiced using the lsblk command to list block devices and their partitions in a tree-like format, and the lshw command to obtain more detailed hardware specifications. The lab also covered using udevadm to inspect device properties managed by the udev subsystem, and how to view the system's bus hierarchies for PCI and SCSI devices.

Furthermore, you explored the low-level information presented by the kernel through pseudo-filesystems. You examined the /proc filesystem to view raw system resource data and navigated the /sys filesystem to explore a structured representation of the system's devices and their attributes. This provided a comprehensive understanding of how to find and interpret hardware information directly from the operating system.