D-Bus

A Unix/Linux szerverek üzemeltetése wikiből

Tartalomjegyzék

1 D-Bus

1.1 1. Bevezetõ

A D-Bus egy folyamatok közötti kommunikációt elõsegítõ rendszer, melyet elõszeretettel használnak az elterjedt grafikus felhasználói felületek (KDE, GNOME), de mûködik Microsoft Windowson és Mac OSX-en is. A kommunikáció üzenetküldések formájában valósul meg: a programok üzeneteket generálhatnak, melyekre más programok objektum-útvonalak alapján elõfizethetnek.

A rendszer célja a desktop alkalmazások jobb integrációjának elõsegítése és egy kényelmes felület biztosítása a desktop alkalmazások és az operációs rendszer közötti kommunikációra. Eredetileg a CORBA-alapú megoldások kiváltására készült.

A rendszer három fõ részbõl áll:

  • könyvtár: a libdbus függvénykönyvtár biztosít a felhasználói programok számára elérést az üzenetküldõ funkciókhoz;
  • daemon: feladata (szintén a libdbus könyvtárt használva) az üzenetek összegyûjtése és kézbesítése az alkalmazások között; több példány futhat párhuzamosan (egymástól független buszok létrehozása, pl. jogosultságok szétválasztása miatt). A példányok (buszok) a hozzájuk tartozó sockettel címezhetõek (a tényleges megvalósításokban általában két socket közül választhatunk: session vagy system, lásd késõbb).
  • wrapper könyvtárak: az egyes fejlesztõi környezetekhez vagy programozási nyelvekhez illeszti a libdbus felületét;

Az üzenetek a programokon belül egyes objektum-példányokhoz érkeznek. A D-bus az objektumokat olyan nevek alapján azonosítja, melyek emlékeztetnek a UNIX fájlrendszereken megszokott fájlnevekre (/im/pidgin/purple/PurpleObject) és támogatja a névtereket is. Programozói szemszögbõl a D-bus tekinthetõ egy RPC-megoldásnak, ami a folyamat memóriájában tárolt natív bináris adatok ki- és becsomagolását (marshaling) is megoldja. Ez azt jelenti, hogy a programok számára kényelmes bináris formátumban tárolt adatokat képes az adatokhoz tartozó típusok ismeretében szöveges formára (vagy egy egységes bináris formára) alakítani, hogy azok más programok számára elküldhetõek legyenek. Ennek a mûveletnek nyilván az inverzét is el tudja végezni. Ez azért fontos, mert a bináris adatformátumok porgramozási nyelvenként és számítógépenként eltérõek lehetnek. A szokásos IPC-mechanizmusok közül a dbus tekinthetõ a POSIX message queue (mq_overview(7)) rokonának, bár a dbus sokkal magasabb szintû (pl. elvégzi a data marshalingot is), támogatja a broadcast üzeneteket is, és képes szolgáltatásokat automatikusan elindítani. Cserébe sokkal nagyobb és az API bonyolultabb.

Az üzenetek a kliensektõl a dbus daemonhoz futnak be socketeken keresztül. A daemon a beérkezett üzenet másolatát küldi el az összes olyan socketre, aminek a másik oldalán az üzenetben érdekelt kliensek lehetnek. Broadcast signalok esetén nem jelent problémát, ha senkinek nem kézbesíthetõ az üzenet, de metódushívásoknál hibaüzenetet erdményez, ha a címzett nem elérhetõ.

További érdekesség, hogy a fejlesztõk tervezik a rendszer bõvítését hálózati kommunikációval, így különbözõ számítógépeken futó folyamatok is képesek lesznek ugyanezzel a módszerrel üzenetet küldeni egymásnak.

1.2 2. felhasználási terület

D-bus a nagyobb projektekben:

  • Avahi
  • pidgin
  • XChat
  • Skype
  • HAL
  • udev
  • gnome

A legtöbb modern Linux-disztribúció normál telepítés után kétféle d-bus daemont futtat:

  • rendszerszintû: üzenetek pl. új hardverek felcsatolásáról
  • session-szintû: az adott felhasználó alkalmazásai számára


1.3 3. használat

1.3.1 3.1 konfiguráció

