A statikus rendszerfájlok helyett a 2.4-es kerneltől fogva lehetőség volt a devfs fájlrendszer használatára. A devfs egy a proc és sys fájlrendszerekhez hasonló virtuális fájlrendszer volt. Amennyiben a devfs-t felmountoltuk a /dev könyvtár alá, akkor a rendszergazda, sőt bármilyen rendszerszoftver közreműködése nélkül automatikusan biztosította, hogy a kernelben jelenlevő (vagy frissen csatlakoztatott) eszközök /dev alatti eszközfájljai megjelenjenek, a leválasztott eszközök eszközfájljai pedig eltűnjenek. A devfs rendszer programkódja teljes egészében a kernelben helyzkedett el. A 2.4-es Linuxok korában az eszközfájlok valós időben történő, dinamikus létrehozásán és törlésén kívül egyéb feladatot nem végző devfs-t kiegészítette a hotplug alrendszer, amelynek fő feladata a menet közben csatlakoztatott hardvereszközök meghajtóprogramjainak (vagyis kernel-moduljainak) betöltése, és az eszközök esetleges bekonfigurálása volt. A hotplug rendszer működése azon alapult, hogy amikor valamilyen hotplug esemény (pl. hardvereszköz csatlakoztatása, eltávolítása) történt, akkor a kernel meghívta a /sbin/hotplug
parancsot (pontosabban azt a binárist, amelynek a neve meg volt adva a /proc/sys/kernel/hotplug
fájlban), és rendszerváltozókba kódolva átadta neki az esemény részleteit. A kernel által meghívott hotplug parancs aztán lefuttatta a megfelelő hotplug szkriptet (az ún. ügynököt), ami elvégezte a szükséges driverbetöltést, eszközkonfigurálást, stb.
A 2.6-os kerneltől kezdve a kizárólag a kernelben helyet foglaló, ezért rugalmatlan, és a kernel kódját feleslegesen bonyolító devfs-t kiváltotta az Udev rendszer. Az Udev legfontosabb összetevője a háttérben folyamatosan futó udev démon, amely a hotplug alrendszerhez hasonló módon a kerneltől érkező eseményeket dolgoz fel, ezek alapján dolgozik. Az udev rendszer feladata kezdetben nem igazán mutatott túl a devfs-én, de sokkal rugalmasabban dolgozik annál: A /dev könyvtárban (amely alá a korábbi speciális devfs helyére többnyire egy egyszerű, általános célú tmpfs fájlrendszer került) létrehozta, megfelelő fájljogosultsággal ellátta, vagy éppen törölte az eszközfájlokat. Amint az udev man oldalából kitűnik, az udevd összetett szabályrendszerek szerint dolgozza fel a kerneltől jövő eseményeket. A szabályoknak a udev fejlesztők által írt szabványos, "kőbe vésett" része a /lib/udev/rules.d
könyvtárban található, míg a disztribútorok és rendszergazdák által írt (sőt, néha az udevd által futásidőben generált) szabályok a /etc/udev/rules.d
könyvtárban kapnak helyet. Az udev szabályok szerencsére nem annyira bonyolultak, mint amilyenek elsőre tűnnek, és az eszközfájlok rendkívül rugalmas kezelését teszik lehetővé. Amikor Greg Kroah-Hartman a devfs Udevvel történő kiváltása mellett kardoskodott, az egyik legfontosabb érve az volt, hogy az udev kiterjedt konfigurációja lehetővé teszi, hogy ugyanaz a hardvereszköz - függetlenül attól, hogy a vele azonos típusú eszközök közül hányadikként lett csatlakoztatva a rendszerhez - az udev konfigurációjában eltárolható azonosítói (pl. kötetazonosító, MAC-cím, WWN, gyári szám, stb.) alapján mindig ugyanolyan néven szerepeljen a /dev könyvtárban, vagy ha ez a név esetleg pl. túl hosszú lenne, mindig legyen egy (vagy több) symlink a /dev könyvtárfában, aminek a segítségével egyértelműen megtalálhatjuk a keresett eszközt. Az udev tehát megoldotta a devfs által el nem ért célt, az állandó eszköznevek biztosítását, ráadásul úgy, hogy közben egyszerűsödött a kernel programkódja.
A rendszer működéséhez szükség van arra, hogy néhány eszközfájlt már azelőtt jelen legyen a /dev könyvtárban, mielőtt az udevd bármilyen utasítást kaphatna a kerneltől ezek létrehozására. Sőt, ezen eszközfájlok némelyike olyan speciális rendszereszközöket reprezentál, amelyek esetében a kernelkód értelmetlen túlbonyolításához vezetne, ha elvárnánk a kerneltől, hogy hozassa létre őket az Udev rendszerrel. A problémát egy huszárvágással oldották meg az Udev fejlesztői oly módon, hogy az udevd démon az indulásakor egyszerűen átmásolja a /lib/udev/devices
könyvtár tatalmát a /dev könyvtárba. A /lib/udev/devices
könyvtár tehát arra szolgál, hogy a disztribútorok (vagy a rendszergazdák) itt hozzák létre azokat a karakter- vagy blokk-speciális UNIX eszközfájlokat, amelyekre a boot folyamat korai fázisában szüksége van a rendszernek.
A 2.6-os kernelre épülő disztribúciókban az udev eleinte csak a devfs-t váltotta ki, és ahhoz hasonlóan együtt dolgozott a hotplug rendszerrel. Később azonban - mivel az udev szabályok egyebek mellett tetszőleges parancsok végrehajtását is lehetővé teszik a kerneltől érkező események feldolgozásakor - elkezdett összefonódni a hotpluggal, és végül azt is teljes egészében kiváltotta, vagyis a modern linux disztribúciókban hiába is keresnénk a fent említett hotplug alrendszert. A "hatalomátvétel" első lépéseként az udevd kezdte el feldolgozni a kerneltől a hotplug alrendszer számára érkező eseményeket is, úgy, hogy ebben a fázisban az udev szabályrendszere utasította az udevd-t a hotplug ügynökök megfelelő paraméterekkel történő futtatására. A felhasználók először csak azt érzékelték, hogy a /proc/sys/kernel/hotplug
fájl tartalma /sbin/hotplug
-ról /sbin/udevsend
-re változott. Mivel a kernel minden eseményhez új példányt indít a /sbin/udevsend
(vagy /sbin/hotplug
) programból, előfordulhat, hogy az egymást esetleg túl gyorsan követő események bekövetkezésekor a sok párhuzamosan futó udevsend (vagy hotplug) processz elfogyasztja a rendszer memóriáját. Többek között emiatt a kernelből az udevsend felé irányuló eseményfolyamot teljes mértékben átköltöztették a szóbanforgó /proc/sys/kernel/hotplug
mechanizmusról az udev rendszer natív netlink csatornájára. Ezzel feleslegessé vált mind a /sbin/hotplug
, mind a /sbin/udevsend
parancs, és mivel az udev szabályok is fokozatosan átvették a hotplug ügynökök szerepét, a hotplug programcsomag végül teljes egészében eltűnt.
A netlink hálózati alrendszer (AF_NETLINK) egy Linux specifikus virtuális hálózati közeg, amely csak a helyi gépen belüli kommunikációra használható. Ilyen szempontból leginkább a már többször említett Unix Domain Socket rendszerre hasonlít, de azzal ellentétben nem kapcsolat/adatfolyam- (SOCK_STREAM), hanem csomagalapú (SOCK_RAW/SOCK_PACKET) kommunikációra szakosodott, és nem annyira alkalmazások közötti, mint inkább a kernel és az alkalmazások közötti adatcserére szolgál. Az Udev rendszer netlink üzeneteit lehallgathatjuk a későbbiekben részletesebben ismertetett udevadm program monitor parancsával, pl. a következőképpen: `udevadm monitor --property`
. A parancs kimenetén láthatjuk az udev man oldaláról már ismerős paraméterek (pl. ACTION, DEVPATH, SUBSYSTEM, stb.) neveit és értékeit, jól láthatjuk tehát, hogy az udev szabályok és események milyen szoros kapcsolatban vannak egymással. Ha ráadásul strace-szel futtatjuk az udevad parancsot, azt is megfigyelhetjük, hogy az udev rendszer netlink üzenetcsomagjai szinte közvetlen cleartext formában hordozzák a parancs kimenetén látható eseményeket, vagyis az Udev események, az azokat hordozó netlink csomagok és az Udev szabályok kapcsolatrendszere rendkívül kézenfekvő és jól érthető.
A kernel az általa kezelt hardver- és virtuális eszközökről összeállít egy adatbázist, és a megfelelő jogosultságokkal futó alkalmazások számára elérhetővé teszi azt az alapértelmezetten a /sys
könyvtár alá csatolt Sysfs fájlrendszeren keresztül. A Sysfs a procfs-hez hasonló filozófiájú virtuális fájlrendszer, azonban azzal ellentétben kizárólag Linux alatt létezik. A procfs-sel szemben, amelynek elsődleges funkciója, hogy a rendszeren futó processzek adatsruktúráihoz biztosítson elegáns módon hozzáférést, a sysfs a kernel által kezelt hardver- és egyéb eszközök adatbázisát teszi elérhetővé, és rendkívül szorosan kapcsolódik az Udev rendszerhez, valamint annak netlink üzeneteihez. Háromféle udev esemény létezik (azaz az Udev man oldalán bemutatott ACTION paraméter háromféle értéket vehet fel): add (egy eszköz hozzáadása), change (egy eszköz állapotának változása), remove (egy eszköz eltávolítása). Minden esemény mindig pontosan egy adott eszközhöz tartozik, és minden rendszereszközt reprezentál egy alkönyvtár a sysfs fájlrendszerben. Mivel egy adott hardvereszköz többféle aspektusához több rendszereszköz rendelődhet a kernelben és a sysfs-ben, nem ritka, hogy egy hardvereszköz csatlakoztatása több rendszereszköz megjelenésével, ezáltal több udev esemény generálódásával jár. Pl. egyetlen USB pendrive megjelenik driverként, usb eszközként, scsi hosztként, generic scsi eszközként, scsi lemezként, blokkeszközként, stb., és ezek mindegyikének saját alkönyvtára van a sysfs-ben, többnyire a könyvtárfa egymástól távol eső ágaiban. A netlinkben kapott uevent üzenet DEVPATH paramétere megmutatja, hol kell keresnünk a sysfs-en belül azt a könyvtárat, amely az eseményhez tartozó rendszereszközt reprezentálja, a DEVPATH ugyans nem más, mint az adott könyvtár elérési útja a sysfs könyvtárfáján belül. Az eszköz sysfs könyvtárát tehát alapesetben a /sys/DEVPATH
helyen kell keresnünk. Az ueventben KERNEL néven szereplő paraméter a DEVPATH utolsó tagjával, vagyis a szóbanforgó eszközt szimbolizáló sysfs könyvtár nevével egyezik meg. Azon rendszereszközök esetében, amelyek karakter- vagy blokk-speciális UNIX eszközfájlként is megjelennek (pl. merevlemezek, hangeszközök, kommunikációs portok, stb.), a KERNEL paraméterben szereplő névvel kerül létrehozásra az eszközfájl a /dev
könyvtárban. Az az eszköz tehát, amelynek DEVPATH-ja /class/block/sda
(tehát a KERNEL paraméter értéke sda
), alapértelmezetten /dev/sda
néven fog létrejönni az eszközfájlok könyvtárában. Az eszközöknek a sysfs-en keresztül olyan paramétereit is elérhetjük, amelyek az ueventet hordozó netlink üzenetből hiányoznak, pl. az Udev man oldalában ATTR néven említett attribútumokat. Az ATTR attribútumok a sysfs fájlrendszerben közönséges fájlokként jelennek meg, amelyekre hivatkozhatnak az udev szabályok szűrőfeltételei (azaz függővé tehetjük a bennük levő értékektől, hogy az adott szabály szűrőfeltétele találatot adjon-e), sőt az udev szabályok meg is változtathatják az ATTR attribútumok értékét, aminek eredményeképpen az udevd egyszerűen beleírja a kívánt értéket a megfelelő ATTR attribútumot hordozó fájlba, amit természetesen parancssorból is megtehetünk az udevd-től függetlenül. Az én gépemen pl. az `echo 7 > /sys/devices/pci0000:00/0000:00:02.0/backlight/acpi_video0/brightness`
parancs (figyelem: erősen hardverfüggő) maximális fényerőre állítja az elsődleges LCD kijelző háttérvilágítását. Hasonló hatást elérhettem volna a következő udev szabállyal is:
SUBSYSTEM=="backlight", KERNEL=="acpi_video0", ATTR{brightness}="7"
Ezen szabály szépséghibája, hogy a szűrőfeltételei nem vizsgálják az ACTION paraméter értékét, tehát az adott hardvereszköztől eredő összes udev esemény aktiválni fogja. Mivel az ATTR attribútumok értékadása maga is change típusú ueventet vált ki, a fenti szabály első találata (pl. fényerőváltozással járó energiagazdálkodási esemény vagy a fényerő manuális állítása) végtelen ciklusba hajszolja az udevd démont, nem elhanyagolható mértékű CPU terhelést és áramfogyasztást előidézve...
A sysfs-ből nem csak a rendszereszközök ATTR attríbútumai nyerhetők ki, hanem pl. az ENV (environment, újabban pedig property) paraméterek értékei is. Az ENV változók az ATTR paraméterektől eltérő módon nem különálló fájlokban, hanem az uevent nevű fájlban ömlesztve találhatóak. Ennek szemléltetésére próbáljunk meg kiíratni egy /sys/DEVPATH/uevent
jellegű fájlt, pl.:
# cat /sys/class/block/sda/uevent
MAJOR=8
MINOR=0
DEVNAME=sda
DEVTYPE=disk
Az ENV változók abban is eltérnek az ATTR attribútumoktól, hogy az ueventeket hordozó netlink üzenetek is tartalmazzák őket (amint ezt a fenti, `udevadm monitor --property`
parancs kipróbálásakor megfigyelhettük), tehát a szűrőfeltételek kiértékelésekor az udevd-nek nem kell a sysfs-ből olvasnia. Az udev man oldala szerint az ATTR attribútumokthoz hasonlóan az ENV változók értékeit is megváltoztathatják az Udev szabályok, ezeket a változásokat azonban az udevd nem írja vissza a sysfs-be (konkrétabban az uevent fájlba), hanem - többek között a TAG címkékkel együtt - eltárolja őket a /run/udev
(korábban /var/run/udev
) könyvtárban található adatbázisába. Amint később látni fogjuk, az udevd a kerneltől kapott uevent üzeneteket tovább is küldi. A továbbküldött ueventekben szintén az adatbázisban tárolt módosított ENV értékek szerepelnek, a módosított ATTR attribútumokkal, a hozzáadott TAG címkékkel és a feldolgozás eredményeként végrehajtott minden változtatással együtt.
Az ENV értékeket többek között azért nem írhatjuk vissza az uevent fájlokba, mert azoknak nem módosítható a tartalma. Ennek ellenére mégis írhatóak: Egy uevent fájlba az "add", "change" vagy "remove" karaktersorozatot írva arra utasítjuk a kernelt, hogy generáljon egy megfelelő típusú ueventet, és küldje ki azt netlink üzenet formájában. Ennek eredményeképpen az Udev és D-Bus rendszer úgy fog reagálni, mint ha az adott eszköz tényleg az adott pillanatban csatlakozott volna a rendszerhez, vagy éppen akkor módosult volna az állapot, esetleg leválasztódott volna a rendszerről. A fenti háttérvilágítást figyelő Udev szabály végtelen ciklusa tehát a fényerő tényleges változtatása nélkül is elindítható pl. az alábbi paranccsal:
`echo change > /sys/devices/pci0000:00/0000:00:02.0/backlight/acpi_video0/uevent`
Az ily módon mesterségesen kikényszerített ueventek semmiben nem térnek el a valós eseménye alapulóktól, az udevadm parancs monitor funkciójával tehát ugyanúgy megfigyelhetjük ezeket is.
Amint a fentiekből kiderül, manapság az udev rendszer számos rendszerközeli feladatot lát el, többek elvégzi a futásidőben szükségessé váló kernelmodulok betöltését, a /lib/firmware
könyvtárból kiolvassa majd átadja a kernelnek a driverek által bekért firmware-eket, a sorozat második részében bemutatott ConsoleKit rendszer adatbázisát felhasználva beállítja az adott eszközfájlok jogosultságait, hogy csak az éppen aktív konzol előtt ülő felhasználók érhessék el azokat, stb. A legérdekesebb, és egyben legironikusabb azonban az, hogy a legutóbbi időkben az udev elvesztette az eredeti funkcióját, azaz nem hoz létre eszközfájlokat a /dev könyvtárfában!!!
A legkorszerűbb disztribúciókban a /dev könyvtár alá sima tmpfs helyett devtmpfs típusú fájlrendszer mountolódik, amelynek a létrehozásában ugyanaz a Greg Kroah-Hartman működött nagy mértékben közre, aki annak idején "kifúrta" a devfs fájlrendszert. A devtmpfs védelmében elmondható, hogy a kb. 3600 soros devfs kóddal szemben mindössze 300 sorból áll, mert egyrészt teljes mértékben a meglevő tmpfs kódra épül, másrészt rendkívül egyszerű a működése: a létrejövő eszközfájlok UNIX tulajdonosát, csoportját és jogosultságait egyáltalán nem állítja be, mivel ez továbbra is az Udev feladata, csakúgy mint az eszközfájlokra mutató beszédes nevű symlinkek létrehozása, és a néhai hotplug rendszer funkcióinak (pl.kernelmodul- és firmware betöltés) kiváltása. A devtmpfs alapvetően közönséges tmpfs-ként működik, azaz bármilyen típusú fájlt létrehozhatunk benne a szokásos eszközökkel, az egyedüli különlegessége mindössze annyiban áll, hogy a kernel automatikusan létrehozza és törli benne a csatlakoztatott és leválasztott eszközök UNIX eszközfájljait.
A devtmpfs elterjedése óta az udevd újabb változatai hibaüzenetet adnak, ha egy Udev szabály (ld. udev man oldal, mint fent) a KERNEL paraméterben megadott alapértelmezett eszközfájlnévtől eltérő nevű UNIX eszközfájlt kísérel meg létrehozni, azaz értéket ad a NAME paraméternek, hiszen a /dev könyvtárbeli eszközfájlokat már nem az udevd, hanem maga a kernel hozza létre, mégpedig a KERNEL paraméterben meghirdetett alapértelmezett néven. Ez alól a szabály alól csak a hálózati eszközök (vezetékes- és vezetéknélküli hálókartyák, VPN alagutak, stb.) képeznek kivételt, hiszen azokhoz nincs eszközfájlt hozzárendelve a /dev könyvtárfában. A hálózati eszközök neveinek megváltoztatását végző Udev szabályok általában a /etc/udev/rules.d/70-persistent-net.rules
fájlban vannak. Ezt a fájlt az udevd maga generálja, minden újonnan megismert hálózati eszközt felvéve bele, de nyugodtan szerkeszthetjük magunk is. Amint láthatjuk, az ebben a fájlban levő szabályok büntetlenül értéket adhatnak a NAME paraméternek.
Greg Kroah-Hartmannak a devtmpfs melletti legfontosabb érvei azok voltak, hogy egyrészt szinte kihasználatlan volt a létrehozandó UNIX eszközfájlok nevének megváltoztatásának (azaz a NAME paraméter megváltoztatásának) lehetősége az Udev-ben - kivéve a továbbra is tetszőlegesen változtatható nevű hálózati eszközöket, amelyek viszont nem eszközfájlok -, helyette szinte kizárólag symlinkekkel valósították meg az állandó eszközneveket (pl. /dev/disk/by-uuid/*, /dev/disk/by-path/*, /dev/disk/by-id/*, /dev/input/by-id/*, /dev/input/by-path/*, stb.), másrészt pedig megjelentek az Androidhoz hasonló pehelysúlyú Linux alapú rendszerek, amelyek lehetőség szerint az Udev használatát is mellőzik, és ezen rendszereknek nagy segítséget jelenthet a devtmpfs.
Amint már említettem, a korszerű Udev alapú rendszerekben az eszközesemények (ún. uevent-ek) kizárólag a netlink hálózati alrendszeren keresztül jutnak el a kernelből az udevd démonhoz. Ezen felül az udevd a feldolgozott eseményeket továbbküldi ugyancsak netlinken keresztül néhány további démonnak (pl. udisks, UPower), amelyek aztán többnyire D-Bus szignálokat generálnak belőlük. A netlink nem kapcsolat, hanem csomagalapú kommunikáció. Minden Udev esemény (uevent) külön netlink csomagban utazik. A sorozat első részében már hivatkozott "Demystifying Unix Domain Sockets" című tanulmány szerzője tulajdonképpen megkérdőjelezi a netlink létjogosultságát, és első pillantásra tényleg felmerülhet a kérdés, hogy miért nem unix domain socketeken, vagy egyenesen D-Bus-on keresztül történik az Udev kommunikáció? Nos, a Kay Sievers-szel folytatott IRC párbeszéd rávilágított ennek az okaira: Az unix domain socketeken a legutóbbi időkig nem működött (rendesen?) a multicast csomagtovábbítás és a Berkeley Packet Filter nyomán kifeljesztett Linux Socket Filter, holott az Udev kommunikáció kizárólag multicast üzenetekkel történik, és az eseményeket szállító csomagokat LSF szűrővel szűrik a hallgatózó Udev programok (igaz, a legutóbbi időkben ezen a területen is megindult a fejlődés: ld. itt és itt). A D-Bus démon által biztosított kommunikációs közegben mind a broadcast üzenetküldés, mind a csatornába integrált üzenetszűrés megoldott, de nem kernel, hanem user módú kódban, ami a rendkívül rendszerközeli Udev számára túlságosan nehézsúlyú megoldás lenne, főként mivel az udevd démonnak a boot folyamat olyan korai fázisában kell indulnia, hogy egyszerűen nem engedheti meg magának, hogy egy másik démonra, jelen esetben a D-Bus démonra várjon.
A netlinkkel, mint kommunikációs közeggel kapcsolatban biztonsági aggályok is felmerülhetnek, mert annak ellenére, hogy a Linux capabilities man oldala szerint RAW és PACKET típusú hálózati socket-ek nyitásához CAP_NET_RAW jogra (azaz gyakorlatilag root jogra) van szükség, a netlink man oldala szerint pedig a netlink multicast csoportok forgalmának fogadásához és küldéséhez egyaránt CAP_NET_ADMIN jog (szintén gyakorlatilag root jog) szükséges, a Linux kernel fejlődése során a jogosultsági rendszerben megjelenő számos kivétel folytán azt a helyzet állt elő, hogy unicast netlink csomagot közönséges felhasználók is küldhetnek bárkinek, illetve fogadhatnak bárkitől, sőt, a netlink multicast csoportok forgalmát is korlátlanul lehallgathatja bármely közönséges felhasználó, egyedül a multicast csomagok küldése van CAP_NET_ADMIN joghoz kötve. Ezen ellenőrzésbeli lazaságok legalább egy esetben biztonsági problémához is vezettek az Udev rendszerben, amely a 141-es verzióig fenn is állt. A multicast csomagküldés root joghoz való kötésén és az LSF szűrők alkalmazásán felül az Udev kommunikációt folytató programok legfontosabb biztonsági eszköze a korábbi részekben az Unix Domain Socketeknél már említett SO_PEERCRED opcióhoz hasonló SO_PASSCRED opció, amely lehetővé teszi, hogy a netlinken kommunikáló programok minden egyes beérkező netlink csomaggal együtt kapjanak egy olyan adatstruktúrát is a kerneltől, amiből kiolvashatják a csomagot küldő processz UID-jét, PID-jét, stb. Ezen opció, és a kizárólag multicast kommunikáció használata - úgy tűnik - képes megakadályozni, hogy illetéktelen személyek hamis Udev eseményeket injektáljanak az Udev rendszerbe, a kerneltől és az udevd-től származó ueventek lehallgatása viszont mindenki számára lehetséges, aki futtatni (és/vagy esetleg lefordítani) tud egy egy erre alkalmas programot.
Amint már szó volt róla, az uevent eseményeket a kernel küldi az udevd démonnak, amely az Udev szabályok alapján feldolgozza azokat. A feldolgozás során módosíthatja az eseményben, mint adatcsomagban levő paraméterek értékeit, új paramétereket adhat hozzá, sőt az eseményre adott válaszként különböző műveleteket hajthat végre, pl. kernelmodult vagy firmware-t tölthet be, tetszőleges parancsokat futtathat le az eseményt kiváltó eszköz bekonfigurálásának céljából (vagy más célból), módosíthatja a devtmpfs által létrehozott eszközfájl UNIX tulajdonosát, csoportját, jogosultságait, POSIX ACL-jét, az eszközfájlra mutató symlinkeket hozhat létre, és számos más feladatot is végrehajthat. Az udevd a feldolgozott (és esetleg módosított) uevent eseményeket továbbküldi, és amint már utaltam rá, az udevd által kiküldött udev eseményekből sok esetben D-Bus szignál lesz a rendszer D-Buson. Amikor az Udev témakört elkezdtem feldolgozni, kezdetben azt gondoltam, hogy az udevd maga is csatlakozik a rendszer D-Busra, és saját maga küldi a D-Bus szignálokat a rendszer D-Buson hallgatózó D-Bus klienseknek. Mivel azonban - amint erre Kay Sievers rávilágított - az udevd nem várhatja meg a D-Bus indulását (és ha esetleg megvárhatná, sem függhetne tőle, mert rendkívül megbízhatónak kell lennie), nyilvánvaló, hogy az udevd nem tart fenn semmilyen közvetlen kapcsolatot a D-Bus-szal. Ehelyett van egy közvetítő réteg néhány olyan démon formájában, amelyek az udevd-vel és a D-Bus-szal egyaránt kapcsolatban állnak: fogadják az udevd-től érkező feldolgozott ueventeket, ismét feldolgozzák, és a feldolgozás eredményeképpen D-Bus szignálokat küldenek ki a rendszer D-Buson, ezen kívül pedig különböző D-Bus interfészek és azok metódusainak formájában olyan szolgáltatásokat nyújtanak a D-Bushoz kapcsolódó kliensek (többnyire grafikus felhasználói felületek, pl. KDE, Gnome) számára, amelyek lehetővé teszik a hatáskörükbe tartozó eszközök aszinkron lekérdezését vagy akár menedzselését. Ilyen köztes démonok pl. a már többször említett UPower, udisk és NetworkManager alrendszerek. Az ilyen udevd-hez kapcsolódó köztes démonok a kernel által küldött netlink csomagokhoz nagy mértékben hasonlító (az adatformátum gyakorlatilag azonos, csak a fejlécben van némi eltérés) netlink csomagokban kapják meg az udevd-től a feldolgozott ueventeket, és sok esetben saját maguk is olvassák és/vagy írják az adott rendszereszközökre vonatkozó bejegyzéseket a sysfs fájlrendszerben. Az érdekesség kedvéért megjegyzem, hogy az Udev rendszer minden komponense a NETLINK_KOBJECT_UEVENT "protokollt" használva küldi és fogadja az uevent csomagokat a netlink hálózaton, de míg a kerneltől az udevd-hez tartó netlink csomagok az 1-es számú multicast csoportban, addig az udevd-től a köztes alrendszerek felé irányuló csomagok a 2-es számú multicast csoportban kerülnek elküldésre, tehát nem keverednek egymással. Mivel azonban az Udev rendszer megvalósításának ilyen lényegtelen részletei időről időre megváltozhatnak, nem érdemes alapozni rájuk. Az udevd által küldött netlink adatcsomagoknak és a sysfs fájlrendszerben levő adatbázisnak az értelmezését nagyban megkönnyíti a libudev programkönyvtár, amit a szóbanforgó köztes démonok általában mind ki is használnak. Az udevd és a D-Bus rendszer elkülönítése azért is előnyös, mert amíg az Udev rendszerre gyakorlatilag minden GNU/Linux disztribúciónak szüksége van, addig a D-Bus feladatköre alapvetően a Linux desktopra terjed ki, és bár bizonyos szoftverfüggőségek ezt néha megnehezítik (és a jövőben egyre inkább meg fogják), kellően paranoiás rendszergazdák kikapcsolhatják a D-Bust a kizárólag szerverfeladatokat ellátó gépeken.
Az Udev szabályokban a RUN direktívát felhasználva lehetőség van az uevent eseményekre adott válaszként tetszőleges parancsok futtatására. Maga az udev programcsomag is tartalmaz néhány szabványos segédprogramot, amelyekkel az Udev szabályok rendszerkonfigurációs feladatokat hajthatnak végre. Ezen szabványos segédprogramok helye a /lib/udev
könyvtár gyökerében van. Amennyiben egy Udev szabály RUN opciójában relatív (nem / karakterrel kezdődő) elérési úttal rendelkező parancs végrehajtására adunk utasítást, az udevd ebben a könyvtárban fogja keresni a végrehajtandó programfájlt. Ezen szabványos segédprogramok némelyikét nem csak az Udev, hanem más alrendszerek is felhasználják. A /lib/udev/scsi_id
segédprogramot pl. a multipath alrendszer használja, hogy kinyerje a különböző blokkeszközök LUN WWN azonosítóit az SCSI Inquiry parancs útján. A /lib/udev/udev-acl
segédprogram pedig a második részben tárgyalt ConsoleKit alrendszer adatbázisát felhasználva állítja be bizony UNIX eszközfájlok jogosultságait, ezáltal kiváltva a néhai Resource Manager feladatait. A /lib/udev/udev-acl
segédprogramot egyébként nem csak az udevd futtatja a /lib/udev/rules.d/70-udev-acl.rules szabálygyűjtemény feldolgozásának eredményeképpen, hanem a ConsoleKit maga is meghívja a /usr/lib/ConsoleKit/run-seat.d/udev-acl.ck symlinken keresztül, így biztosítva az aktív konzol megváltozásakor az azonnali jogosultságbeállításokat, aminek eredménye többek között a zenelejátszónk azonnali elnémulása egy inaktív szöveges virtuális terminálra történő váltás (pl. Alt+Ctrl+F1) esetén.
Végezetül néhány jó tanács (aki tudja, egészítse ki!):
Amint már többször utaltam rá, az Udev rendszer segít a kernelnek betölteni a firmware állományokat. Amikor egy kernel modul meghívja a request_firmware függvényt, a kernel egy uevent üzenetben kéri meg az udevd-t, hogy keresse meg és adja át a szükséges firmware binárist. Ha azt gyanítjuk, hogy firmware-betöltési problémák adódtak a rendszerünkön, nézzünk utána, nem tartalmaz-e a dmesg erre utaló hibaüzenetet, illetve hogy minden rendben van-e a /lib/udev/rules.d/50-firmware.rules
szabálygyűjtemény és a /lib/firmware
könyvtár környékén!
Az Udev nem csak a firmware-ek, hanem a kernel modulok betöltését is elvégzi (igaz, nem minden esetben). Ha egy kernelmodul explicit módon kéri egy másik kernelmodul betöltését a request_module függvény meghívásával, akkor a kernel közvetlenül futtatja a modprobe parancsot (pontosabban azt a binárist, amelynek neve a /proc/sys/kernel/modprobe
fájlban megadásra került), amennyiben viszont egy hotplug esemény okán válik szükségessé egy kernelmodul betöltése, akkor a kernel uevent üzenetben kéri meg az udevd-t, hogy töltse be (a modprobe segítségével) a szükséges kernelmodult. Ha azt gyanítjuk, hogy a hotplug események által igényel kernelmodul-betöltéseket nem megfelelően végzi a rendszerünk, nézzük meg, hogy minden rendben van-e /lib/udev/rules.d/80-drivers.rules
szabálygyűjtemény és a /lib/modules
könyvtár háza táján!
Többször is említettem már érintőlegesen az Udev rendszer (különösen az udevd démon) menedzselésére szolgáló udevadm parancsot. A parancs man oldalának áttanulmányozása és némi kísérletezés után jó hasznát vehetjük ennek a programnak, többek között a monitor funkciónak, amellyel új Udev szabályok írásához szükséges információkat nyerhetünk ki a rendszerből. A man oldalhoz fontos hozzátenni, hogy a parancs trigger funkciójával (amely nem csinál mást, mint az "add, "change" vagy "remove" karaktersorozatot írja a kiválasztott rendszereszközök sysfs könyvtáraiban levő uevent fájlokba) érdemes óvatosan bánni, különben nem kívánt következményekkel leszünk kénytelenek szembenézni.
Köszönöm a figyelmet. Elnézést kérek, hogy elvesztem a részletekben a netlink kommunikáció taglalásánál. Az volt a célom, hogy a biztonságra valamit adó Linux rendszergazdáknak fogalmuk legyen arról, milyen kockázatok merülhetnek fel az Udev rendszerrel kapcsolatban.
- nice blogja
- A hozzászóláshoz be kell jelentkezni
Hozzászólások
- A hozzászóláshoz be kell jelentkezni
szintén
- A hozzászóláshoz be kell jelentkezni
subscribe
- A hozzászóláshoz be kell jelentkezni
Már vártam, ez egy szuper sorozat, gratulálok érte! :)
-----
"Egy jó kapcsolatban a társunkat az ő dolgában kell támogatni, nem a miénkben."
rand() a lelke mindennek! :)
- A hozzászóláshoz be kell jelentkezni
Köszi mindenkinek az elismerést. Volt egy kis javítás, pontosítás és kiegészítés a cikkben, de azt hiszem, most már tényleg kész. Olvassátok el újra! Jó éjszakát!
- A hozzászóláshoz be kell jelentkezni
subscribe
- A hozzászóláshoz be kell jelentkezni
trey, ha olvasod, szerinted ez elférne a főoldalon?
-----
"Egy jó kapcsolatban a társunkat az ő dolgában kell támogatni, nem a miénkben."
rand() a lelke mindennek! :)
- A hozzászóláshoz be kell jelentkezni
WIKI -be, plz!
Köszönjük!
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni