W jaki sposób OSX uruchamia 64-bitowe pliki binarne podczas działania na 32-bitowym jądrze?

6

Niedawno zorientowałem się, że Mac OS X faktycznie może uruchamiać aplikacje 64-bitowe (x64), nawet jeśli jądro x86 jest załadowane. To było dla mnie szokujące po raz pierwszy.

Ale potem zdałem sobie sprawę, że to naprawdę dziwne, jeśli system działa pod procesorem kompatybilnym z x64, nie może uruchamiać aplikacji x64, bez względu na to, jakie jądro zarządza procesami. Czy to naprawdę takie trudne? Wystarczy załadować tę cholerną aplikację do pamięci i ustawić wskaźnik działania procesora na pierwszy bajt, to proste!

Jedyną barierą, jaką można to zrobić, jak mogłem sobie wyobrazić, są jakieś „nagłówki wykonywalne”. Niestety nie czuję się dobrze z architekturą Windows i strukturą binarną, dlatego potrzebuję więcej wyjaśnień tutaj.

De facto UNIXopodobnych binarny standardowy nagłówek ELF ma to brat ELF64, który (jako dokument tutaj opisano) nie ma wiele różnic z Elf32, ale mimo jądra 32-bitowe nie są w stanie uruchomić kod x64. Tak, ten program jest prawdopodobnie powiązany z bibliotekami x64 i pozwala sobie wyobrazić, że właśnie skopiowaliśmy i wkleiliśmy je bezpośrednio do folderu / usr / lib64. Ale jestem pewien, że to nie pomaga, dlaczego?

I wreszcie, co jest takiego specjalnego w jądrze Mac OS X, aby nie martwiło się o zestaw instrukcji programu? Czy Mac OS X ma jakiś uniwersalny i odpowiedni dla nagłówka plików wykonywalnych obu jąder, więc może po prostu załadować aplikację do pamięci i powiedzieć procesorowi „wykonać od razu, nie mam nic przeciwko temu”.

PS: Naprawdę zastanawiałem się, gdzie umieścić to pytanie: na stackoverflow.com lub superuser.com, i postanowiłem umieścić tutaj, ponieważ temat jest prawdopodobnie bardziej specyficzny dla systemu operacyjnego.

pechenie
źródło
Co sprawiło, że pomyślałeś, że OSX będzie uruchamiał 64-bitowy plik binarny podczas działania na 32-bitowym jądrze Darwina? Co widziałeś?
James T Snell
Ponieważ byłem prawie pewien, że korzystam z jądra x64, więc jedyne zainstalowane oprogramowanie to x64 i system operacyjny działa doskonale. Ale jakiś czas temu wpisałem „uname -a” w moim terminalu i byłem zaskoczony. Wikipedia również to potwierdza - en.wikipedia.org/wiki/X86-64#Mac_OS_X
pechenie
Wikipedia i oboje możecie się mylić. Uruchamianie 64-bitowego systemu operacyjnego nie oznacza, że ​​wszystkie pliki binarne są 32-bitowe. Oznacza to, że twoje jądro i architektura sprzętowa mogą obsługiwać 64-bitowe pliki binarne. Co powraca twoje uname -a ?
James T Snell
Nie rozumiem też tytułu twojego pytania. Czy możesz to powtórzyć?
James T Snell
To nie pomyłka, możesz spróbować, jeśli możesz. Używałem jądra x86, a nie x64, więc nadal mogłem uruchamiać oprogramowanie x64. Już przeszedłem na architekturę x64_86, ale dane wyjściowe uname -ajądra pod x86 prawdopodobnie wyglądały mniej więcej tak:Darwin MacMini.local 11.1.0 Darwin Kernel Version 11.1.0: Tue Jul 26 16:07:11 PDT 2011; root:xnu-1699.22.81~1/RELEASE_i386 i386
pechenie 27.09.11

Odpowiedzi:

5

