¿Para qué sirve prácticamente D-Bus?

¿Para qué sirve prácticamente D-Bus?

dbusse supone que proporciona "una forma sencilla para que las aplicaciones se comuniquen entre sí".

Pero todavía no estoy seguro de para qué sirve en la práctica. Nunca he visto una situación en la que dbussea útil, solo veo advertencias de que algún dbuscomponente ha experimentado errores, como cuando inicio Terminator desde la línea de comandos (para poder ver los errores):

Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files

Me deshice del error anterior agregando NO_AT_BRIDGE=1a /etc/environment. No tengo idea de lo que eso hace.

Casi todas las aplicaciones gui parecen estar vinculadas con dbus. Algunos permiten iniciar sin dbus, es decir:

terminator --no-dbus

No veo ninguna diferencia en el comportamiento. ¿Qué se supone que deja de funcionar cuando terminatorse empieza sin dbus?

Además, intenté deshabilitar varios componentes de dbus para ver qué deja de funcionar:

Lo he borrado /etc/X11/Xsession.d/95dbus_update-activation-envsólo para ver qué pasa. Contenía el siguiente código:

if [ -n "$DBUS_SESSION_BUS_ADDRESS" ] && [ -x "/usr/bin/dbus-update-activation-environment" ]; then
  # subshell so we can unset environment variables
  (
    # unset login-session-specifics
    unset XDG_SEAT
    unset XDG_SESSION_ID
    unset XDG_VTNR

    # tell dbus-daemon --session to put the Xsession's environment in activated services' environments
    dbus-update-activation-environment --verbose --all
  )
fi

Todo funciona igual, hasta donde yo sé. ¿Cuál fue el propósito del guión anterior?

¿En qué situación sería útil que mis aplicaciones se comunicaran entre sí a través de dbus?

¿Hay aplicaciones que no funcionan sin ellas dbus?

Mi sistema es Debian Buster y estoy usando un entorno openbox simple (sin ningún entorno de escritorio como Gnome o KDE)

Respuesta1

dbusHace exactamente lo que dijiste: permite la comunicación bidireccional entre aplicaciones.


Para su ejemplo específico que mencionó terminator. Depágina de manual de terminador, vemos:

--new-tab
    If this is specified and Terminator is already running, DBus 
    will be used to spawn a new tab in the first Terminator window.

Entonces, si haces esto desde otra terminal (konsole, xterm, gnome-terminal):

$ terminator &
$ terminator --new-tab &

Verás que el primer comando abre una nueva ventana. El segundo comando abre una nueva pestaña en la primera ventana. Esto lo hace el segundo proceso usando dbus para encontrar el primer proceso, pidiéndole que abra una nueva pestaña y luego saliendo.

Si haces esto desde otra terminal:

$ terminator --no-dbus &
$ terminator --new-tab &

Verás que el primer comando abre una nueva ventana. El segundo comando no encuentra el dbus de la primera ventana, por lo que abre una nueva ventana. Instalé Terminator para probar esto y es cierto.

Además, sospecho que polkit se vería afectado. Polkit usa dbus para elevar los privilegios de las aplicaciones GUI. Es como el sudomundo GUI. Si está en gnome y ve que se cubre toda la pantalla mientras se le solicita la contraseña del administrador, eso es polkit en acción. Sospecho que no recibirá ese mensaje en ninguna aplicación GUI desde la que inicie terminatorsi tiene --no-dbus. No podrá autenticarse o recurrirá a alguna autenticación de terminal. De terminatorintentarlo pkexec ls. Eso se ejecutará lscon privilegios elevados. Vea si es diferente con y sin la --no-dbusopción. No tengo un agente polkit en mi administrador de ventanas (i3), así que no puedo probarlo.


Conozco principalmente dbus en términos de systemd, así que de ahí vendrá el resto de mi respuesta.

¿Hay aplicaciones que no funcionan sin ellas dbus?

Sí. Llevar systemctl. systemctl statusemitirá una consulta a "org.freedesktop.systemd1"y se la presentará. systemctl startllamará a un método dbus y pasará la unidad como argumento a ese método. systemdrecibe la llamada y realiza la acción.

Si desea tomar medidas en respuesta a un cambio de estado de una unidad systemd (es decir, foo.service), puede obtener un descriptor de archivo para la interfaz org.freedesktop.DBus.Propertiescon ruta /org/freedesktop/systemd1/unit/foo_2eservicey miembro PropertiesChanged. Configure un inotifyFD y de repente tendrá una manera de reaccionar ante el inicio, la detención, la falla de un servicio, etc.

Si desea ver lo que está disponible en systemd dbus para una unidad específica (es decir ssh.service), pruebe este comando:

busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/ssh_2eservice
NAME                                TYPE      SIGNATURE       RESULT/VALUE                             FLAGS
org.freedesktop.DBus.Introspectable interface -               -                                        -
.Introspect                         method    -               s                                        -
org.freedesktop.DBus.Peer           interface -               -                                        -
.GetMachineId                       method    -               s                                        -
.Ping                               method    -               -                                        -
org.freedesktop.DBus.Properties     interface -               -                                        -
.Get                                method    ss              v                                        -
.GetAll                             method    s               a{sv}                                    -
.Set                                method    ssv             -                                        -
.PropertiesChanged                  signal    sa{sv}as        -                                        -
org.freedesktop.systemd1.Service    interface -               -                                        -
.AttachProcesses                    method    sau             -                                        -
.GetProcesses                       method    -               a(sus)                                   -
.AllowedCPUs                        property  ay              0                                        -
.AllowedMemoryNodes                 property  ay              0                                        -
.AmbientCapabilities                property  t               0                                        const
.AppArmorProfile                    property  (bs)            false ""                                 const
.BindPaths                          property  a(ssbt)         0                                        const
.BindReadOnlyPaths                  property  a(ssbt)         0                                        const
.BlockIOAccounting                  property  b               false                                    -
.BlockIODeviceWeight                property  a(st)           0                                        -
.BlockIOReadBandwidth               property  a(st)           0                                        -
.BlockIOWeight                      property  t               18446744073709551615                     -
.BlockIOWriteBandwidth              property  a(st)           0                                        -
.BusName                            property  s               ""                                       const
.CPUAccounting                      property  b               false                                    -
.CPUAffinity                        property  ay              0                                        const
.CPUAffinityFromNUMA                property  b               false                                    const
.CPUQuotaPerSecUSec                 property  t               18446744073709551615                     -
.CPUQuotaPeriodUSec                 property  t               18446744073709551615                     -
.CPUSchedulingPolicy                property  i               0                                        const
.CPUSchedulingPriority              property  i               0                                        const
.CPUSchedulingResetOnFork           property  b               false                                    const
.CPUShares                          property  t               18446744073709551615                     -
.CPUUsageNSec                       property  t               18446744073709551615                     -
.CPUWeight                          property  t               18446744073709551615                     -
.CacheDirectory                     property  as              0                                        const
.CacheDirectoryMode                 property  u               493                                      const
.CapabilityBoundingSet              property  t               18446744073709551615                     const
.CleanResult                        property  s               "success"                                emits-change
.ConfigurationDirectory             property  as              0                                        const
.ConfigurationDirectoryMode         property  u               493                                      const
.ControlGroup                       property  s               "/system.slice/ssh.service"              -
.ControlPID                         property  u               0                                        emits-change
.CoredumpFilter                     property  t               51                                       const
.DefaultMemoryLow                   property  t               0                                        -
.DefaultMemoryMin                   property  t               0                                        -
.Delegate                           property  b               false                                    -
.DelegateControllers                property  as              0                                        -
.DeviceAllow                        property  a(ss)           0                                        -
.DevicePolicy                       property  s               "auto"                                   -
.DisableControllers                 property  as              0                                        -
.DynamicUser                        property  b               false                                    const
.EffectiveCPUs                      property  ay              0                                        -
.EffectiveMemoryNodes               property  ay              0                                        -
.Environment                        property  as              0                                        const
.EnvironmentFiles                   property  a(sb)           1 "/etc/default/ssh" true                const
.ExecCondition                      property  a(sasbttttuii)  0                                        emits-invalidation
.ExecConditionEx                    property  a(sasasttttuii) 0                                        emits-invalidation
.ExecMainCode                       property  i               0                                        emits-change
.ExecMainExitTimestamp              property  t               0                                        emits-change
.ExecMainExitTimestampMonotonic     property  t               0                                        emits-change
.ExecMainPID                        property  u               835                                      emits-change
.ExecMainStartTimestamp             property  t               1597235861087584                         emits-change
.ExecMainStartTimestampMonotonic    property  t               5386565                                  emits-change
.ExecMainStatus                     property  i               0                                        emits-change
.ExecReload                         property  a(sasbttttuii)  2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecReloadEx                       property  a(sasasttttuii) 2 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStart                          property  a(sasbttttuii)  1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartEx                        property  a(sasasttttuii) 1 "/usr/sbin/sshd" 3 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPost                      property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStartPostEx                    property  a(sasasttttuii) 0                                        emits-invalidation
.ExecStartPre                       property  a(sasbttttuii)  1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStartPreEx                     property  a(sasasttttuii) 1 "/usr/sbin/sshd" 2 "/usr/sbin/sshd" "… emits-invalidation
.ExecStop                           property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStopEx                         property  a(sasasttttuii) 0                                        emits-invalidation
.ExecStopPost                       property  a(sasbttttuii)  0                                        emits-invalidation
.ExecStopPostEx                     property  a(sasasttttuii) 0                                        emits-invalidation
.FileDescriptorStoreMax             property  u               0                                        const
.FinalKillSignal                    property  i               9                                        const
.GID                                property  u               4294967295                               emits-change
.Group                              property  s               ""                                       const
.GuessMainPID                       property  b               true                                     const
.IOAccounting                       property  b               false                                    -
.IODeviceLatencyTargetUSec          property  a(st)           0                                        -
.IODeviceWeight                     property  a(st)           0                                        -
.IOReadBandwidthMax                 property  a(st)           0                                        -
.IOReadBytes                        property  t               18446744073709551615                     -
.IOReadIOPSMax                      property  a(st)           0                                        -
.IOReadOperations                   property  t               18446744073709551615                     -
.IOSchedulingClass                  property  i               0                                        const
.IOSchedulingPriority               property  i               0                                        const
.IOWeight                           property  t               18446744073709551615                     -
.IOWriteBandwidthMax                property  a(st)           0                                        -
.IOWriteBytes                       property  t               18446744073709551615                     -
.IOWriteIOPSMax                     property  a(st)           0                                        -
.IOWriteOperations                  property  t               18446744073709551615                     -
.IPAccounting                       property  b               false                                    -
.IPAddressAllow                     property  a(iayu)         0                                        -
.IPAddressDeny                      property  a(iayu)         0                                        -
.IPEgressBytes                      property  t               18446744073709551615                     -
.IPEgressFilterPath                 property  as              0                                        -
.IPEgressPackets                    property  t               18446744073709551615                     -
.IPIngressBytes                     property  t               18446744073709551615                     -
.IPIngressFilterPath                property  as              0                                        -
.IPIngressPackets                   property  t               18446744073709551615                     -
.IgnoreSIGPIPE                      property  b               true                                     const
.InaccessiblePaths                  property  as              0                                        const
...skipping...
.CollectMode                        property  s               "inactive"                               const
.ConditionResult                    property  b               true                                     emits-change
.ConditionTimestamp                 property  t               1597235861034899                         emits-change
.ConditionTimestampMonotonic        property  t               5333881                                  emits-change
.Conditions                         property  a(sbbsi)        1 "ConditionPathExists" false true "/et… emits-invalidation
.ConflictedBy                       property  as              0                                        const
.Conflicts                          property  as              1 "shutdown.target"                      const
.ConsistsOf                         property  as              0                                        const
.DefaultDependencies                property  b               true                                     const
.Description                        property  s               "OpenBSD Secure Shell server"            const
.Documentation                      property  as              2 "man:sshd(8)" "man:sshd_config(5)"     const
.DropInPaths                        property  as              0                                        const
.FailureAction                      property  s               "none"                                   const
.FailureActionExitStatus            property  i               -1                                       const
.Following                          property  s               ""                                       -
.FragmentPath                       property  s               "/lib/systemd/system/ssh.service"        const
.FreezerState                       property  s               "running"                                emits-change
.Id                                 property  s               "ssh.service"                            const
.IgnoreOnIsolate                    property  b               false                                    const
.InactiveEnterTimestamp             property  t               0                                        emits-change
.InactiveEnterTimestampMonotonic    property  t               0                                        emits-change
.InactiveExitTimestamp              property  t               1597235861039525                         emits-change
.InactiveExitTimestampMonotonic     property  t               5338505                                  emits-change
.InvocationID                       property  ay              16 90 215 118 165 228 162 72 57 179 144… emits-change
.Job                                property  (uo)            0 "/"                                    emits-change
.JobRunningTimeoutUSec              property  t               18446744073709551615                     const
.JobTimeoutAction                   property  s               "none"                                   const
.JobTimeoutRebootArgument           property  s               ""                                       const
.JobTimeoutUSec                     property  t               18446744073709551615                     const
.JoinsNamespaceOf                   property  as              0                                        const
.LoadError                          property  (ss)            "" ""                                    const
.LoadState                          property  s               "loaded"                                 const
.Names                              property  as              2 "ssh.service" "sshd.service"           const
.NeedDaemonReload                   property  b               false                                    const
.OnFailure                          property  as              0                                        const
.OnFailureJobMode                   property  s               "replace"                                const
.PartOf                             property  as              0                                        const
.Perpetual                          property  b               false                                    const
.PropagatesReloadTo                 property  as              0                                        const
.RebootArgument                     property  s               ""                                       const
.Refs                               property  as              0                                        -
.RefuseManualStart                  property  b               false                                    const
.RefuseManualStop                   property  b               false                                    const
.ReloadPropagatedFrom               property  as              0                                        const
.RequiredBy                         property  as              0                                        const
.Requires                           property  as              3 "system.slice" "-.mount" "sysinit.tar… const
.RequiresMountsFor                  property  as              1 "/run/sshd"                            const
.Requisite                          property  as              0                                        const
.RequisiteOf                        property  as              0                                        const
.SourcePath                         property  s               ""                                       const
.StartLimitAction                   property  s               "none"                                   const
.StartLimitBurst                    property  u               5                                        const
.StartLimitIntervalUSec             property  t               10000000                                 const
.StateChangeTimestamp               property  t               1597235861208937                         emits-change
.StateChangeTimestampMonotonic      property  t               5507917                                  emits-change
.StopWhenUnneeded                   property  b               false                                    const
.SubState                           property  s               "running"                                emits-change
.SuccessAction                      property  s               "none"                                   const
.SuccessActionExitStatus            property  i               -1                                       const
.Transient                          property  b               false                                    const
.TriggeredBy                        property  as              0                                        const
.Triggers                           property  as              0                                        const
.UnitFilePreset                     property  s               "enabled"                                -
.UnitFileState                      property  s               "enabled"                                -
.WantedBy                           property  as              1 "multi-user.target"                    const
.Wants                              property  as              0                                        const

