Chwila zabawy z Udev'em
31 stycznia, 2009W życiu każdego człowieka przychodzi taka chwila w której zdaje sobie sprawę, że denerwuje go fakt iż nazwa z jaką jakieś urządzenie pojawi się w systemie zależy od kolejności jego podłączenia względem innych urządzeń podobnej klasy. Jeśli mamy np tylko jednego pendrive'a lub jeden dysk usb wtedy nie ma żadnego problemu. Lecz jeśli posiadamy obydwa te urządzenia a do tego jeszcze telefon , mp3 player i w dodatku chcemy podłączyć je wszystkie na raz, to zaczynają się schody.
W takiej sytuacji niemożliwe staje się napisanie jakiś sensownych reguł w /etc/fstab. Ale dlaczego? Dlatego, że jeśli podłączymy najpierw dysk usb a potem pendrive to dysk zostanie oznaczony jako sdb a pendrive jako sdc (zakładając, że główny dysk jest podłączony poprzez interfejs SATA, ale to w tej chwili nie ma zupełnie znaczenia) natomiast jeśli wykonamy te czynności w odwrotnej kolejności wtedy 'etykiety' urządzeń będą inne. Niby niema problemu, można podłączać urządzenia w określonej kolejności, ale w końcu to nie my mamy robić to co chce komputer a komputer to co my chcemy. W tym momencie z pomocą przychodzi udev.
Udev jest menadżerem urządzeń wprowadzonym w jądrze 2.6.13 który zastąpił wysłużony już devfs. W odróżnieniu od swego poprzednika udev działa w przestrzni użytkownika. Nie przechowuje on jednak statycznego katalogu /dev ale pliki reprezentujące jedynie urządzenia dostępne w danej chwili w systemie.
Jedną z ciekawszych cech udev'a na której chciałem się skupić jest możliwość nadawania urządzeniom stałych nazw, niezależnie od kolejności ich podłączenia oraz nie zmieniających się po reboocie.
Wszystkie reguły używane przez udev'a umieszczone są na katalogu /etc/udev/rules.d/. Jak można zauważyć większość plików ma przed nazwą liczbę. Determinuje ona kolejność w jakiej pliki będą przetwarzane w trakcie pracy managera.
Napiszemy teraz własną regułę dotyczącą przykładowego sprzętu, np Pendrive'a. Aby otrzymać informacje na jego temat wystarczy wykonać kilka prostych komend.
W pliku /proc/partitions sprawdzamy jaka nazwa została przyporządkowana właśnie podłączonemu urządzaniu. W moim przypadku było to sdb.
Teraz należy się dowiedzieć gdzie na katalogu /sys leżą informacje o danym urządzeniu. W tym celu wydajemy komendę udevadm info --query=path --name=/dev/sdb (na innych systemach może ona wyglądać trochę inaczej dlatego polecam manual około udev'owy)
bash-3.2$ udevadm info --query=path --name=/dev/sdb/
/block/sdb
Lokalizacja nie jest nader skomplikowana. Jeśli ktoś jest ciekawy i wytrwały może wyciągnąć atrybuty bezpośrednio stamtąd. Ja natomiast skupię się na rozwiązaniu dla niecierpliwych.
Wydajemy komendę udevadm info -a --path=/sys/block/sdb
looking at device '/block/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
DRIVER==""
ATTR{range}=="16"
ATTR{ext_range}=="256"
ATTR{removable}=="1"
ATTR{ro}=="0"
ATTR{size}=="1966080"
ATTR{capability}=="53"
ATTR{stat}==" 76 2069 3706 373 1 0 1 3 0 236 376"
looking at parent device '/devices/pci0000:00/0000:00:13.5/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':
KERNELS=="6:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{device_blocked}=="0"
ATTRS{type}=="0"
ATTRS{scsi_level}=="0"
ATTRS{vendor}=="Sony "
ATTRS{model}=="Storage Media "
ATTRS{rev}=="0100"
ATTRS{state}=="running"
ATTRS{timeout}=="30"
ATTRS{iocounterbits}=="32"
ATTRS{iorequest_cnt}=="0x14d"
ATTRS{iodone_cnt}=="0x14d"
ATTRS{ioerr_cnt}=="0x2"
ATTRS{modalias}=="scsi:t-0x00"
ATTRS{evt_media_change}=="0"
ATTRS{queue_depth}=="1"
ATTRS{queue_type}=="none"
ATTRS{max_sectors}=="240"
looking at parent device '/devices/pci0000:00/0000:00:13.5/usb1/1-1/1-1:1.0/host6/target6:0:0':
KERNELS=="target6:0:0"
SUBSYSTEMS==""
DRIVERS==""
.....
W tym momencie mamy wszystkie niezbędne informacje potrzebne do napisanie reguły która utworzy nam piękną nazwę dla pendrive'a. Ważne jest aby nie mieszać atrybutów określających różne urządzenia.
Na katalogu/etc/udev/rules.d/ tworzymy sobie jakiś pliczek z rozsądnym numerem. Możemy się gdzieś co prawda dopisać ale to niezbyt eleganckie rozwiązanie. Następnie w świeżo utworzonym pliku umieszczamy regułę.
KERNEL=="sd*" , SUBSYSTEM=="block" , ATTRS{vendor}=="Sony " , ATTRS{model}=="Storage Media " , SYMLINK+="Sony"
Powyższa reguła mówi że dla każdego urządzenia blokowego które zostanie nazwane przez jądro jako sd* oraz którego producentem jest Sony a nazwą modelu Storage Media zostanie utworzone dodatkowe dowiązanie symboliczne od nazwie Sony.
W tym momencie pozostało nam jeszcze przeładować udev'a za pomocą komendy udevadm trigger lub udevadm control --reload-rules.
Po jej wykonaniu na katalogu /dev pojawi się dowiązanie symboliczne o nazwie Sony, którego możemy z powodzeniem użyć pisząc reguły w pliku /etc/fstab.
Podobną procedurę możemy zastosować w zasadzie do każdego urządzenia, nie tylko zewnętrznego.
Jak pewnie większość z was zauważy opisałem zagadnienie trochę z samolotu, ale taka już specyfika blogowej notki. Ciężko w niej wyczerpać tak obszerny temat. Na otarcie łez mogę polecić stronę na której zainteresowani będą mieli okazję uzupełnić swoją wiedzę o pisaniu reguł dla udev'a. Klik.
1.
Nelchael napisał(a):
31 stycznia 2009, 16:00:38
A dlaczego nie korzystać z etykiet? Hint: /dev/disk/by-label/...
2.
Avilar napisał(a):
31 stycznia 2009, 16:05:27
Ja na katalogu /dev/disk nie mam katalogu by-label.
drwxr-xr-x 2 root root 0 sty 31 13:33 by-id
drwxr-xr-x 2 root root 0 sty 31 13:33 by-path
drwxr-xr-x 2 root root 0 sty 31 13:33 by-uuid
Powiem szczerze, to co się znajduje w moich zasobach do przesadnie czytelnych nie należy.
3.
Nelchael napisał(a):
31 stycznia 2009, 16:08:37
Czyli nie korzystasz z etykiet, u mnie (mam etykiety na wszystkich dyskach USB) /etc/fstab:
/dev/disk/by-label/gstick /mnt/gstick vfat noauto,user,fmask=113,dmask=002 0 0
/dev/disk/by-label/ibmstick /mnt/ibmstick vfat noauto,user,fmask=113,dmask=002 0
Polecam tune2fs -L (lub reiserfstune, etc ...).
4.
Avilar napisał(a):
31 stycznia 2009, 16:23:51
W sumie nigdy ich tam chyba nie było i powiem szczerze niewiele wiem na ten temat. Partycje mam co prawda identyfikowane przez UUIDy ale nigdy się w to nie zagłębiałem. Poczytam ;)
5.
Michał Górny napisał(a):
31 stycznia 2009, 19:25:58
Avilar: then ur distro (udev?) is a fail, Sir.
6.
zdz napisał(a):
31 stycznia 2009, 23:42:08
"Udev jest menadżerem urządzeń wprowadzonym w jądrze [...] udev działa w przestrzni użytkownika." Dwa zdania zaprzeczające sobie nawzajem (swoją droga, co zostało zmienione w tej kwesti w 2.6.13?)
Druga sprawa, wpisy w /etc/fstab dla urządzeń wymiennych są jakieś takie trącące myszką. Do niedawna zalecanym sposobem mountowania ich było używanie wywołań HALa, obecnie DeviceKit-disks.
Polecam też zapoznanie się z poleceniem "blkid", w przejrzysty sposób wyświetla urządzenia, labele i UUIDy.
7.
Avilar napisał(a):
01 lutego 2009, 14:00:20
@zdz: No może powinienem napisać, że udev w obecnym kształcie jest dołączany do wszystkich (większości?) systemów z jądrami w wersji >= 2.6.13. Tak czy śmak nie miałem na myśli , że jest częścią jądra. Co do HALa i reszty to chętnie się zapoznam ;)
8.
zdz napisał(a):
02 lutego 2009, 11:59:52
Wciąż dziwi mnie ta wersja. W 2.6.13 jedynie usunięto devfs. Natomiast udev pojawił się jakieś 6 lat temu, współpracował z jądrami w wersji 2.5.x.
9.
Avilar napisał(a):
02 lutego 2009, 19:32:36
"The latest versions of udev depend on the latest version of the uevent interface of the Linux kernel which has been updated or introduced with Linux kernel 2.6.13".
To z wiki. Chyba trochę spałem jak czytałem to ostatnim razem.
10.
Michał Górny napisał(a):
12 lutego 2009, 00:09:49
Swoją drogą, @Nelchael: lepiej zamiast /dev/disk/by-label/ używać po prostu LABEL=. Wtedy będzie działać nawet wtedy, gdy udev nie wystartuje.