Prawdziwe pytanie brzmi: dlaczego niektóre inne systemy operacyjne nie mogą uruchamiać 64-bitowych plików binarnych w 32-bitowym jądrze. Nie ma podstawowego powodu, dla którego nie byłoby to możliwe. Podstawowa architektura procesorów obsługuje zarówno 64-bitowy zestaw instrukcji (amd64 aka x86-64), jak i 32-bitowy zestaw instrukcji (i386), i nie ma ograniczeń co do ich używania (w szczególności nie ma „Tryb 64-bitowy”, który jest niezależny od „trybu 32-bitowego”; istnieje jeden długi tryb , który pozwala na instrukcje zarówno z i386, jak i „natywnego” zestawu amd64).

Uruchamianie 64-bitowych aplikacji w 32-bitowym jądrze wymaga nieco więcej pracy wewnątrz jądra, ponieważ musi zarządzać 64-bitowymi wskaźnikami do przestrzeni użytkownika wraz z 32-bitowymi wskaźnikami do przestrzeni jądra. Większość, jeśli nie wszystkie wskaźniki przekazywane w jądrze są albo znane z przestrzeni jądra, albo z przestrzeni użytkownika, więc nie ma problemu, jeśli mają inny rozmiar. Główną trudnością jest rezygnacja z możliwości posiadania uniwersalnego typu wskaźnika, który ma osobne zakresy wartości dla pamięci procesu, pamięci jądra i pamięci używanej przez różne elementy sprzętu (w tym RAM), ale nie jest to możliwe w najnowszych 32-bitowych jądrach w każdym razie na sprzęcie klasy PC (jeśli masz 4 GB lub więcej pamięci RAM lub chcesz zmapować 2 GB pamięci RAM plus 2 GB przestrzeni procesowej plus pamięć jądra i więcej, musisz mieć możliwość mapowania ponad 32 bitów)

Zgodnie z cytowanym artykułem z Wikipedii OSX miał możliwość uruchamiania procesów amd64 na procesorach amd64, zanim miał 64-bitowe jądro. Solaris również obojętnie miesza pliki wykonywalne i386 i amd64 na procesorach amd64, niezależnie od tego, czy jądro jest 32-bitowe czy 64-bitowe (oba są dostępne).

Inne systemy operacyjne mogą uruchamiać procesy i386 na (64-bitowym) jądrze amd64, ale nie procesy amd64 na 32-bitowym jądrze, na przykład Linux, FreeBSD, NetBSD i Windows. Jeszcze inne systemy operacyjne traktują amd64 i i386 jako zupełnie różne architektury, na przykład OpenBSD.

Gilles
źródło
Wskaźniki AIUI nie stanowią problemu w OS X, ponieważ i tak nie są przekazywane między jądrem a przestrzenią użytkownika. Nawet przy 32-bitowym procesie działającym pod 32-bitowym jądrem proces ten może mieć do 4 GB zdefiniowanej przestrzeni pamięci wirtualnej, a jądro może mieć do 4 GB, a te dwa nie pokrywają się. Jeśli przekażesz wskaźnik z przestrzeni użytkownika do jądra, byłoby to bez znaczenia, ponieważ pod tym adresem w przestrzeni jądra jest coś zupełnie innego.
Gordon Davisson
Jeśli spojrzysz na kod źródłowy, zobaczysz, jak to się robi. W 32-bitowym systemie OS X jądro nie jest mapowane do przestrzeni adresowej użytkownika, więc oba mają całkowicie oddzielne 32-bitowe przestrzenie adresowe. Wszelkie przekazywane dane są kopiowane lub ponownie mapowane. Karą jest brak pamięci podręcznej TLB.
Russbishop
pytanie brzmi: w jaki sposób procesor może przechowywać kontekst, gdy tryb 32-bitowy nie może uzyskać dostępu do najwyższych 64-bitowych, a także 8 wysokich rejestrów?
phuclv
1
@ LưuVĩnhPhúc Potrzebujesz trochę 64-bitowego kodu, aby zapisać i przywrócić rejestry. O ile wiem, jest to możliwe na x86-64 (i tak właśnie robi to np. Solaris). Rzeczywiście byłby to problem na ramieniu, w którym nie można mieszać instrukcji 64-bitowych i 32-bitowych bez zmiany uprawnień.
Gilles
4