Puedes ver en esto que la interfaz dbus es bastante poderosa.

Quizás se pregunte: ¿Por qué estas aplicaciones no se comunican simplemente a través de sockets o archivos?

DBus proporciona una interfaz común. No necesita una lógica diferente para llamar a métodos o verificar propiedades según la aplicación con la que está hablando. Sólo necesitas saber el nombre del camino.

Lo he usado systemdcomo ejemplo porque es lo que mejor entiendo, pero hay muchísimos usos de dbus en la mayoría de los escritorios. Todo, desde la autenticación hasta la configuración de visualización, está disponible en dbus.

Respuesta2

Ya existe una excelente respuesta detallada de D-Bus por parte de @Stewart, pero quiero modificarla con una idea de alto nivel sobre el diseño de D-Bus.

La forma "tradicional" de comunicación entre procesos (IPC) en sistemas UNIX y Linux utiliza sockets directamente, por ejemplo, el proceso A abre /var/run/a.sockety el proceso B lee/escribe. Esto funciona bastante bien para programas muy unidos que fueron diseñados para comunicarse entre sí.

Sin embargo, es posible que desee tener comunicación entre los procesos de dos programas donde el programa B ni siquiera existía cuando se escribió el programa A. D-Bus intenta resolver este problema proporcionando protocolos de comunicación y descubrimiento de servicios. De esa manera, solo era necesario que existiera la interfaz b cuando se escribió A y el proceso B implementa la interfaz b.

