May 10, 2026

How D-Bus works in Embedded Linux

D-Bus often looks more complicated than it really is. Once you understand names, object paths, interfaces, methods, properties and signals, the whole model becomes much easier to reason about.

When you boot an embedded Linux device, there is a good chance that half of your system already talks over D-Bus. NetworkManager exposes network state. BlueZ exposes Bluetooth adapters and devices. systemd exposes units, jobs and system state. ModemManager does the same for cellular modems.

At some point, your own daemon may need to expose a D-Bus API too. That is where many developers get uncomfortable. At first, D-Bus looks strange. There are bus names, object paths, interfaces, methods, properties, signals, unique names, well-known names and XML introspection. It feels like a lot.
But the core idea is simple:

D-Bus is just a local message bus.

Or, less formally: D-Bus is what happens when Unix sockets grow a type system, names, routing, signals, introspection and access control.
Under the hood, local D-Bus communication commonly uses Unix domain sockets. But instead of each daemon inventing its own private socket protocol, D-Bus gives the system a shared way to expose local APIs.
Processes connect to the bus. They send messages. The bus routes those messages to the right destination. That is the mental model you need first.

overview of d bus system diagram

ⓘ Note

Strictly speaking, D-Bus is both a message bus system and a protocol. In practice, embedded developers usually meet it through the system bus daemon and tools such as busctl, dbus-send or gdbus.

System bus and session bus


There are usually two kinds of D-Bus buses:

  • The system bus is used by system services. This is the bus you usually care about in embedded Linux. Network configuration, Bluetooth, modems, system services, power management and product-specific daemons usually live here.
  • The session bus is associated with a user session. It is common on desktop Linux systems, where graphical applications need to talk to each other.

In headless embedded Linux, the session bus is often irrelevant. So when someone says “D-Bus” in an embedded Linux context, they usually mean the system bus.

system bus vs session bus comparison

The four coordinates of a D-Bus call


To call something over D-Bus, you usually need four things. Each part answers a different question.

  • The bus name says which service you want to talk to.
  • The object path says which object inside that service you want to address.
  • The interface says which contract you want to use.
  • The method says what operation you want to call.

Once you understand these four coordinates, D-Bus becomes much less mysterious.

the four coordinates of a d bus call
A D-Bus call is usually identified by a bus name, object path, interface and method.

Services own names


A process connected to D-Bus gets a unique name, something like :1.42
This name identifies a specific connection to the bus. But clients usually do not want to talk to :1.42. They want to talk to a stable service name: org.bluez This is called a well-known name.

A service owns a well-known name so clients can find it without caring about the current unique connection name. Your client should not care whether BlueZ is currently :1.42, :1.77 or something else. Your client talks to org.bluez.

service naming comparison diagram
Think of the unique name as the temporary connection ID, and the well-known name as the stable public address of the service.

Object paths are public endpoints


Inside a service, functionality is exposed through object paths.
An object path looks like a filesystem path, but it is not a file. It is a logical address of an object exposed by a D-Bus service. Also, a D-Bus object is not necessarily your C++ object. That distinction matters. A D-Bus object is part of your public IPC API. It is an endpoint that other processes can address. How you implement it internally is a separate decision.

⚠ Warning

Do not design your D-Bus API by blindly exposing your internal class hierarchy. That is how implementation details become public contracts.

d bus object paths diagram overview
Object paths look like filesystem paths, but they are logical endpoints exposed by a service.

Interfaces are contracts


An object path alone does not say much. The interface defines what the object can do. For example, a device object could expose several interfaces:

  • com.gr8software.Device.Power
  • com.gr8software.Device.Diagnostics
  • com.gr8software.Device.Update

Each interface groups related methods, properties and signals. This is the contract between the service and its clients. The object is where the contract is exposed. The interface is what the contract contains.

implementing interfaces in a tech diagram
One object can expose multiple interfaces. Each interface is a contract.

Methods, properties and signals


Most D-Bus APIs are built from three basic concepts:

  • Methods are commands: client calls a method when it wants a service to do something.
  • Properties are state: client reads a property when it wants to know the current state of something. Some properties may also be writable.
  • Signals are events: service emits a signal when something happened and interested clients can react to it.

This simple distinction helps a lot when designing your own D-Bus API.

methods properties and signals infographic
Methods are commands. Properties are state. Signals are events.

What happens during a method call


A method call is just a message exchange. Imagine a client wants to call com.gr8software.Device.Power.Reboot()

The flow looks like this:

method call process flow diagram
The bus routes method calls and replies. The service owns the actual behavior.

The important part is that the bus is not the service. The bus does not reboot the device. The bus does not decide whether rebooting is safe. The bus only delivers the message. Your service owns the behavior. Your service owns the validation. Your service owns the security decision. We will come back to that when we talk about polkit.

Why D-Bus is useful in embedded Linux


Embedded Linux systems are often built from independent daemons. One daemon owns networking. Another owns Bluetooth. Another owns updates. Another owns diagnostics. Another owns the UI. Another owns factory test logic. These processes need to communicate.
You can solve that with private Unix sockets, custom protocols, files in /tmp, signals, shared memory or HTTP endpoints on localhost. Sometimes those are valid choices. But when you need a stable local control API between processes, D-Bus is often a good fit. It gives you names, discovery, typed messages, properties, signals and a common toolset. That is why so many Linux system services expose D-Bus APIs.

What D-Bus is not


D-Bus is useful, but it is not the answer to every IPC problem. D-Bus is best used for control plane APIs. Start this operation. Read this state. Notify me when this changed. For high-volume data plane traffic, you probably want something else. Use D-Bus where it fits.

⚠ Warning

Do not stream video frames over D-Bus. Do not push large firmware images through D-Bus if a file descriptor or file path would be a better contract.

what d bus is and isn t
D-Bus is useful for local control plane APIs, but it is not the right tool for everything.

A simpler way to think about D-Bus


If you remember only one thing, remember this:

💡 Tip

D-Bus is a local message bus where services expose objects, objects implement interfaces, and clients exchange method calls, replies, properties and signals with them.

That is it. The terminology looks intimidating, but the model is small. In the next post, we will use this model to explore real D-Bus APIs with busctl and introspection. Because once you can read an existing D-Bus API, writing your own becomes much less scary.