It’s been a while since I posted about Linux, or networking, for that matter. Between grad school and work projects, blogging about networking and Linux kinda took a back seat.
But I’m still working on improving my networking and Linux chops, along with everything else. The learning never really stops… yay.
(Yes, I am somewhat still able to find gaps that I consider life in between modes)
This morning, I’m writing this while having an espresso and two slices of toasted bread with cinnamon swirls, thinking about something that has probably happened to almost every Linux user at some point.
You plug in a USB drive… nothing happens.
Your Wi-Fi suddenly disappears after a kernel update.
Or a serial device shows up in /dev, but your program says “Permission denied.”
(Silently… I’m working through the chapter on the Linux administration book on device drivers, so I decided I might as well blog about it.)
At first it feels like Linux is being mysterious.
But most of the time the issue comes down to a few simple pieces working together:
- the Linux kernel
- device drivers
- the
/devinterface - and tools that help you see what the system actually detects
Once you understand how these pieces fit together, troubleshooting hardware on Linux becomes much more systematic.
(Note: the commands shown here are based on Ubuntu, which I think is awesome, and I use it as my primary Linux environment. Most will work on other distributions (not sure why you’re on it), though command output and package names may vary slightly.)
The Layers of a Linux System (let’s peel some onions)

At this point you might be looking at the screenshot and thinking something perfectly reasonable.
“Wait a minute… if your computer is already running Linux, why are you running Ubuntu Server inside a virtual machine?”
That’s a fair question.
The short answer is: because I plan to break things.
When you’re learning Linux administration, networking, or anything involving the kernel, there’s a very good chance you’re going to type a command that makes the system… unhappy. Maybe you remove the wrong package. Maybe you mess up networking. Maybe you try something with drivers or kernel modules and suddenly the system decides it’s done cooperating.
Doing that on the machine you actually depend on every day is not a great strategy.
So instead, I run Ubuntu Server in a VM. That way I can experiment, misconfigure things, fix them, break them again, and generally learn how the system behaves without turning my main computer into a very expensive paperweight.
Virtual machines are basically the IT version of a practice arena. If something goes sideways, I can just reboot the VM, restore a snapshot, or rebuild the server. No panic, no drama.
It also lets me run a more realistic server setup. Ubuntu Server doesn’t have the desktop environment, so everything happens in the terminal, which is closer to how real infrastructure is managed anyway.
So the VM becomes my little Linux lab where mistakes are expected and breaking things is part of the learning process.
And if the whole thing explodes… well, that’s what snapshots are for.
(So back to driver talk…)
A Linux system is generally organized into three layers:
- Hardware
- Kernel Space
- User Space
At the bottom is the hardware layer, which includes the physical components of your computer: CPU, memory, disks, network interfaces, and other devices.
Above that sits the kernel, which operates in kernel space. The kernel manages memory, processes, system resources, and device drivers.
Applications run in user space, which is separated from kernel space for stability and security. Programs cannot access hardware directly. Instead, they make requests to the kernel using system calls (the API the kernel exposes to applications).
The kernel processes those requests and communicates with hardware through device drivers.
(Here I’m grinning as I sound like a totally awesome Linux Engineer)