Por tanto, se podría describir a D-Bus como un "administrador" de IPC.

Históricamente, las herramientas de interfaz de línea de comandos (CLI) suelen utilizar también un administrador de IPC, el shell, para comunicarse con programas arbitrarios mediante canalizaciones. El problema con este enfoque es que no proporciona validación de datos, protocolos estandarizados, etc. Por lo tanto, sólo lo pueden utilizar usuarios avanzados. Las herramientas GUI en general deberían hacer esto de forma "invisible". Sin embargo, cada vez más herramientas CLI comienzan a utilizar D-Bus, prácticamente como una alternativa a sudo(1). Entonces, como usuario sin privilegios, puede ejecutar systemctl poweroffy se le solicitará autenticación (esto se puede comparar con el UAC en Windows). Dependiendo de su proveedor de polkit, esto puede ser incluso un mensaje de GUI. Al menos en teoría, este enfoque es más flexible y permite privilegios más detallados y funciona sin binarios setuid (como sudo). Esto puede verse como una característica de seguridad.

Por supuesto, como abstracción, introduce algún tipo de complejidad (al menos en las dependencias de los programas). Sin embargo, cuanto más programas lo utilicen (sanamente), menor será la carga. Si te gusta D-Bus y el desarrollo actual no te lo puedo decir. Pero los sistemas operativos modernos tienden a proporcionar muchos servicios cruciales fuera del núcleo (y ahora sacan de nuevo el material histórico del núcleo, al estilo microkernel) debido a los requisitos más complejos de la informática actual. Por lo tanto, si "sólo" quieres un terminal "simple", todo esto podría considerarse "inflado", pero la industria lo exige por una buena razón y cada vez más desarrolladores notan las ventajas de usar D-Bus. Es el reemplazo actual de la vieja tubería en su shell (no la interfaz del sistema, en realidad D-Bus la utiliza, pipe()etc.).