Debian GNU/Linux alatt a dbus csomag telepítése után a /etc/dbus-1 könyvtárban megjelenik két konfigurációs fájl, a session.conf es a system.conf. Ezek a fajlok csak általános beállításokat tartalmaznak és a /etc/dbus-1/session.d es a /etc/dbus-1/system.d könyvtárakra hivatkoznak, ahol az egyes alkalmazások saját "konfig-plugin" fájljai találhatóak. A konfiguráció nyelve XML. Ezekben a fájlokban szabályozhatjuk, hogy bizonyos dbus-on elérhetõ szolgáltatásokat ki nyújthat és ki érhet el (név vagy UID). Beállíthatunk továbbá egy sor korlátozást is az üzenetekre, kapcsolatokra, nevekre, stb. Itt szabályozhatjuk azt is, hogy a daemon mennyi kimenõ üzenetet gyûjtsön sorba egy olyan kliens számára, aki épp nem olvassa a socketet (limit max_outoing_bytes); egyébként az, hogy egy ilyen limit átlépésekor pontosan mi történik, sajnos nem világos, a manual mélyen hallgat róla. A teljes leírás megtekinthetõ a dbus-daemon(1) manualban.

1.3.2 3.2 felügyelet, használat parancssorból

  • Monitorozás. Ha már fut a dbus, a dbus-monitor nevû programmal lehet a mûködését ellenõrizni. A program indítható --system vagy --session kapcsolóval, továbbá megadhatunk egy szûrési kifejezést. Ezután a dbus-monitor kiírja a standard kimenetére az összes olyan eseményt, ami az adott daemonon történt (system vagy session) és megfelel a szûrési feltételünknek. Például ha kíváncsiak vagyunk az USB-s eszközök felcsatolására, mert valamilyen plug&play programot szeretnénk írni, ami üdvözlõszöveget játszik a hangkártyán minden újabb csatlakoztatott eszköznek (vagy csak folyamatosan szeretnénk listázni õket automatikus frissítéssel), a következõ parancs kimenetét célszerû használni:
     dbus-monitor type='signal',path=/org/freedesktop/Hal/Manager,member=DeviceAdded --system 		
    A kimenet így fest (egy egér csatlakoztatásakor):
     signal sender=org.freedesktop.DBus -> dest=:1.89 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired    string ":1.89" signal sender=:1.2 -> dest=(null destination) serial=6857 path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceAdded    string "/org/freedesktop/Hal/devices/usb_device_15ca_c3_noserial" signal sender=:1.2 -> dest=(null destination) serial=6859 path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceAdded    string "/org/freedesktop/Hal/devices/usb_device_15ca_c3_noserial_if0" signal sender=:1.2 -> dest=(null destination) serial=6861 path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceAdded    string "/org/freedesktop/Hal/devices/usb_device_15ca_c3_noserial_usbraw" signal sender=:1.2 -> dest=(null destination) serial=6863 path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceAdded    string "/org/freedesktop/Hal/devices/usb_device_15ca_c3_noserial_if0_logicaldev_input" 		
    A betûvel kezdõdõ sorok az események, a következõ mezõkkel:
    • sender: a feladó egyedi azonosítója
    • dest: címzett objektum (ha null, akkor broadcast)
    • serial: a feladó által beállított cookie, válasz esetén a feladó ez alapján könnyebben megállapíthatja, hogy a válaszüzenet pontosan melyik kérésre érkezett
    • path: metódushíváskor az objektum elérési útvonala, signal esetén a forrás objektum útvonala
    • interface: az interfész neve, ahonnan az üzenet érkezett vagy amin a metódust futtatni kell. Signal esetén kötelezõ megadni.
    • member: az üzenet származási helye a feladó objektumob belül

Az elsõ esemény csak azt jelzi, hogy sikerült csatlakozni a buszhoz.

Persze ez a funkcionalitás elérhetõ a libdbus-on vagy annak valamelyik wrapper könyvtárán keresztül is.

  • Üzenetküldés. Üzeneteket a dbus-send paranccsal küldhetünk, ami a címzés mellett az üzenet tartalmát is a parancssori argumentumokból veszi. Kötelezõ megadni a következõ mezõket:
    • --system vagy --session (ha nincs megadva, akkor --session)
    • a megcímzett objektum elérési útja (destination object path; path a dbus-monitor kimenetén)
    • az üzenet neve (member a dbus-monitor kimenetén)