Device Drivers: The Translators (the bits babbler)
Device drivers allow the Linux kernel to communicate with hardware devices.
You can think of a driver as a translator.
Hardware speaks one language. Software speaks another. The driver sits in the middle translating instructions between the two.
Without drivers, Linux would not be able to (this means you got yourself a fancy paperweight):
- read disks
- send network packets
- accept keyboard input
- display graphics (yes… you can actually play games on your Linux machine, I have… Noob)
In Linux, many drivers are loaded dynamically as kernel modules (files typically ending in .ko). These modules allow the kernel to add or remove hardware support without rebuilding the entire kernel.
That’s why commands like lsmod and modprobe exist, they allow you to inspect and load these modules.
However, it’s worth noting that some drivers are built directly into the kernel itself. These built-in drivers will not appear in lsmod, which is normal for many essential components like CPUs or basic disk controllers.
Everything in Linux Is a File (and yes, I know you’re scratching your head and asking… why?)
One of the most famous design ideas in Linux and Unix systems is the phrase:
“Everything is a file.”
(Not necessarily your Word file, but a file in the same spirit and essence)
At first, this may sound strange. A keyboard isn’t a file. A hard drive isn’t a file. And a network card definitely isn’t a file.
(Remember C, <stdio.h>… or maybe not)
But in Linux, the operating system represents many system resources, including hardware devices, as file-like interfaces.
The reason for this is simplicity and consistency.
Think of Linux like a plumbing system in a house (or an apartment or a villa overlooking the ocean… hey… one can dream right).
Instead of having a different control system for everything, it all connects through pipes. Water flows through the same plumbing whether it’s going to the kitchen sink, the shower, or the washing machine.
(Do not PM me to help fix your plumbing issues, I’m just using it as an analogy, I can do electrical, but I suck at plumbing, or carpentry, or masonry, or roofing)
Linux works in a similar way. Instead of creating completely different interfaces for disks, keyboards, network cards, and other hardware, the system exposes them as files. Programs simply read from or write to these “pipes,” and the kernel routes the request to the correct device driver.
In other words, the /dev directory is like a control panel of pipes connecting software to hardware.
Instead of creating a different way to interact with every type of hardware, Linux provides a single, unified interface: the file system. Programs can interact with devices using the same basic operations they already use for files, such as reading, writing, or opening.
This design allows applications to communicate with hardware through device files, which live in the /dev directory.
For example:
/dev/sdarepresents a disk/dev/ttyrepresents a terminal/dev/nullrepresents a device that discards data
/dev/null
This device simply discards anything written to it, the famous “black hole” of the Linux world; data goes in and never comes out. Incredibly useful, you can use it to send unwanted output there when they don’t want a command to clutter the terminal.
(And if you’ve worked with Linux long enough, you’ve probably also wished there was a /dev/null for emails, meetings, and certain error messages.)
Anyway… When a program reads from or writes to one of these device files, the request is handled by the kernel, which passes it to the appropriate device driver.
(The kernel’s got you, with a side of coleslaw, chicken for lunch?)
The device file serves as the interface between user-space programs and kernel-space drivers.
This approach simplifies system design. Tools and programs don’t need special logic for every type of hardware. They just interact with files, and the kernel takes care of the rest.
It’s one of the reasons Linux systems are so flexible and powerful.
(Hell yeah… Feel that Linux power yet?… Must be the third cup of espresso… )

Block Devices vs Character Devices
Linux devices generally fall into two categories:
- block devices
- character devices
You can identify them using:
ls -l /dev
Example output:
brw-rw---- 1 root disk 8,0 sda
crw-rw-rw- 1 root tty 5,0 tty
The first letter indicates the device type:
- b → block device
- c → character device
(Like duh! Its kinda obvious… b… c…)
Block Devices
Block devices store data in fixed-size blocks.
Examples include:
- hard drives
- SSDs
- USB storage devices
Typical device names:
/dev/sda
/dev/sdb
/dev/nvme0n1
These devices usually contain filesystems and partitions.
Character Devices (No… No… It’s not about Batman’s utility belt)
Character devices process data as a continuous stream.
Examples include:
- keyboards
- serial ports
- terminal devices

Device Detection and the Role of udev (udev, idev, wealldev haha)
So how do these device files appear?
This is where udev comes in.
udev runs in user space and listens for hardware events generated by the kernel. When hardware is detected, it automatically creates the appropriate device file in /dev.
For example, when you plug in a USB drive:
- the kernel detects the hardware
- a hardware event is generated
udevreceives the eventudevcreates a device file
Example:
/dev/sdb
Important distinction:
- device drivers run in kernel space
- udev runs in user space