Respuesta3

En Unix tradicional, suele haber poca comunicación entre los programas en ejecución. Cada programa se ejecuta en un espacio de direcciones completamente separado y solo interactúa con el kernel. Este modelo es simple y robusto, pero los permisos de acceso son en su mayoría demasiado generales para entornos de escritorio, y la implementación de un control de acceso detallado es demasiado compleja en muchos casos.

Un ejemplo en el que el kernel refina el control de acceso es el sistema de archivos: los programas sin privilegios pueden enviar una solicitud de escritura al kernel, que se traduce en una solicitud de escritura enviada al disco duro sin violar la separación entre programas. Sin embargo, esta es una capa bastante compleja y el control aún no es lo suficientemente fino para las computadoras de escritorio modernas donde los usuarios pueden querer conectar una memoria USB.

Para otras funciones, como por ejemplo el acceso a la tarjeta de sonido, el núcleo sólo implementa un modelo de acceso simple: una vez que un programa tiene acceso a la tarjeta de sonido, puede reproducir y grabar sonido y manipular los controles del mezclador, y no existe ningún mecanismo para revocar ese acceso excepto terminando el programa.

En un entorno de escritorio, querríamos un modelo más fino: el navegador debería poder usar el micrófono y la cámara web solo después de preguntarle al usuario, y cuando un usuario cierra sesión, cualquier programa en ejecución debería perder el acceso al micrófono, pero si el usuario quiere ejecutar un cálculo durante la noche, eso aún debería ser posible.

El sistema X window es un buen precedente para realizar control de acceso en un programa de usuario: la representación en una ventana se realiza enviando una solicitud a otro programa que calcula el contenido final de la pantalla que se muestra. Si la solicitud se traduce en un cambio visible en el contenido de la pantalla se decide en función de la configuración de control de acceso actual: arrastrar una ventana hacia el frente otorga acceso de escritura a un área del espacio de la pantalla para este programa, enviarla hacia atrás revoca ese acceso.

Los entornos de escritorio ahora proporcionan muchos de estos programas mediadores, por lo que para cada función debe haber un protocolo de comunicaciones y un método para abrir un identificador para ese programa.

dbus proporciona un protocolo genérico y un servicio de intermediario donde los programas pueden solicitar conectarse a un programa que proporciona control de acceso a una funcionalidad específica. Si el programa de destino ya se está ejecutando, el corredor simplemente reenviará las solicitudes; si aún no se está ejecutando, el corredor iniciará el programa a pedido si sabe cómo hacerlo.

La funcionalidad equivalente en Windows es COM/DCOM en combinación con el registro.

Respuesta4

Todo parece funcionar todavía bajo XFCE (algunos escritorios, por ejemplo, gnome, pueden sermás dependiente dedbus). Ejecuto aplicaciones a travéscárcel de bomberospor lo que perder cualquier supuesto beneficio de seguridad dbusno es realmente una preocupación.

Las siguientes distribuciones de Linux parecen funcionar bien sin dbus& systemd:

Habrá problemas menores, pero si eres razonablemente competente, son fáciles de solucionar.

información relacionada