MODUŁY

 Zmiany związane z kompilacją

W porównaniu z poprzednią wersją zmieniono przebieg procesu kompilacji modułu. W jądrze 2.4 do kompilacji wystarczyły pliki nagłówkowe jądra, obecnie oprócz nagłówków potrzebne jest również skonfigurowane źródłowe drzewo katalogowe jądra. Struktura pliku makefile do tworzenia modułu uległa w związku z tym zmianie. Szczegółowe informacje dotyczące tych zmian można znaleźć np w artykule: http://lwn.net/Articles/21823/

W związku z powyższymi zmianami nie potrzebna staje się w kodzie modułu defincja:

           #define MODULE

Dodatkowo zmieniono rozszerzenia skompilowanych modułów z .o na .ko.

 

Funkcje inicjujące i kończące

W kodzie modułu należy jawne podać funkcję inicjującą i fukcję wykonywaną przy odładowywaniu modułu za pomocą :

    module_init(nazwa_funkcji_inicjującej)

    module_exit(nazwa_funkcji_zwalniającej)

Próba użycia dopuszczalnych w jądrze 2.4 makr int_module oraz cleanup_module zakończy się warning'iem przy wgrywaniu.

 

Eksportowanie symboli, a makro MODULE_LICENSE

Domyślnie w jądrze 2.6 nie są eksportowane żadne identyfikatory, zatem używanie EXPORT_NO_SYMBOLS jest redundantne.  

Warning'iem również kończy się nie umieszczenie w kodzie modułu opisu jego licencji za pomocą MODULE_LICENSE(„Licencja”). Makro to było również dostępne w  jądrach 2.4, ale tam miało charakter czysto informacyjny, a tu rodzaj licencji niesie pewne konsekwencje. Z MODULE_LICENSE związane jest bowiem makro EXPORT_SYMBOL_GPL(...) które pozwala udosępniać identyfikatory tylko modułom na licencji GPL – jest to krok w celu umocniania rodziny open-sorce’owej. Wprowadzenie tego rozwiązania było sprawą dyskusyjną.

 

Parametry modułów

Używane w jądrze 2.4 MODULE_PARAM(...) już nie istnieje. Aby używać parametrów w wersji 2.6 po pierwsze należy dołączyć plik nagłówkowy:

        #include <linux/moduleparam.h>

Teraz już w kodzie modułu możemy definiować parametry na kilka sposobów. Standardowo będzie to makro:

                module_param(name, type, perm);

gdzie name to oczywiście nazwa parametru (a zarazem i zmiennej); type to typ parametru: byte, short, ushort, int, uint, long, ulong, charp, bool lub invbool; perm natomiast jest w obecnej implementacji jądra argumentem roboczym (ma być związany z sysfs) więc bezpiecznie jest ustawić go na 0.

Jeżeli zewnętrzna nazwa naszego parametru ma być inna niż nazwa zmiennej wewnątrz kodu to możemy użyć:

        module_param_named(name, value, type, perm);

gdzie name to nazwa zewnętrzna; value to nazwa naszej zmiennej; a type i perm są analogiczne jak powyżej.

Oprócz tego do dyspozycji mamy dwie możliwości deklaracji:

        module_param_string(name, string, len, perm);

gdy chcemy parametr który jest stringiem mieć jako tablicę, a nie jako *char; len oznacza długość napisu - standardowo powinno to być sizeof(string).

        module_param_array(name, typ, num, perm);

gdy chcemy parametr który jest tablicą typu type – w momencie ładowania wartości powinny być podane po przecinkach; num to zewnętrzny parametr ustawiany na liczbę podanych do tablicy wartości. 

 

Aliasy

W jądrze 2.4 aliasy mogły być definiowna w /etc/modules.conf. W wersji 2.6 można dodatkowo tworzyć aliasy bezpośrednio w kodzie poprzez makro:

        MODULE_ALIAS("alias-name");

 

 Koncepcja licznika odwołań

W jądrze 2.6 zmienił się sposób zarządzania odwołaniami do modułów. W jądrze 2.4 zarządzanie licznikiem odbywało się wewnątrz kodu modułu poprzez makra MOD_INC_USE_COUNT, MOD_DEC_USE_COUNT. Ewentualnie w określonych przypadkach mogło odbywać się automatycznie poprzez ustawienie pola owner dla zasobów na THIS_MODULE. Podejście to często powodowało kłopoty i mogło się zdarzyć iż następowało odwołanie do właśnie odładowywanago modułu.

Jądro 2.6 przynosi nowe rozwiązanie, nieco odciążające autorów modułów. Otóż modyfikacja licznika odwołań może odbywać się tylko z zewnątrz kodu modułu poprzez funkcję:

        int try_module_get(&module);

która zgłasza żądanie na moduł (w przypadku niemożności dostępu zwraca 0) zwiększając przy okazji licznik odwołań. Zwolnienie modułu i tym samym zmniejszenie licznika odwołań odbywa się poprzez:

          module_put(&module)

Wyjątkiem od reguły może być wywołanie w uzasadnionych przypadkach try_module_get(...) od siebie samego.

Podejście to niestety nie jest pozbawione wad – może się np. zdarzyć iż z powodu jakiegoś niestandardowego błędu proces wykonujący
try_module_get nie wykona module_put co zafałszuje licznik odwołań i może sprawić że nigdy nie osiągnie on zera. W obronie przed takimi sytuacjami powstała opcja:

        CONFIG_MODULE_FORCE_UNLOAD

Która ustawiona w konfiguracji zezwala jądru na odładowywanie modułu nawet w przypadku niewyzerowanego licznika odwołań. Opcja ta powinna być stosowana z należytą ostrożnością.

autor: Paweł Kowalski

Źródła:

http://www.linuxdevcenter.com/pub/a/linux/2002/12/12/vanishing.html

http://www.linux.org.uk/~davej/docs/post-halloween-2.6.txt

http://www.linux-mag.com/2004-06/compile_01.html

www.bashprofile.net/IMG/linux26.pdf

http://lwn.net/Articles/21817/

http://lwn.net/Articles/22197/

http://vmlinux.org/jocke/linux/external-modules-2.6.shtml  

http://lwn.net/Articles/21823/