Opcionálisan megadható:

    • az üzenet tartalma (típus:érték párokban, pl int32:42)
    • --type=TYPE, az üzenet típusa (signal vagy method_call; ha nincs megadva, akkor signal)
    • --print-reply, ha azt szeretnénk, hogy a folyamat az üzenet kiküldése után blokkolódjon egy válasz érkezéséig; a választ kiírja a standard kimeneten. Ezzel a megoldással juthatunk hozzá az általunk hívott metódusok visszatérési értékeihez. A formátum megegyezik a dbus-monitor kimenetén látottal, csak "signal" helyett az elsõ sor a "method return" azonosítót tartalmazza.

Sem a megcímzett objektum útvonalának, sem az üzenet nevének nem kell szerepelnie semmilyen konfigurációs fájlban. Persze csak olyan üzenetet érdemes küldeni, amit aztán valaki értelmezni is tud. Ha metódushívást kezdeményezünk egy objektumra, amit senki sem regisztrált, akkor az hibaüzenetet eredményez. Broadcast singalt viszont küldhetünk úgy, hogy senki nem olvassa el.

  • Adminisztráció.
    • dbus-cleanup-sockets - Linux rendszereken nem használatos, mert a dbus "absztrakt socketeket" használ és ezek nem jelennek meg a fájlrendszerben. Más UNIX rendszerek alatt viszont elõfordulhat, hogy a socketek megjelennek pl. a /tmp könyvtárban, ezek ottmaradhatnak dbus-t használó programok szabálytalan kilépésekor; ezeket a feleslegessé vált socketeket tudjuk így feltakarítani.
    • dbus-launch - wrapper dbus programok indításához, gyakran használják a felhasználó session-buszának elindításához.
  • Socketek. A kliensek és a daemon között UNIX socketeken folyik a kommunikáció. Linux rendszereken ezek a socketek általában absztrakt socketek, így listázásuk a fájlrendszert használva nem lehetséges. A kapcsolatok listáját a következõ paranccsal lehet lekérni:
     dbus-send --system --type=method_call --dest=org.freedesktop.DBus --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames 	     
    Egy konkrét kapcsolathoz tartozó process tulajdonosának UID-jét pedig így:
     dbus-send --system --type=method_call --dest=org.freedesktop.DBus --print-reply /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixUser string:":1.1" 	     
    A socketek tényleges nevei a netstat -x kimenetén látszanak.

1.4 4. esettanulmányok

1.4.1 4.1. pidgin

A pidgin egy népszerû Instant Messaging kliens. A program a mûködése során keletkezõ események jelentõs részét signalok formájában kiküldi a session-buszra a /im/pidgin/purple/PurpleObject útvonalon. Így értesülhetünk róla, ha:

  • üzenetünk érkezett,
  • ha egy pajtásunk éppen gépel nekünk,
  • ha a felhasználói felületen történik valami (pl. mi kezdünk el gépelni).

Az események teljes listája megtalálható a http://developer.pidgin.im/wiki/DbusHowto oldalon.

A dbus-interfész használható a pidgin natív plugin interfésze helyett is: üzenetekre reagáló szkripteket vagy programokat futtathatunk a pidgin processzen kívül. A pidgin metódusokat is megoszt dbus-on keresztül, így az is megoldható, hogy a pidgin-t távirányítva üzeneteket küldjünk, IRC-csatornákra lépjünk be vagy a pajtásaink információit kérjük le.