Nie jestem wystarczająco zaznajomiony z architekturą x86_64, aby podać szczegóły, ale zasadniczo dzieje się tak, że procesor jest przełączany między trybem 64-bitowym a trybem zgodności (32-bitowym) w ramach przełączania kontekstu między jądrem a przestrzenią użytkownika program. Jest to prawie to samo, co można zrobić, aby uruchomić 32-bitowy program pod 64-bitowym jądrem, po prostu odwrotnie.

BTW, OS X nie używa formatu binarnego ELF, używa plików binarnych Mach-O . Format Mach-O pozwala na wielowątkowe („uniwersalne”) pliki binarne, więc programy (i w tym przypadku jądro) mogą być dostarczane zarówno w wersji 32-, jak i 64-bitowej (oraz PPC i PPC64 i ...), a system operacyjny może wybierz, która wersja ma zostać załadowana (a więc i w jakim trybie ją uruchomić) w czasie ładowania. Możesz użyć filepolecenia w pliku binarnym, aby zobaczyć, w jakim formacie (-ach) jest on. Na przykład, oto aplikacja Chess dostarczana z systemem OS X 10.5:

$ file Applications/Chess.app/Contents/MacOS/Chess 
Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 4 architectures
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc): Mach-O executable ppc
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc64):   Mach-O 64-bit executable ppc64
Applications/Chess.app/Contents/MacOS/Chess (for architecture i386):    Mach-O executable i386
Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64):  Mach-O 64-bit executable x86_64

I uwaga dla tych, którzy wątpią, że jest to możliwe: OS X obsługiwał 64-bitowe programy od wersji 10.4 (z ograniczoną obsługą API), ale nie zawierał 64-bitowego jądra aż do wersji 10.6 (a nawet wtedy jądro działało domyślnie w trybie 32-bitowym w większości modeli). Aby uzyskać szczegółowe informacje, zobacz 64-bitowy przewodnik Apple . Wysyłam to z MacBooka Pro z systemem 10.6 z 32-bitowym jądrem (64-bit nie jest obsługiwany w tym konkretnym modelu), ale według Monitora aktywności jedynym procesem, który nie działa w trybie 64-bitowym, jest kernel_task.

Gordon Davisson
źródło
4

Komputery Mac obsługują uruchamianie 64-bitowych aplikacji na 32-bitowym jądrze, ponieważ plan wieloetapowy to dokładnie zrobić:

  1. Aplikacje na komputery Mac są dostarczane jako „duże pliki binarne” w „pakietach”, które pozwalają wszystkim czterem kombinacjom 64/32-bitowych i Intel / PPC być częścią jednej instalacji, która może być tak prosta jak przeciąganie i upuszczanie. System operacyjny uruchamia odpowiedni.
  2. Komputery Mac używają PAE, aby uzyskać dostęp do ponad 4 GB pamięci RAM podczas działania jądra 32-bitowego. Windows nie zezwala na PAE w wersjach innych niż Serwer z powodu problemów ze zgodnością ze sterownikami, których mają o wiele więcej, w tym innych.
  3. Tiger dodaje 64-bitowy interfejs ABI (Application Binary Interface) w celu uruchomienia 64-bitowego kodu na 32-bitowym jądrze oraz 64-bitową wersję interfejsów API niskiego poziomu (interfejs programowania aplikacji) dla „konsoli” (nie GUI).
  4. Leopard dodaje 64-bitową wersję Cocoa dla aplikacji GUI (ale nie 64-bitową wersję Carbon).
  5. Snow Leopard dodaje 64-bitowe jądro, które jest domyślne tylko w niektórych wysokiej klasy modelach.
  6. Lion wymaga 64-bitowego procesora, ale nadal zawiera 32-bitowe jądro. Na przykład stary komputer Mac z 64-bitowym procesorem, ale GPU, który ma tylko 32-bitowe sterowniki, musiałby uruchomić jądro 32-bitowe.

Tak więc OS X obsługiwał 64-bitowe aplikacje tak szybko, jak to możliwe, i nadal uruchamiał jądro 32-bitowe tak długo, jak to możliwe, ze względu na sytuację sterownika. (Ziarnistość jądra staje się czynnikiem tylko podczas próby zarządzania ogromnymi ilościami pamięci RAM - tabele stron również zajmują pamięć - i przejście na 64-bitowe jądro oferuje pewne korzyści związane z wydajnością.) Ale Apple z pewnością nie wstydzi się upuszczać rzeczy.

