2008-10-19 16 views
39

Użyłem C# w Visual Studio z .NET, i trochę grałem z Mono na openSUSE Linux, ale tak naprawdę nie rozumiem jak to działa.Jak działa Mono?

Jeśli napiszę aplikację w systemie Windows na platformie .NET, jak to się dzieje w przypadku Mono? Nie mogę po prostu wykonać pliku Windows .exe w systemie Linux bez Wine, więc nie pomaga mi to w uruchamianiu aplikacji opracowanych w systemie Windows.

Czy celem jest posiadanie odpowiednika biblioteki .NET na Linuksie (i innych), aby ułatwić tworzenie wielu platform? Na przykład, jeśli byłem firmą i chciałem dotrzeć do klientów Linuksa, ale naprawdę chciałem korzystać z .NET, to Mono powinien być moim wyborem? Czy jest jeszcze coś, czego mi brakuje?

Odpowiedz

20

Plik EXE zawiera wiele "części". Uproszczony, kod .net (= MSIL) to tylko część EXE, aw "EXE" znajduje się również "prawdziwa" natywna część Windows, która służy jako program uruchamiający dla .net Framework, który następnie wykonuje MSIL.

Mono po prostu weźmie MSIL i uruchomi go, ignorując natywne rzeczy z Windows Launchera.

Ponownie, jest to uproszczony przegląd.

Edit: boję moje zrozumienie głębokich głębokich szczegółów nie jest wystarczająco dobre dla bardzo dużo szczegółów (wiem z grubsza co to PE Header, ale naprawdę nie dane), ale uważam, że te linki pomocne:

NET Assembly Structure – Part II

.NET Foundations - .NET assembly structure

+0

masz szansę na nieco bardziej szczegółową wersję? :) – DavidG

+0

Obawiam się, że moje zrozumienie szczegółów głębokiego depp nie jest do tego wystarczające (wiem z grubsza, czym jest nagłówek PE, ale nie tak naprawdę szczegóły), ale uważam, że te linki są pomocne: http://is.gd/ 4n4i http://is.gd/4n4n –

+4

W pliku EXE nie ma "prawdziwej" natywnej części systemu Windows. Nagłówek to tylko opis. Może wskazywać na punkt wejścia w EXE lub DLL, ale jest to albo wykonywalne przez środowisko hosta, albo nie. Rzeczywisty "launcher" jest zewnętrzny do pliku wykonywalnego i jest natywny dla systemu Windows lub część CLR (dla .NET i Mono). – Justin

10

Można faktycznie uruchomić plik .NET .exe z Mono w systemie Linux. To nie wymaga Wine. W rzeczywistości Mono kompiluje programy do plików .exe, które mogą być uruchamiane z Mono w systemie Linux lub jako plik wykonywalny w systemie Windows.

+1

Prawidłowe. Mono implementuje CLR (.NET), podczas gdy Wine próbuje wdrożyć pełne natywne środowisko Windows (Win32 API i funkcje jądra). – Justin

2

Mono jest implementacja open-source z Microsoftu .NET CLR (Common Language Runtime). Jest to część programów .NET, które nie są natywne, lecz w języku CIL (Common Intermediate Language), języku pośredniczącym w języku i maszynie. Środowisko wykonawcze przyjmuje ten pośredni kod i tłumaczy go na kod maszynowy.

W bieżącym stanie Mono można korzystać z programów .NET, które korzystają z głównych składników .NET (mscorlib.dll) i uruchamiać je wszędzie tam, gdzie działa Mono, a nie tylko Windows.

2