Pár példa a fent felsoroltak megvalósítására shell-bõl.

  • Ez a szkript minden beérkezõ üzenetet kiír a kimenetén:
     #!/bin/sh dbus-monitor --session path=/im/pidgin/purple/PurpleObject,member=WroteChatMsg | awk ' 	/^signal/ { 		getline; chat=$2 		getline; from=$2 		getline; text=$0 		sub("^ *\"", "", from); sub("\"$", "", from) 		sub("^ *string \"", "", text); sub("\"$", "", text) 		print "[" chat "] (" from ") " text 	} ' 	
  • Ez a szkript minden folyamatban lévõ privát beszélgetésbe beküldi azt, hogy foobar:
     #!/bin/sh  convs=`dbus-send --session --print-reply --dest=im.pidgin.purple.PurpleService /im/pidgin/purple/PurpleObject im.pidgin.purple.PurpleInterface.PurpleGetIms | awk '/int32/ { print $2 }'` for c in $convs do 	im=`dbus-send --session --print-reply --dest=im.pidgin.purple.PurpleService /im/pidgin/purple/PurpleObject im.pidgin.purple.PurpleInterface.PurpleConversationGetImData int32:$c  | awk '/int32/ { print $2 }'` 	dbus-send --session --print-reply --dest=im.pidgin.purple.PurpleService /im/pidgin/purple/PurpleObject im.pidgin.purple.PurpleInterface.PurpleConvImSend int32:$im string:foobar done 	

1.4.2 4.2. alkalmazások desktop-integracioja: gEDA

A dbus egyik fõ célja a deszktopalkalmazások integrációjának megkönnyítése. Egy szélsõséges példa erre a gEDA programcsomagban találhato xgsch2pcb program, ami a programcsomag gschem nevû kapcsolástervezõ és a PCB nevû nyáktervezõ programját kapcsolja össze dbus-üzenetek segítségével.

A gschem és a PCB alapvetõen jól viselkedõ unixos programok: mindegyik csak egy konkrét feladat elvégzésére való. A szokásos munkafolyamat a kapcsolási rajz megtervezése, majd az abból készített "netlist" (az alkatrészek közötti kapcsolatok logikai hálózata) átvitele PCB alá, ahol a tényleges nyákrajzot készítjük úgy, hogy annak meg kell felelnie a logikai kapcsolásnak. Ha késõbb a kapcsolásban valamilyen változtatást végzünk (ami elég gyakori), az új hálózati listát ismét át kell vinnünk a nyákrajzra, es ott is el kell végezni a megfelelõ módosításokat.

Mivel ezek grafikus programok, a kommunikáció nem tud olyan egyszerû lenni, mint shell alatt a pipe. Helyette a kommunikáció fájlokon keresztül történik:

  1. elmentjük a kapcsolási rajzot (ami rengeteg metaadatot tartalmaz)
  2. a gsch2pcb nevû program a metaadatokat felhasználva elõállítja a logikai kapcsolatok listáját és készít egy üres nyákrajzot, amin a felhasználandó alkatrészek már mind szerepelnek, de nincs közöttük semmilyen galvanikus összeköttetés
  3. a PCB program segítségével betöltjük az így készült fájlt az alkatrészekkel, a logikai kapcsolatokat és egyéb metaadatokat

A folyamatot gyakran Makefile-bol vezéreljük, fõleg ha több kapcsolási rajzból több nyákrajzot is szeretnénk készíteni.

Vannak azonban olyan felhasználók, akik az integrált grafikus szerkesztõket kedvelik. Az xgsch2pcb program segít, hogy a fent említett UNIX-elvek szerint szétválasztott programot meg lehessen tartani így, miközben egyes felhasználók számára az egész integráltnak tûnjön. Ezt úgy éri el, hogy futtat egy gschem és egy PCB programot is, mindkettõvel felveszi a kapcsolatot dbus-on keresztül, így az információk átviteléhez szükséges összes parancsot végre tudja hajtani a felhasználó helyett (pl. el tudja menteni a kapcsolást gschem-ben és be tudja tölteni a megváltozott hálózati listát PCB-ben). A felhasználó az egész rendszert úgy látja, mintha lenne egy grafikus projektmenedzser-ablak, ahol össze lehet párosítani a kapcsolási rajzokat a nyákrajzokkal és két szerkesztõablak, egy a kapcsolási rajzokra, egy a nyákrajzokra.

A konkrét megvalósításban

  • az xgsch2pcb egy python-szkript,
  • a PCB egy c-ben írt program, a /org/seul/geda/pcb dbus elérési úton,
  • a gschem egy fõleg scheme nyelven írt program.

Persze ebben az esetben is elképzelhetõ lenne bármilyen más IPC-mechanizmus használata.

1.5 5. felhasznált irodalom, hasznos linkek

Személyes eszközök