Em computação, D-Bus ou DBus (acrônimo para Desktop Bus, em inglês, ou Barramento de área de trabalho, em português), um barramento de software, é um mecanismo de comunicação entre processos (CIP) e chamada de procedimento remoto que possibilita a comunicação entre vários programas de computador (isto é, processos) rodando simultaneamente na mesma máquina. O D-Bus foi desenvolvido como parte do projeto freedesktop.org, iniciado por Havoc Pennington da Red Hat para padronizar serviços fornecidos pelos ambientes de desktop do Linux como GNOME e KDE.

O projeto freedesktop.org também desenvolveu uma biblioteca de software livre e de código aberto chamada libdbus, como uma implementação de referência da especificação. Esta biblioteca é geralmente confundida com o próprio D-Bus. Outras implementações da biblioteca cliente do D-Bus também existem, como GDBus (GNOME), QtDBus (Qt/KDE), dbus-java e sd-bus (parte do systemd).

Visão geral D-Bus é um mecanismo de comunicação entre processos inicialmente concebido para substituir os sistemas de comunicação de componentes de software usados pelos ambientes de desktop Linux GNOME e KDE (CORBA e DCOP, respectivamente). Os componentes desses ambientes de desktop são normalmente distribuídos em muitos processos, cada um fornecendo apenas alguns - normalmente um - serviços. Esses serviços podem ser usados por aplicativos clientes regulares ou por outros componentes do ambiente de desktop para executar suas tarefas.

Devido ao grande número de processos envolvidos - incluindo processos que fornecem os serviços e os clientes acessando-os - o estabelecimento de comunicações CIP um-para-um entre todos torna-se uma abordagem ineficiente e pouco confiável. Em vez disso, o D-Bus fornece uma abstração de barramento de software que reúne todas as comunicações entre um grupo de processos em um único canal virtual compartilhado. Processos conectados a um barramento não sabem como ele é implementado internamente, mas a especificação D-Bus garante que todos os processos conectados ao barramento possam se comunicar entre si através dele.

Os ambientes de desktop Linux aproveitam as facilidades do D-Bus instanciando não um barramento, mas muitos:

um único barramento de sistema, disponível para todos os usuários e processos do sistema, que fornece acesso aos serviços do sistema (ou seja, serviços fornecidos pelo sistema operacional e também por quaisquer daemons do sistema) um barramento de sessão para cada sessão de login do usuário, que fornece serviços de área de trabalho para aplicativos do usuário na mesma sessão da área de trabalho e permite a integração da sessão da área de trabalho como um todo

Um processo pode se conectar a qualquer número de barramento, desde que tenha acesso a eles. Na prática, isso significa que qualquer processo do usuário pode se conectar ao barramento do sistema e ao seu barramento de sessão atual, mas não aos barramentos de sessão de outro usuário, ou mesmo a um barramento de sessão diferente pertencente ao mesmo usuário. A última restrição pode mudar no futuro se todas as sessões do usuário forem combinadas em um único barramento do usuário.

O D-Bus fornece recursos adicionais ou simplifica a funcionalidade existente para os aplicativos, incluindo compartilhamento de informações, modularidade e separação de privilégios. Por exemplo, informações sobre uma chamada de voz recebida via Bluetooth ou Skype podem ser propagadas e interpretadas por qualquer reprodutor de música atualmente em execução, que pode reagir alterando o volume ou pausando a reprodução até que a chamada seja finalizada.

O D-Bus também pode ser usado como uma estrutura para integrar diferentes componentes de um aplicativo de usuário. Por exemplo, um pacote de escritório pode se comunicar através do barramento de sessão para compartilhar dados entre um processador de texto e uma planilha.

Especificação D-Bus

Modelo de Barramento Cada conexão a um barramento é identificada no D-Bus através de um nome de barramento.O nome de barramento consiste de duas ou mais strings separadas por ponto que podem conter letras, dígitos, traços e underscores - um nome de domínio reverso. Um exemplo de nome de barramento válido é org.freedesktop.NetworkManager.

Quando um processo se conecta a um barramento, o barramento dá para a conexão um nome de barramento especial chamado nome único de conexão (”unique connection name”, em inglês). Nomes de barramento desse tipo são imutáveis - é garantido que eles não mudarão enquanto a conexão existir - e, mais importante, eles não podem ser reutilizados enquanto o barramento estiver ativo. Isso significa que nenhuma outra conexão àquele barramento terá o mesmo nome único de conexão, mesmo que um mesmo processo feche a conexão ao barramento e a abra de novo. Nomes únicos de conexão são facilmente reconhecíveis porque eles iniciam com o caractere de dois-pontos :, cuja utilização é proibida em outras aplicações. Um exemplo de nome único de conexão é :1.1553 (os caracteres depois dos dois-pontos não possuem nenhum significado especial).

Um processo pode pedir mais nomes de barramento para sua conexão, desde que nenhum nome pedido já esteja sendo usado por outra conexão ao barramento. No linguajar de D-Bus, diz-se que quando um nome de barramento está sendo usado por uma conexão, essa conexão possui aquele nome. Neste sentido, nomes de barramento não podem ser possuídos por duas conexões ao mesmo tempo, mas, diferente dos nomes únicos de conexão, os nomes de barramento podem ser reutilizados se estiverem disponíveis: um processo pode possuir um nome de barramento que foi liberado - propositalmente ou não - por outro processo.

A ideia por trás destes nomes de barramento adicionais, comumente chamados de nomes bem-conhecidos (”well-known names”, em inglês), é fornecer outra forma de se referir a um serviço utilizando um nome de barramento definido previamente. Por exemplo, o serviço que reporta a data e hora atual no barramento de sistema existe em um processo cuja conexão possui o nome de barramento org.freedesktop.timedate1, independentemente de qual processo é.

