Praca z udev w Gentoo
1.
Czym jest udev?
Katalog /dev
Kiedy użytkownicy Linuksa rozmawiają o ich sprzęcie w pobliżu ludzi, którzy
wierzą, że Linux jest pewnego rodzaju wirusem lub gatunkiem kawy, użycie słów
"ukośnik dev ukośnik coś tam" spowoduje, że zaczną się oni dziwnie na nich
patrzeć. Ale szczęśliwy użytkownik (i to jesteśmy my) używając
/dev/hda1 skrótowo wyjaśnia, że rozmowa tyczy się pierwszej
partycji dysku, który jest podpięty jako primary master. Czy nie mam racji?
Wszyscy wiemy czym jest plik urządzenia. Niektórzy nawet wiedzą dlaczego pliki
urządzeń posiadają specjalne numery, które widać wykonując polecenie
ls -l w /dev. Ale zawsze dysk podpięty jako primary master
jest widoczny jako /dev/hda. Można tego nie widzieć w ten sposób,
ale jest to wada projektu.
Pomyślmy o urządzeniach podłączanych podczas pracy takich jak USB, IEEE1394,
PCI... Co jest pierwszym urządzeniem? I na jak długo? Jak będą inne urządzenia
nazwane, kiedy to pierwsze zniknie? Jaki to będzie miało wpływ na inne procesy?
Czyż nie byłoby to zabawne gdyby zadanie do drukowania zostało nagle
przeniesione z naszej nowiutkiej drukarki laserowej do naszej zrupieciałej
drukarki mozaikowej, ponieważ mama zdecydowała się wyciągnąć wtyczkę drukarki
laserowej, która była pierwszą drukarką, z kontaktu?
Wchodzimy do udev. Główne cele projektu udev są zarówno ciekawe jak i
konieczne:
- Działa w przestrzeni użytkownika
- Dynamicznie tworzy lub usuwa pliki urządzeń
- Dostarcza spójne nazewnictwo
- Dostarcza interfejsu API przestrzeni użytkownika
Aby dostarczyć te cechy, udev jest rozwijany w trzech odrębnych projektach:
namedev, libsysfs oraz udev.
namedev
Namedev pozwala zdefiniować odrębne nazewnictwo niż to w udev. To pozwala na
elastyczne polityki i schematy nazewnictwa rozwijane przez odrębne jednostki.
Ten podsystem nazewnictwa urządzeń dostarcza standardowego interfejsu, którego
może używać udev.
Obecnie namedev dostarcza tylko jeden schemat nazewnictwa - LANANA, który jest
używany przez większość obecnych systemów Linuksowych, a zatem pasuje on
większości użytkowników Linuksa.
Namedev używa pięciostopniowej procedury pozyskiwania nazwy urządzenia. Jeśli
nazwa urządzenia zostanie znaleziona w tych pięciu krokach, wtedy zostanie ona
użyta. Są nimi:
- etykieta lub numer seryjny
- numer urządzenia magistrali
- topologia magistrali
- statycznie przydzielana nazwa
- nazwa dostarczona przez jądro
Krok etykieta lub numer seryjny sprawdza czy urządzenie posiada
jednoznaczny identyfikator. Na przykład urządzenia USB posiadają unikalny numer
seryjny, urządzenia SCSI posiadają unikalny UUID. Jeśli namedev znajdzie
odpowiednią nazwę wtedy zostanie ona użyta.
Krok numer urządzenia magistrali sprawdza numer urządzenia magistrali.
Dla systemów, które nie mają możliwości podłączania urządzeń w trakcie pracy,
ten krok jest wystarczający. Ponieważ numery magistrali bardzo rzadko są
zmieniane. Ponownie jeśli namedev znajdzie odpowiednią nazwę wtedy zostanie ona
użyta.
Podobnie krok topologia magistrali jest statycznym sposobem
przydzielania nazw, pod warunkiem, że użytkownik nie zamieni urządzeń. Jeśli
pozycja urządzenia będzie zgodna z tym co podał użytkownik, wtedy towarzysząca
temu nazwa zostanie użyta.
Krok czwarty, statycznie przydzielana nazwa, jest prostym zastępowaniem
ciągów znaków. Kiedy nazwa dostarczona przez jądro (domyślna nazwa) pasuje do
danego ciągu znaków, wtedy ten ciąg zostanie zastąpiony.
Ostatnim krokiem (nazwa dostarczona przez jądro) jest nadanie wszystkim
urządzeniom domyślnej nazwy dostarczonej wraz z jądrem. Większości systemów
Linuksowych ten krok jest wystarczający.
libsysfs
udev komunikuje się z jądrem poprzez pseudo system plików sysfs. Projekt
libsysfs dostarcza interfejsu API, który zezwala na dostęp do informacji danych
przez system plików sysfs. To pozwala na sprawdzenie całego sprzętu bez
konieczności posiadania wiedzy jakiego typu sprzęt jest sprawdzany.
udev
Za każdym razem kiedy jądro zauważy zmianę w drzewie urządzeń konsultuje się z
udev. udev najpierw postępuje zgodnie z zasadami z katalogu
/etc/udev/rules.d/, następnie wprowadza zmiany zasugerowane przez
jądro (usuwając lub dodając pliki w katalogu /dev.
2.
Praca z udev w Gentoo
Wymagania
udev został stworzony do pracy wraz jądrem 2.6 (na przykład
gentoo-sources w domyślnym profilu 2007.0). Jeśli używamy takiego jądra,
wtedy należy się upewnić, że posiadamy najnowszą wersję pakietu
sys-apps/baselayout.
Listing 2.1: Instalacja udev |
# emerge udev
|
Użytkownicy korzystający z ręcznie skompilowanego jądra muszą włączyć
następujące opcje:
Listing 2.2: Wymagane opcje jądra |
General setup --->
[*] Support for hot-pluggable devices
File systems --->
[*] Inotify file change notification support
[*] Inotify support for userspace
Pseudo filesystems --->
[*] /proc file system support
[*] Virtual memory file system support (former shm fs)
|
Użytkownicy genkernela, nie muszą robić nic dodatkowo. Konfiguracja udev
przez genkernel zachodzi domyślnie.
Konfiguracja
Jeśli chcemy, aby ustawienia dodane przez deweloperów Gentoo ułatwiły nam życie
wtedy należy ominąć ten rozdział. Gentoo będzie używał udev, ale katalog
/dev będzie statyczny, żebyśmy nigdy nie doświadczyli braku
jakiegokolwiek węzła urządzenia. W tym wariancie skrypty Gentoo nie uruchomią
demona devfs i wyłączą devfs podczas uruchamiania systemu.
Jeśli jesteśmy twardzi i chcemy, aby nasz system używał tylko i wyłącznie udev
(mogą pojawić się brakujące węzły urządzeń spowodowane przez brak wsparcia ze
strony udev), wtedy należy czytać dalej.
Wyłączymy reguły, które zachowują węzły urządzeń do pliku: edytujemy zmienną
RC_DEVICE_TARBALL w /etc/conf.d/rc i ustawiamy ją na
no:
Listing 2.3: /etc/conf.d/rc |
RC_DEVICE_TARBALL="no"
|
Jeśli włączyliśmy w jądrze wsparcie dla devfs, możemy je wyłączyć dopisując do
parametrów jądra w pliku konfiguracyjnym bootloadera: gentoo=nodevfs.
Jeśli chcemy używać devfs i wyłączyć udev, wtedy jako parametr jądra
dodajemy gentoo=noudev.
3.
Znane problemy
Brakujące pliki węzła urządzenia podczas ładowania systemu
Jeśli nie potrafimy pomyślnie zakończyć procesu uruchamiania systemu ponieważ
wyskakuje nam błąd o nie znalezieniu /dev/null lub ponieważ brakuje
konsoli startowej, wtedy problemem jest brak pewnych plików urządzeń, które
muszą być dostępne przed zamontowaniem katalogu /dev.
Jeśli posiadamy sys-apps/baselayout-1.8.12 lub nowszy, wtedy ten problem
jest złagodzony ponieważ proces uruchamiania systemu powinien zakończyć się
powodzeniem. Jednakże, aby pozbyć się tych denerwujących ostrzeżeń, należy
stworzyć brakujące węzły urządzeń tak jak jest to przedstawione poniżej.
Aby sprawdzić które węzły urządzeń są obecne przed zamontowaniem
katalogu /dev należy wykonać następujące polecenia:
Listing 3.1: Wyświetlanie węzłów urządzeń dostępnych podczas uruchamiania systemu |
# mkdir test
# mount --bind / test
# cd test/dev
# ls
|
Urządzenia wymagane do pomyślnego załadowania systemu są umieszczone w
/dev/null oraz w /dev/console. Jeśli się nie pojawiły,
to należy je stworzyć ręcznie. Będąc w katalogu test/dev/ należy
wykonać:
Listing 3.2: Tworzenie wymaganych plików węzłów urządzeń |
# mknod -m 660 console c 5 1
# mknod -m 660 null c 1 3
|
Kiedy skończymy nie należy zapomnieć o odmontowaniu katalogu test/:
Listing 3.3: Odmontowywanie katalogu test/ |
# cd ../..
# umount test
# rmdir test
|
udev i nVidia
Jeśli używamy odpowiednich sterowników nVidii, ale serwer X nie uruchamia się,
wtedy należy upewnić się, że mamy:
-
moduł nvidia w /etc/modules.autoload.d/kernel-2.6
-
wersję baselayout równą lub wyższą sys-apps/baselayout-1.8.12
Spójne nazewnictwo pomiędzy DevFS a udev
Pomimo naszych starań, aby posiadać spójne nazewnictwo pomiędzy tymi dwoma
dynamicznymi sposobami nazewnictwa urządzeń, czasami pewne różnice w nazwach
występują.
Jednym ze zgłoszonych błędów jest kolizja z kontrolerem HP Smart Array 5i RAID
(a dokładniej modułem jądra cciss). W udev, urządzenia są nazywane
/dev/cciss/cXdYpZ gdzie X, Y i Z są normalnymi liczbami. W devfs
urządzeniami są /dev/hostX/targetY/partZ lub dowiązane symbolicznie
z /dev/cciss/cXdY.
W tym przypadku należy pamiętać o zaktualizowaniu pliku /etc/fstab
oraz o konfiguracji plików bootloadera
To samo dzieje się ze wszystkimi dowiązaniami z katalogu /dev,
takimi jak /dev/mouse, których udev już nie tworzy. Należy
się upewnić, że w pliku konfiguracyjnym X-ów posiadamy odpowiednie ustawienia.
Kolejny problemem jest różnica w nazwach terminali pomiędzy devfs i udev.
Terminale w devfs nazywają się tty, a w udev vc lub tty.
Może to przysporzyć kłopotu, gdy ogranicza się dostęp do konsoli za pomocą
pliku /etc/securetty. Należy zmienić wpis tty1 na
vc/1 w pliku /etc/securetty, aby root mógł logować się w
konsoli.
Zmiana nazw urządzeń blokowych
Nowsze wersje udev (104 i wyżej) oraz nowsze wersje jądra (2.6.19 i wyżej) mogą
zmienić nazwy plików urządzeń dyskowych, co ma związek ze zmianami implementacji
libata w jądrze. W związku z tym na przykład urządzenie nagrywarki CD-RW, które
kiedyś nazywało się /dev/hdc może zmienić nazwę na
/dev/sr0. W większości systemów nie powoduje to żadnych problemów.
Istnieje jednak pewna ilość programów, które mają na stałe wpisane gdzie powinno
znajdować się dane urządzenie, a to może prowadzić do błędów. Przykładem takiego
programu jest media-sound/rip, który zakłada, że znajdzie czytnik płyt CD
w pliku /dev/cdrom. W nowszych wersjach udev i jądra czytnik ten
może się nazywać na przykład /dev/cdrom1.
Aby zapobiec tego typu problemom, należy odpowiednio zmienić plik
/etc/udev/rules.d/70-persistent-cd.rules przypisując prawidłowe
nazwy problematycznym urządzeniom.
Więcej informacji na temat składni reguł udev znajduje się w tekście Daniela Drake'a.
Zmiana nazw urządzeń sieciowych
Czasem odłączanie i ponowne podłączanie urządzenia sieciowego (takiego jak karta
WiFi na USB) może powodować nadawanie nowej nazwy urządzeniu za każdym razem
zwiększając numer przy niej o jeden.
Z czasem wlan0 zmieni się na wlan1, następnie na wlan2 i
tak dalej. Jest to spowodowane tym, że udev dodaje nowe regułki do swojego pliku
konfiguracyjnego zamiast przeładować te już istniejące. Można temu zapobiec
dodając obsługę inotify do jądra:
Listing 3.4: Włączanie obsługi inotify w jądrze |
File systems --->
[*] Inotify file change notification support
[*] Inotify support for userspace
|
Dzięki temu udev będzie trzymał się prawidłowych nazw urządzeń sieciowych.
udev ładuje moduły w niemożliwej do przewidzenia kolejności
Czasami udev ładuje moduły w niepożądanej, niemożliwej do przewidzenia i
pozornie przypadkowej kolejności. To zjawisko występuje najczęściej w systemach,
które posiadają wiele urządzeń tego samego typu, takich jak urządzenia
multimedialne. Może to wpłynąć na przydzielanie numerów urządzeniom; na
przykład, karty dzwiękowe mogą niekiedy wymieniać się numerami.
Jest kilka sposobów na przypisanie numerów urządzeniom i/lub ustalenie
kolejności ładowania modułów. W najlepszym przypadku, aby określić pożądany
numer urządzenia, można użyć parametrów modułu. Niektóre moduły, takie jak ALSA,
zawierają parametr "index". Moduły używające tego parametru mogą zostać
dostosowane w następujący sposób. Przykład jest oparty na systemie z dwiema
kartami dzwiękowymi. Karta o indeksie 0 jest oznaczona jako pierwsza karta. Aby
zmienić jej parametry, należy zaktualizować pliki konfiguracyjne modułu.
Listing 3.5: Ustalanie parametrów modułu |
# echo "option snd-ice1724 index=0" >> /etc/modules.d/alsa
# echo "option snd-ymfpci index=1" >> /etc/modules.d/alsa
# update-modules
|
Powyższy przykład prezentuje najlepszą sytuację. Lecz nie wszystkie moduły
wspierają parametry takie jak "index". Dla tych modułów należy wymusić poprawną
kolejność ich ładowania. Po pierwsze, konieczne jest powstrzymanie udev od
automatycznego ładowania modułów przez wpisanie ich na czarną listę. Wpisując,
należy być pewnym nazwy ładowanego modułu. Dla urządzeń PCI, trzeba użyć nazwy
modułu uzyskanego z wyjścia pcimodules, dostępnego w pakiecie
pciutils. Poniższy przykład opisuje użycie modułu DVB
Listing 3.6: Wpisywanie modułów na czarną listę |
# echo "blacklist b2c2-flexcop-pci" >> /etc/modprobe.d/dvb
# echo "blacklist budget" >> /etc/modprobe.d/dvb
# update-modules
|
Następnie należy załadować moduły w poprawnej kolejności. Trzeba dodać je do
/etc/modules.autoload.d/kernel-2.6 w dokładnie takiej kolejności
w jakiej mają zostać załadowane.
Listing 3.7: Ładowanie modułów w poprawnej kolejności |
# echo "budget" >> /etc/modules.autoload.d/kernel-2.6
# echo "b2c2-flexcop-pci" >> /etc/modules.autoload.d/kernel-2.6
|
Inne problemy
Jeśli węzły urządzeń nie są tworzone podczas ładowania modułu z
/etc/modules.autoload.d/kernel-2.6, ale są tworzone jeśli
załadujemy moduł ręcznie, należy spróbować aktualizacji pakietu baselayout do
wersji sys-apps/baselayout-1.8.12 lub nowszej.
Wsparcie dla urządzeń bufora ramki (/dev/fb/*) jest w jądrze
2.6.6-rc2 i powyżej.
W jądrach starszych od 2.6.4 należy włączyć wsparcie dla systemu plików
/dev/pts.
Listing 3.8: Włączanie systemu plików /dev/pts |
File systems --->
Pseudo filesystems --->
[*] /dev/pts file system for Unix98 PTYs
|
4.
Zasoby i podziękowania
Wykład o udev na Linux Symposium (Ottawa, Ontario Canada - 2003) prowadzony
przez Greg Kroah-Hartman (IBM Corporation) dostarczył solidnego zrozumienia
systemu udev.
Decibel's UDEV Primer jest wyczerpującym źródłem o udev i Gentoo.
Writing udev rules
stworzony przez dewelopera Gentoo Daniela Drake jest doskonałym przykładem
dostosowywania systemu udev do własnych potrzeb.
Materiał udostępniany na podstawie licencji Creative Commons -
Attribution / Share Alike.
|