Prawdziwe pytanie brzmi zatem, dlaczego systemy Windows i Linux nie zrobiły tego samego. W przypadku systemu Windows weź pod uwagę, że ich pierwsza próba Win64 była z Itanium, co było zupełnie inne. Ale ostateczna odpowiedź może sprowadzać się do tego, co zwykle ma przez kilka ostatnich dziesięcioleci: kompatybilności z wieloma programami stron trzecich, które nie działały właściwie :

64-bitowa implementacja OS X różni się znacząco od Windows, który traktuje swoje wersje 32-bitowe i 64-bitowe jako dwa różne systemy operacyjne przechowywane na różnych nośnikach instalacyjnych. Odbywa się to głównie w celu zachowania zgodności systemu Windows ze starszymi aplikacjami - przeniesienie lub zmiana nazwy rzeczy takich jak folder System32 spowodowałaby uszkodzenie programów, które się tam spodziewały - i w rezultacie oba są rozdzielone do tego stopnia, że ​​nie ma nawet aktualizacji ścieżka między 32-bitowym systemem Windows a 64-bitowym systemem Windows. Z tego powodu oraz ponieważ aplikacje i sterowniki systemu Windows mają zwykle różne wersje 32-bitowe i 64-bitowe, przejście systemu Windows na wersję 64-bitową było nieco mocniejsze i bardziej widoczne dla użytkownika.

Istnieje wiele informacji w tle na temat przejścia 64-bitowego zarówno po stronie Maca, jak i Windowsa . (Te linki są na końcu każdej serii artykułów; pamiętaj, aby wrócić na początek każdego z nich).

Nie wiem, jaka była ta historia z Linuksem, ale wyobraź sobie, że Linus miał na jej temat mocne zdanie.

Rozpoznać
źródło
1
Od strony Linuksa: jądro obsługiwało zarówno architekturę 32-bitową, jak i 64-bitową na długo przed istnieniem amd64. Uruchamianie 64-bitowych procesów w 32-bitowym jądrze wymagałoby ponownej inżynierii, przynajmniej w zależnych od architektury częściach kodu. Wystarczająco dużo, aby uruchomić pliki binarne i386 na jądrze amd64, ale nie na (bardziej skomplikowanej) drugiej stronie, ponieważ nie ma tak naprawdę motywującego przypadku użycia dla tego kierunku (jeśli chcesz uruchomić procesy 64-bitowe, nie ma powodu, aby nie uruchamiać 64-bitowe jądro).
Gilles
Bardzo dziękuję za wyjaśnienie, nie mogę jeszcze głosować za głosem (niewystarczająca reputacja) i nie mogę również zaakceptować dwóch odpowiedzi, ale zarówno ty, jak i Gilles, wyjaśniłeś mi to trochę!
pechenie
0

Zdałem sobie sprawę, że to naprawdę dziwne, jeśli system działa pod procesorem kompatybilnym z x64, nie może uruchamiać aplikacji x64, bez względu na to, jakie jądro zarządza procesami. Czy to naprawdę takie trudne? Wystarczy załadować tę cholerną aplikację do pamięci i ustawić wskaźnik działania procesora na pierwszy bajt, to proste!

Brakuje ważnej części. Aplikacje wykonują wywołania API do funkcji i usług udostępnianych przez system operacyjny. Jeśli aplikacja 64-bitowa wysyła wskaźnik 64-bitowy do 32-bitowego systemu operacyjnego, wszystko powinno się wysadzić.

Podejrzewam, że aby wszystko działało akceptowalnie w obu przypadkach, system operacyjny musi przeciążać funkcję i zapewniać wersję 64-bitową i 32-bitową każdej funkcji. Dla każdego jądra funkcja „off” (funkcja 64-bitowa w jądrach 32-bitowych, funkcja 32-bitowa w jądrach 64-bitowych) będzie tylko kodem pośredniczącym, który tłumaczy połączenie jako bezpieczne dla 32-bitów, a następnie ponownie wywołuje funkcję natywną.

Joel Coehoorn
źródło