Nomes de barramento podem ser usados como uma forma de implementar aplicações de instância singular (uma segunda instância da aplicação perceberia que o nome já está sendo utilizado). Também pode ser usado para monitorar o ciclo de vida de um processo, já que o barramento envia uma notificação quando o nome de barramento é liberado devido ao encerramento de um processo.

Modelo de objeto Por causa da sua concepção original como um substituto para diversos componentes orientados a sistemas de comunicação, o D-Bus compartilha com seus antecessores um modelo de objeto no qual se expressa a semântica das comunicações entre clientes e serviços. Os termos utilizados no modelo de objeto D-Bus imitam aqueles utilizados por algumas linguagens de programação orientadas a objetos. Isso não significa que o D-Bus é de alguma forma limitado a linguagens POO - na verdade, a implementação mais utilizada (libdbus) é escrita em C, uma linguagem de programação procedimental.

No D-Bus, um processo oferece seus serviços expondo objetos. Esses objetos tem métodos que podem ser invocados, e sinais que um objeto pode emitir. Métodos e sinais são coletivamente referidos como membros do objeto. Qualquer cliente conectado a um barramento pode interagir com um objeto utilizando seus métodos, fazendo pedidos ou comandando que o objeto faça ações. Por exemplo, um objeto representando um serviço de tempo pode ser solicitado por um cliente usando um método que retorna a data e hora atual. Um cliente também pode escutar sinais que um objeto emite quando seu estado muda devido a certos eventos, geralmente devido a um serviço relacionado. Um exemplo seria quando um serviço que administra dispositivos de hardware - como um USB - sinaliza um evento “um novo dispositivo de hardware foi adicionado”. Clientes devem instruir o barramento de que eles tem interesse em receber certos sinais de um objeto particular, já que o D-Bus só passa sinais aos processos que registraram um interesse neles.

Um processo conectado a um D-Bus pode requisitar que ele exporte quantos objetos D-Bus ele quiser. Cada objeto é identificado através de um caminho de objeto (”object path”, em inglês): uma string de números, letras e underscores separadas, prefixadas pelo caractere de barra. Ele é chamado de caminho devido a sua semelhança com o sistema de caminhos Unix. Um caminho de objeto é selecionado pelo processo que faz o requerimento, e deve ser único dentro do contexto daquela conexão de barramento. Um exemplo de caminho de objeto válido é /org/kde/kspread/sheets/3/cells/4/5. Não é obrigatório - mas também não é desencorajado - que sejam formadas hierarquias dentro dos caminhos de objeto. A convenção de nomeação de objetos de um serviço está completamente a critério dos desenvolvedores do serviço, mas muitos desenvolvedores escolhem utilizar um namespace com um nome de domínio reservado do projeto como prefixo (ex. /org/kde).

Cada objeto é indissociável à conexão de barramento onde ele foi exportado, e, do ponto de vista do D-Bus, só existe no contexto daquela conexão. Assim, para poder usar um determinado serviço, um cliente deve não só informar o caminho de objeto que fornece o serviço desejado, mas também o nome de barramento sob o qual o processo do serviço está conectado. Isso permite que vários processos conectados a barramentos possam exportar objetos diferentes com caminhos de objeto idênticos sem ambiguidades.

Uma interface especifica membros - métodos e sinais - que podem ser usados com um objeto. É um conjunto de declarações de métodos (incluindo parâmetros de passagem e de retorno) e sinais (incluindo seus parâmetros) identificados por um nome separado por pontos parecido com a anotação de interfaces da linguagem Java. Um exemplo de um nome de interface válido é org.freedesktop.Instrospectable. Mesmo com suas similaridades, nomes de interface e nomes de barramento não devem ser confundidos. Um objeto D-Bus pode implementar diversas interfaces, devendo implementar pelo menos uma, e deve dar suporte para cada método e sinal definido nela. A combinação de todas as interfaces implementadas por um objeto se chama tipo de objeto.

Quando um processo-cliente estiver usando um objeto, é uma boa prática fornecer o nome da interface do membro ao lado do nome do membro, mas isso só é obrigatório quando houver alguma ambiguidade causada por nomes de membros duplicados que estão disponíveis via diferentes interfaces implementadas por um objeto - desta forma, o membro selecionado seria indefinido ou errôneo. Um sinal emitido, diferente de um método, deve sempre indicar a qual interface ele pertence.

A especificação D-Bus também define diversas interfaces padrão que objetos podem querer implementar em conjunto com suas próprias interfaces. Enquanto isso é tecnicamente opcional, a maioria dos desenvolvedores do serviço D-Bus escolhem dar suporte a elas nos seus objetos exportados, já que elas fornecem recursos adicionais importantes aos clientes D-Bus, como a introspecção. Essas interfaces padrão são:

org.freedesktop.DBus.Peer: inclui uma forma de testar se uma conexão D-Bus está ativa. org.freedesktop.DBus.Introspectable: inclui um mecanismo de introspecção através do qual um processo-cliente pode, durante o tempo que estiver ativo, receber uma descrição (em formato XML) das interfaces, métodos e sinais que um objeto implementa. org.freedesktop.DBus.Properties: permite que um objeto D-Bus exponha as propriedades e atributos fundamentais por trás do objeto, ou simulá-los caso estes não existam. org.freedesktop.DBus.ObjectManager: quando um serviço D-Bus organiza seus objetos hierarquicamente, essa interface fornece uma forma de interrogar um objeto sobre todos os sub-objetos no seu caminho, além de suas interfaces e propriedades, utilizando uma única chamada de método.