Ale jak już wspomniano, Mono jest open source i nie można po prostu polegać na tym, że będzie to pełna implementacja .NET, ma pewne kontrole, które nie działają, musisz być także ostrożny z P/Invokes, że Twoja aplikacja będzie używać, ponieważ np. twoja aplikacja będzie komunikować się z MCI (Multimedia Controller Interface) pod win32. Ale używałem także mono-piszących GTK # Applications, ale używałem też moich aplikacji Windows, które pracowały bez żadnej rekompilacji, jak wspomniano powyżej, o których wspominali nasi programiści, czyli mono jest alternatywą open source dla .NET firmy Microsoft, i domyślnie, jeśli budujesz albo WinForms albo Gtk # aplikacje mono skompiluje i utworzy zbiór .exe dla każdego pliku, i oczywiście, jeśli chcesz, utworzy bibliotekę Dynamic Link (DLL), prawie tak, jak jest to zrobione w .NET. Tylko dla sugestii spróbuj napisać Gtk # (z MonoDevelop IDE, który ma wbudowanego GUI-projektanta o nazwie stetic). I oczywiście mono może być świetnym zamiennikiem dla usług internetowych, które można utworzyć na platformie .NET i można je hostować na serwerze Apache (ponieważ hosting Linux jest obecnie tańszy niż system Windows), usługi sieciowe i inne aplikacje asp.net będą działać apache z modułem mod_mono, który musi być dołączony do Apache.

Nieco poza tematem, ale chciałem wam tylko rzucić okiem na moje doświadczenia.

0

Aby uzyskać odpowiedź od Michaela, uważam, że będziesz musiał dokonać rekompilacji w Mono, aby aplikacja działała w środowisku wykonawczym Mono. Mogą istnieć wyjątki. Grałem tylko z Mono tylko trochę i zawsze ponownie skompilowałem źródło. Nigdy nie próbowałem uruchomić aplikacji .NET bezpośrednio w Mono.

Ponadto Mono 1.9 ma być w pełni zgodny z technologią .NET 2.0. Mono Olive i Moonlight mają dodawać funkcje .NET 3.0 (mniej WPF) i Silverlight.

+1

Tylko notatkę. Z pewnością nie trzeba przekompilowywać aplikacji .NET, aby działała na Mono. – Justin

1

Możesz również spojrzeć na MoMA (jeśli Twoim celem jest przeniesienie aplikacji z Win na Lin).

Mono Migration Analyzer (MoMA) narzędzie pomaga zidentyfikować problemy można mieć przy przenoszeniu aplikacji .Net mono. Pomaga to zidentyfikować obszary specyficzne dla połączeń platformowych (P/Invoke) i , które nie są jeszcze obsługiwane przez projekt Mono w wersji .

MoMA

Oto webapp który porównuje rodzaje plc już wdrożone przez Mono i .NET Framework 3,5

http://mono.ximian.com/class-status/2.0-vs-3.5/index.html

106

Jest to stary pytanie (z już wybraną odpowiedź), ale nie sądzę, aby na to pytanie dobrze odpowiedziano.

Po pierwsze, trochę w tle ...

Jak działa .NET?

Tradycyjny plik .EXE systemu Windows jest plikiem binarnym, który reprezentuje serię instrukcji języka maszynowego, które komputer rozumie i nawiązuje połączenia z interfejsem Win32 API, które są częściami systemu Windows oferującymi usługi, z których mogą korzystać aplikacje. Użyty język komputera jest bardzo specyficzny dla twojego komputera, a wywołania Win32 sprawiają, że plik wykonywalny jest bardzo zależny od systemu Windows. Plik wykonywalny .NET nie jest taki.

Należy pamiętać, że plik wykonywalny .NET (plik EXE) w rzeczywistości nie jest natywną aplikacją systemu Windows. Sam system Windows nie wie, jak uruchomić kod w pliku wykonywalnym .NET. Twój komputer też tego nie rozumie.

Podobnie jak Java, aplikacja .NET składa się z instrukcji w języku zwanym CIL (Common Intermediate Language), który można uznać za język maszynowy dla wyidealizowanego komputera, który tak naprawdę nie istnieje. W .NET implementacja tego wyidealizowanego komputera nosi nazwę Common Language Runtime (CLR). Odpowiednik w świecie Java nazywa się wirtualną maszyną Java (JVM). W Javie odpowiednik CIL nazywa się bajtowym kodem Java. CIL jest czasem nazywany MSIL (Microsoft Intermediate Language).

CIL jest przeznaczony do pracy na CLR (wyidealizowana maszyna), ale jest poza tym niezależny od platformy, co oznacza, że ​​CIL nie dba o to, jaki masz komputer lub jaki system operacyjny używasz.

