Możliwość uruchamiania binariów linuxowych na BSD (compatibility layer)


FreeBSD dostarcza zgodnosc binariow z roznymi systemami z rodziny UNIX, wlacznie z linuxem.

Wiele firm dostarcza oprogramowanie na platforme linux poniewaz jest to najpopularniejszy z systemow unixopodobnych, zaniedbujac przy tym systemy z rodziny BSD. Tu wlasnie przydaje sie "binary compatility". W skrocie umozliwia to uruchomienie ok. 90% aplikacji napisanych dla linuxa bez zadnych modyfikacji kodu zrodlowego min. StarOffice, Netscape, Adobe Acrobat, Real Player, VMware, Oracle, WordPerfect, Doom, Quake. Interesujace jest to, ze w niektorych przypadkach programy dzialaja lepiej i szybciej na FreeBSD niz na Linuxie.

Sa specyficzne dla Linuxa funkcjonalnosci, ktore nie sa obslugiwane pod FreeBSD. Binaria linuxowe nie beda chodzic na FreeBSD jesli uzywaja systemu plikow /proc lub specyficznych wywolan i386, tj. wlaczanie virtualnego trybu 8086.



Instalacja i uruchomienie

1) Zgodnosc binarna nie jest domyslnie wlaczona na FreeBSD. Najprostsza droga do wlaczenia jej jest zaladowanie obiektu KLD ("Kernel LoaDable object") "linux". Mozna to zrobic wpisuja komende jako root:
# kldload linux

Jesli chcemy aby zgodnosc binarna z linuxem byla zawsze wlaczona to powinnismy dodac ponizsza linijke do pliku /etc/rc.conf:

linux_enable="YES"

Komenda kldstat(8) umozliwia nam sprawdzenie czy modul KLD jest zaladowany:

% kldstat
Id Refs Address Size Name
1 2 0xc0100000 16bdb8 kernel
7 1 0xc24db000 d000 linux.ko

Jesli z jakiegos powodu nie udaje sie zaladowac modulu, mozna statycznie podlaczyc zgodnosc binariow z linuxem do jadra dodajac options COMPAT_LINUX do pliku konfiguracyjnego jadra i skompilowac i zainstalowac jadro.



2) Sam modul nie wystarczy, aby mozna bylo uruchamiac programy linuxowe. Modul eksportuje symbole specyficzne dla linuxa oraz dostarcza linuxowe api wywolan systemowych. Jak wiemy wiekszosc programow linkuje dynamicznie linuxowe biblioteki. W dystrybucji FreeBSD i tego nie zabraklo. Instalujac pakiet "Linux Runtime Libraries" zapewniamy programom dostep do powszechniejszych bibliotek linuxowych tj. libc, glibc itd.

Aby zainstalowac powyzszy pakiet nalezy skorzystac z systemu portow:

# cd /usr/ports/emulators/linux_base-fc4
# make install distclean
3) Jesli z aplikacja nadal narzeka na brak niektorych bibliotek nalezy je dokopiowac z systemu linux. Aby sie dowiedziec jakich bibliotek potrzebyjemy musimy wykonac nastepujaca komende na koncie roota:
% ldd linuxdoom
libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0
libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0
libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29
Aby program sie uruchomil powinnismy umiescic biblioteki z prawej kolumny w katalogu /compat/linux, wraz z linkami symbolicznymi z pierwszej kolumny wskazujacymi na nie. To znaczy ze katalog /compat/linux powinien zawierac:
/compat/linux/usr/X11/lib/libXt.so.3.1.0
/compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0
/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

4) Binaria ELF niekiedy wymagaja dodatkowego dzialania: "brandingu". Jesli proba uruchomienia pliku konczy sie komunikatem:

% ./my-linux-elf-binary
ELF binary type not known
Abort

znaczy to ze FreeBSD nie moze rozpoznac typu binariow ELF. Aby pomoc systemowi w odroznieniu linuxowego ELFa od ELFa FreeBSD nalezy uzyc komendy:

% brandelf -t Linux my-linux-elf-binary

Poniewaz FreeBSD moze odroznic jeden typ binariow od drugiego, moze zmusic binaria linuxowe do uruchamiania sie w nieco innym srodowisku z innymi bibliotekami.


W przyszlosci reczne wprowadzanie typu bedzie zbedny poniewaz GNU toolchain teraz zapisuje informacje o typie binariow w pliku ELF.



Jak to dziala?

FreeBSD posiada abstrakcyjna warstwe za wywolaniesm systemowym execve(2). FreeBSD w tej warstwie przetrzymuje liste loaderow odpowiedzialnych za rozne formaty plikow wykonywalnych. System przechodzi liste loaderow przekazujac kazdemu pierwsze bajty pliku do wykonania. Jesli ktorys stwierdzi, ze to jest jego plik wykonuje go. Jest jeden loader odpowiedzialny za wszystkie pliki ELF (nie ma roznicy czy to sa binaria Solaris, Linux, FreeBSD czy inne) i na tym etapie nie ma rozroznienia na brandy.

To Loader plikow ELF, a nie system sprawdza typ (brand) plikow, poprzez przeczytanie bajtow z sekcji comments pliku ELF. Jesli Loader rozpozna typ jako linuxowe binarium wtedy podmienia wskazniki w strukturze proc. Od teraz wskaznik wskazuje na inne wywolania systemowe (te eksportowane przez modul linux), proces jest oznaczony tak, aby lapanie sygnalow i inne mniejsze rzeczy byly obslugiwane przez kod z modulu linux. Specjalne traktowanie sprawia dodatkowo, ze poczatkowo wymagane biblioteki beda szukane w katalogu /compat/linux/original-path, dopiero gdy to zakonczy sie porazka przeszukiwana jest wlasciwa sciezka /original-path. To oznacza, ze gdy system nie znajdze biblioteki linuxowej moze uzyc w zastepstwie biblioteki FreeBSD. 


POKAZAC CO ZWROCI uname W KATALOGU /compat/linux/bin

Wiekszosc wywolan systemowych Linuxa i FreeBSD sie pokrywa. Tam gdzie jest jakas roznica sa stosowane funkcje klejace, czyli takie ktore implementuja api np. Linuxa za pomoca natywnych wywolan systemowych FreeBSD.

Mechanizm "Compatibility Layer" czesto jest mylnie nazywany emulatorem. Nie ma tam nic co mogloby wskazywac na takie porownianie. Mozna rzec, ze jest to jadro Linuxa w jadrze FreeBSD. Spadek wydajnosci jest niewielki, a niekiedy zdarza sie nawet jej przyrost. W emulatorze byloby to niemozliwe.