Real-World Troubleshooting on Ubuntu (insert your distro here; if the command or output is different, Google it LOL)
Understanding these concepts becomes extremely useful when something breaks.
(Ask Ubuntu works too)
Here are a few real troubleshooting scenarios.
Scenario 1: The “Missing” USB Drive
Step 1 — Check Kernel Detection
Run:
dmesg | tail
Or on modern Ubuntu systems:
journalctl -k --since "5 minutes ago"
Example:
usb 2-1: new high-speed USB device detected
usb-storage 2-1: USB Mass Storage device detected
If you see messages like this, the kernel detected the device and loaded a driver.
Step 2 — Check Hardware Recognition
Run:
lsusb
Example:
Bus 002 Device 004: Kingston USB Flash Drive
Step 3 — Check Device Interface
Run:
lsblk
Example:
sda 256G
sdb 32G
If /dev/sdb exists but there is no partition like /dev/sdb1, the disk may not be formatted.
Check with:
sudo fdisk -l
Mount manually if needed:
sudo mount /dev/sdb1 /mnt

Scenario 2: Network Interface Not Working After a Kernel Update
Step 1 — Verify Hardware
Run:
lspci -k
Example:
Network controller: Intel Wireless Adapter
Kernel driver in use: iwlwifi
(Drivers in Linux are commonly loaded as kernel modules — .ko files — which is why tools like lsmod and modprobe manage them.)
Step 2 — Check Loaded Modules
Run:
lsmod
Look for your driver module (for example iwlwifi).
Step 3 — Load the Driver
Run:
sudo modprobe iwlwifi
If it fails, inspect logs:
journalctl -k | grep wifi
Often the issue is missing firmware provided by:
linux-firmware

Scenario 3: Permission Denied on a Serial Device
Step 1 — Locate the Device
Common device files:
/dev/ttyUSB0
/dev/ttyACM0
Step 2 — Check Permissions
Run:
ls -l /dev/ttyUSB0
Example:
crw-rw---- 1 root dialout ttyUSB0
Step 3 — Add Your User to the Group
Instead of using sudo every time:
sudo usermod -aG dialout $USER
Log out and log back in.
What I think (and this may not be the same thoughts in your head)
When troubleshooting Linux systems, administrators usually start with one simple question:
What hardware does the kernel actually see?
(KFC anyone?)
Commands that help answer that quickly:
lsblk— shows storage deviceslspci— lists PCI hardwarelsusb— lists USB devicesdmesg/journalctl -k— shows kernel hardware detection logs
One of the reasons Linux remains powerful is its transparency.
Instead of hiding hardware interactions behind layers of abstraction, Linux exposes them in ways administrators can inspect and understand.
Once you realize that:
- the kernel manages hardware
- drivers (often loaded as modules) translate instructions
- hardware appears as files in /dev
- udev dynamically manages those devices
the system becomes much easier to reason about.
If anyone is wondering where some of this refresher thinking is coming from, I’ve been spending some time going through Mastering Linux Administration by Alexandru Calcatinge and Julian Balog.
(No… They’re not my sponsor… but it would be cool if I got a newer edition free book out of this… LOL)

I’m sure there’s a newer edition out there by now, and there’s probably something you have on your shelf that’s even better (or not). But this one works well for me and does a good job walking through the fundamentals of how Linux systems actually operate.
What I like about it is that it spends time explaining how the pieces fit together, things like how the kernel interacts with hardware, how drivers get loaded, and how Linux exposes devices through /dev. Those sections were the ones that got me thinking more about how Linux talks to hardware in the first place, which eventually led to this post.
(This jives really well with my For Dummies first philosophy)
Sometimes going back to the basics is the best way to sharpen your understanding of how the system really works.
(Somehow in my head, I am re-reading this section in a somewhat bastardized British accent; maybe I’m just watching too many documentaries, plus I can’t do a Morgan Freeman reading voice in my head… Wait… Yep, I can read in my head using James Earl Jones voice…)
What About You? What’s the strangest hardware issue you’ve had to troubleshoot on Ubuntu or Linux?
Or if you’re just starting out with Linux, let me know how it’s going.
(Or if you’re a Kali fan boy, how’s that WiFi going after your install… Ha)