Tak jak potrzebujesz natywnej wersji Java JVM na każdej platformie, na której chcesz uruchomić Javę, potrzebujesz natywnej wersji środowiska CLR do uruchamiania plików wykonywalnych .NET CIL. CLR jest natywną aplikacją Windows, podobnie jak tradycyjne pliki Win32 EXE opisane powyżej. Sam CLR jest specyficzny dla implementacji Windows i architektury komputerowej, dla której został zaprojektowany.

Nie ma znaczenia, z jakiego języka .NET zaczniesz (C#, VisualBasic, F #, IronPython, IronRuby, Boo itd.), Wszystkie zostaną skompilowane do kodu bajtowego CIL. Możesz łatwo "zdemontować" program CIL w postaci obiektowego języka asemblerowego, który jest łatwy do odczytania przez ludzi. Możesz napisać program bezpośrednio w CIL, ale niewiele osób to robi.

W systemie Windows CLR kompiluje ten kod CIL "Just-in-Time" (JIT) tuż po uruchomieniu pliku wykonywalnego - tuż przed faktycznym uruchomieniem kodu. Oznacza to, że kod bajtowy CIL jest konwertowany (kompilowany) na rzeczywisty kod maszynowy, który działa natywnie na twoim komputerze. Ta część CLR jest nazywana kompilatorem JIT lub często tylko JIT.

Do tej pory firma Microsoft wydała cztery wersje środowiska CLR: 1.0, 1.1, 2.0 i 4.0. Aby móc uruchamiać pliki wykonywalne .NET kierowane na to środowisko, na komputerze musi być zainstalowana odpowiednia wersja środowiska CLR. CLR 2.0 obsługuje aplikacje .NET 2.0, 3.0 i 3.5. W przypadku innych wersji .NET wersja .NET jest mapowana czysto do wersji CLR.

Oprócz JIT/CLR. NET dostarcza wiele bibliotek (złożeń), które składają się na resztę architektury .NET i zapewniają wiele możliwości i usług, z których mogą korzystać aplikacje .NET. Ogromna większość tych zespołów to czysty kod CIL, który działa na CLR. W systemie Windows niektóre wywołują również wywołania Win32 API. Podczas instalacji .NET instalujesz CLR, biblioteki klas (framework) i kilka narzędzi programistycznych. Każda wersja CLR zazwyczaj wymaga kompletnego zestawu tych "szkieletowych" zespołów. Niektóre wersje .NET (np. 3.0 i 3.5) dodawały dodatkowe zespoły szkieletowe bez aktualizacji CLR lub istniejących złożeń powiązanych z tym CLR.

Format pliku Portable Executable (PE), do którego dostarczono plik .EXE systemu Windows zawiera nagłówek opisujący plik wykonywalny i identyfikujący plik jako plik .NET lub macierzysty plik Win32. Kiedy system Windows próbuje uruchomić plik .NET, widzi ten nagłówek i automatycznie wywołuje CLR w twoim imieniu. Właśnie dlatego pliki .NET EXE wydają się działać natywnie w systemie Windows.

Ok, więc jak działa Mono?

Mono implementuje CLR na systemach Linux, Mac i innych platformach. Środowisko wykonawcze Mono (CLR) to natywna aplikacja napisana głównie w języku C i skompilowana do kodu języka komputera dla systemu komputerowego, na którym ma działać. Podobnie jak w systemie Windows, środowisko wykonawcze Mono jest specyficzne dla systemu operacyjnego i rodzaju używanego komputera.

Podobnie jak w Windows, środowisko wykonawcze Mono (CLR) kompiluje kod bajtowy CIL w pliku wykonywalnym .NET Just-in-time na natywny kod, który komputer może zrozumieć i wykonać. W ten sposób plik .NET jest tak samo "natywny" jak dla systemu Linux.

Aby przesłać Mono do nowej architektury, należy przesłać JIT/CLR. Jest to podobne do przenoszenia dowolnej natywnej aplikacji na nową platformę.

Dobrze działający kod .NET na Linuksie lub Macu to tylko kwestia, jak dobrze CLR jest zaimplementowany w tych systemach. Teoretycznie, Mono CLR mógłby wykonywać kod .NET na tych systemach znacznie lepiej niż wersja MS .NETa działająca w systemie Windows. W praktyce wdrożenie MS jest ogólnie lepsze (choć nie we wszystkich przypadkach).

Oprócz CLR, Mono zapewnia większość pozostałych bibliotek (złożeń), które tworzą strukturę .NET. Podobnie jak w wersji Microsoft .NET (w rzeczywistości bardziej), zespoły monofoniczne są dostarczane jako kod bajtowy CIL. Dzięki temu można pobrać plik * .dll lub * .exe z Mono i uruchomić go niezmodyfikowany w systemach Windows, Mac i Linux, ponieważ CIL to "rodzimy" język implementacji CLR w tych systemach.

Podobnie jak w systemie Windows, Mono obsługuje wiele wersji CLR oraz związane z nimi zespoły:

Bardzo wczesne wersje mono (przed 1.2?) Tylko obsługiwane CLR 1.0 lub 1.1. Mono nie obsługiwał dużych fragmentów struktury 2.0, dopóki nie jest własną wersją 2.0.

Wersje mono do wersji 2.4 obsługują zarówno aplikacje CLR 1.1, jak i CLR 2.0.

Począwszy od Mono 2.6, dodano CLR 4.0, ale CLR 2.0 był nadal domyślny.

Począwszy od wersji Mono 2.8, CLR 4.0 stał się domyślny, a CLR 1.1 nie jest już obsługiwany.

Mono 2.10 nadal używa CLR 4.0 jako domyślnego, a także do obsługi CLR 2.0.

Podobnie jak w rzeczywistym .NET (ale w znacznie mniejszej liczbie przypadków) istnieją pewne zespoły monofoniczne, które wywołują biblioteki natywne. Aby zmontować zestaw System.Drawing w Mono, zespół Mono napisał program Linux, aby zasymulować porcję GDI + Win32 API w systemie Linux. Ta biblioteka nazywa się "libgdiplus". Jeśli skompilujesz Mono ze źródła, zauważysz, że musisz zbudować ten plik 'libgdiplus', zanim będziesz mógł zbudować 'mono'. Nie potrzebujesz "libgdiplus" w systemie Windows, ponieważ część interfejsu Win32 API systemu GDI + jest już częścią systemu Windows. Pełny port Mono na nowe platformy wymaga również przeniesienia biblioteki "libgdiplus".

W obszarach, w których konstrukcja biblioteki .NET jest nadmiernie uzależniona od projektu systemu Windows i słabo pasuje do systemów takich jak Mac lub Linux, zespół Mono napisał rozszerzenia do platformy .NET. Rozszerzenia Mono to także kod bajtowy CIL i ogólnie działają dobrze na platformie .NET.

W przeciwieństwie do systemu Windows, Linux zazwyczaj nie wykrywa plików wykonywalnych .NET i domyślnie uruchamia CLR. Użytkownik zwykle musi uruchamiać CLR bezpośrednio, wpisując "mono appname.exe" lub coś podobnego. Tutaj "mono" jest aplikacją, która implementuje CLR, a "appname.exe" jest plikiem EXE, który zawiera kod .NET do wykonania.

Aby ułatwić pracę użytkownikom, aplikacje Mono są często pakowane w skrypt powłoki, który uruchamia środowisko CLR. To ukrywa fakt, że CLR jest używany tak, jak w Windows. Możliwe jest również poinformowanie Linuxa o uruchomieniu CLR, gdy napotkany zostanie plik z formatem pliku PE. Zwykle nie jest to wykonywane, ponieważ format pliku PE jest również używany w przypadku rodzimych plików wykonywalnych systemu Win32, które oczywiście nie obsługują CLR (Mono).

Nie ma żadnego technicznego powodu, dla którego program uruchamiający PE nie mógłby być używany przez system Linux, który uruchamia system rozpoznający natywny kod systemu Windows (np. Wine) lub CLR (Mono). Po prostu nie zostało to zrobione według mojej wiedzy.

iz powrotem

Każdy kod .NET, które przykleja się do „w pełni zarządzane” kod, co oznacza, że ​​nie nazywa się kodem non-.NET, powinien działać dobrze na Mono na wszystkich platformach. Rutynowo używam skompilowanych zestawów .NET z Windows (dla których nie mam kodu) w systemach Linux i Mac.

Mogę również pobrać dowolny kod, który kompiluję w Mono i uruchomić go na platformie .NET w systemie Windows. Mogę dostarczyć klientowi kod skompilowany z Mono i nie martwić się, jeśli jest na przykład w 32-bitowym lub 64-bitowym systemie Windows. Klient musi mieć zainstalowaną odpowiednią wersję .NET (prawy CLR). CLR 2.0 istnieje od bardzo dawna i można założyć, że prawie wszyscy użytkownicy Windows mają go zainstalowanych. Kompilatory Mono i inny kod to także pliki wykonywalne CIL, więc jeśli chcesz, działają poprawnie w systemie Windows.

Kompatybilność w trybie mono wystarcza, aby duże fragmenty rzeczywistego kodu Microsoft, np. ASP.NET MVC, mogły zostać pobrane (jeśli jest to zgodne z prawem) z rzeczywistej wersji MS .NET i uruchomione na komputerach Mac lub Linux. Ogólnie rzecz biorąc, zespół Mono wykonał świetną robotę implementując zarówno CLR, jak i reszta frameworka (biblioteki klas/zespoły).

ASP.NET

W systemie Windows Internet Information Server (IIS) wie, jak zadzwonić do CLR .NET do wykonania w ramach aplikacji internetowej. W systemie Linux/Mac dostępny jest moduł Apache (mod_mono), który zapewnia podobne możliwości do serwera WWW Apache. Ta aplikacja jest napisana w języku C i musi być również przeniesiona do nowych architektur.

Porting Mono

Ta dyskusja zidentyfikował części Mono, które zostały zbudowane jako „native” wykonywalnych i musi istnieć w systemie, na którym chcesz uruchomić aplikacji .NET.

  • CLR (w tym JIT kompilator) - powszechnie znany jako Mono
  • libgdiplus (dla systemów, które nie natywnie obsługują GDI + API [tylko Windows ma])
  • mod_mono (aby umożliwić Apache podniesienia zarzutu CLR dla aplikacji internetowych .NET)

Te trzy komponenty, z dodatkiem bibliotek klas, udostępniają środowisko .NET, które wygląda "natywnie" do plików wykonywalnych .NET, które należy uruchomić.

Tak działa Mono.

+1

bardzo ładne kompleksowe napisy. Masz jednak jedno pytanie. Kiedy uruchomisz skompilowany .net exe, w jaki sposób system operacyjny wie, że musi uruchomić JIT przez niego, czy nie? Czy nie musi korzystać z jakiegoś wykonywanego przez PE32 hakera, który uruchamia JIT w razie potrzeby? Ale jeśli to zrobi, to będzie zależało od platformy? W jaki sposób inna platforma używa tego exe, ponieważ nie rozumie PE32? – greatwolf

+1

@Victor - Struktura pliku PE (EXE) zawiera nagłówek. Sekcja "opcjonalna" tego nagłówka identyfikuje plik jako plik wykonywalny .NET. Przed Windows XP program ładujący nie miał wiedzy o .NET i wymagał natywnej instrukcji skoku, aby wywołać CLR. Od XP program ładujący przegląda nagłówek i bezpośrednio wywołuje CLR (nie wymaga natywnego kodu). CLR wywołuje JIT. W przypadku Mono, typowe jest wywoływanie CLR ręcznie w czasie uruchamiania (np. Przez wpisanie "mono somefile.exe"). "Hackery" PE to tylko dane w nagłówku. Ani Mono, ani nowoczesne Windows nie używają natywnego kodu z EXE. – Justin

+0

@Victor - JIT jest wywoływany przy każdym uruchomieniu pliku wykonywalnego CIL (.NET). Nie jest kompilowany do natywnego kodu do czasu wykonania. Dlatego nazywany jest "Just-in-Time". Możesz wykonać kompilację AOT w Mono (lub użyć ngen.exe na .NET), aby wstępnie skompilować część kodu. Ten skompilowany kod nie jest przenośny. JIT jest nadal wywoływany nawet w czasie wykonywania, ale może użyć wstępnie skompilowanego kodu z "pamięci podręcznej", jeśli jest to właściwe. AOT/Ngen nie są typowe, chociaż MonoTouch (.NET na iOS) tego wymaga i używa wyłącznie pełnej AOT. – Justin