Как работает Mono

Я использовал C # в Visual Studio с .NET, и я немного поигрался с Mono в openSUSE Linux, но я действительно не понимаю, как это работает.

Если я напишу приложение в Windows на .NET, какое отношение это имеет к Mono? Я не могу просто запустить файл Windows .exe в Linux без Wine, поэтому он не помогает мне запускать приложения, разработанные в Windows.

Является ли цель просто иметь эквивалент библиотеки .NET в Linux (и других), чтобы упростить кроссплатформенную разработку? Например, если я занимался бизнесом и хотел привлечь клиентов Linux, но действительно хотел использовать .NET, тогда мне следовало бы выбрать Mono? Или мне не хватает чего-то еще?


person DavidG    schedule 19.10.2008    source источник


Ответы (8)


EXE для Windows состоит из нескольких «частей». Упрощенно, код .net (= MSIL) является только частью EXE, а внутри EXE также есть "настоящая" родная часть Windows, которая служит своего рода средством запуска для .net Framework, который затем выполняет MSIL.

Mono просто возьмет MSIL и выполнит его, игнорируя собственный материал Windows Launcher.

Опять же, это упрощенный обзор.

Изменить: Боюсь, что мое понимание глубоких подробностей недостаточно для действительно большого количества деталей (я примерно знаю, что такое PE-заголовок, но не совсем подробности), но я нашел эти ссылки полезными:

Структура сборки NET - Часть II

Основы .NET - сборка .NET структура

person Michael Stum    schedule 19.10.2008
comment
есть шанс на чуть более подробную версию? :) - person DavidG; 19.10.2008
comment
Я боюсь, что мое понимание глубоких деталей depp недостаточно для этого (я примерно знаю, что такое PE-заголовок, но не совсем подробности), но я нашел эти ссылки полезными: is.gd/4n4i is.gd/4n4n - person Michael Stum; 19.10.2008
comment
Внутри EXE нет настоящей родной части Windows. Заголовок - это просто описание. Он может указывать на точку входа в EXE или DLL, но это либо исполняется средой хоста, либо нет. Фактическая программа запуска является внешней по отношению к исполняемому файлу и является либо собственной Windows, либо частью CLR (для .NET и Mono). - person Justin; 04.03.2011
comment
@Justin Я считаю, что .net все еще включает заглушку Windows Native. Помните, что Windows 2000 не знала о .net, поэтому .exe должен был иметь в себе загрузчик Windows. Более поздние загрузчики EXE в ОС Windows понимают .net и могут его пропускать. Книга Марио Хьюардта Advanced .NET Debugging содержала объяснение. Не уверен, что это все еще применимо к .net 4, поскольку это работает только в более новых версиях Windows. Также надеюсь, что я правильно понял ваш комментарий :) - person Michael Stum; 04.03.2011
comment
Windows использует DLL (mscoree.dll) для инициализации среды CLR и запуска исполняемого кода .NET. Эта программа запуска CLR является внешней по отношению к самому EXE-файлу. Для версий Windows до XP вы правы, что в EXE есть инструкция одиночного перехода, которая передает выполнение этой DLL. Начиная с XP, Windows Loader обнаруживает файлы .NET и загружает саму среду CLR. Ни современная Windows, ни Mono не требуют и не используют инструкцию перехода. Во всех случаях (Mono, старая и новая Windows) сама среда CLR проверяет EXE-файл на предмет точки входа, а затем выполняет соответствующий байт-код CIL. - person Justin; 04.03.2011

Это старый вопрос (с уже выбранным ответом), но я не думаю, что на него действительно дан хороший ответ.

Сначала немного предыстории ...

Как работает .NET?

Традиционный файл Windows .EXE - это двоичный файл, который представляет собой серию инструкций на машинном языке, которые понимает ваш компьютер, и который выполняет вызовы Win32 API, которые являются частями Windows, которые предоставляют услуги, которыми могут воспользоваться приложения. Используемый машинный язык очень специфичен для вашего типа компьютера, а вызовы Win32 делают исполняемый файл очень зависимым от Windows. Исполняемый файл .NET не такой.

Важно понимать, что исполняемый файл .NET (файл .EXE) на самом деле не является собственным приложением Windows. Сама Windows не понимает, как запустить код в исполняемом файле .NET. Ваш компьютер тоже этого не понимает.

Как и Java, приложение .NET состоит из инструкций на языке CIL (Common Intermediate Language), который вы можете рассматривать как машинный язык для идеализированного компьютера, которого на самом деле не существует. В .NET программная реализация этой идеализированной машины называется Common Language Runtime (CLR). Эквивалент в мире Java называется виртуальной машиной Java (JVM). В Java эквивалент CIL называется байт-кодом Java. CIL иногда называют MSIL (Microsoft Intermediate Language).

CIL разработан для работы на CLR (идеализированной машине), но в остальном он не зависит от платформы, что означает, что CIL не заботится о том, какой у вас компьютер или какая операционная система работает.

Так же, как вам нужна собственная версия Java JVM на каждой платформе, на которой вы хотите запускать Java, вам нужна собственная версия CLR для запуска исполняемых файлов .NET CIL. CLR - это собственное приложение Windows, подобное традиционным Win32 EXE-файлам, описанным выше. Сама среда CLR специфична для реализации Windows и архитектуры компьютера, на которой она была разработана.

Неважно, с какого языка .NET вы начинаете (C #, VisualBasic, F #, IronPython, IronRuby, Boo и т. Д.), Все они компилируются в байт-код CIL. Вы можете легко «разобрать» программу CIL на объектно-ориентированный язык ассемблера, который легко читается людьми. Вы можете написать программу на CIL сами, но это мало кто делает.

В Windows CLR компилирует этот код CIL точно в срок (JIT) прямо при запуске исполняемого файла - непосредственно перед фактическим запуском кода. Это означает, что байт-код CIL преобразуется (компилируется) в реальный машинный код, который изначально выполняется на вашем компьютере. Эта часть CLR называется JIT-компилятором или часто просто JIT.

На сегодняшний день Microsoft выпустила четыре версии CLR: 1.0, 1.1, 2.0 и 4.0. У вас должна быть установлена ​​правильная версия CLR на вашем компьютере, если вы хотите запускать исполняемые файлы .NET, ориентированные на эту среду выполнения. CLR 2.0 поддерживает приложения .NET 2.0, 3.0 и 3.5. Для других версий .NET версия .NET полностью соответствует версии CLR.

Помимо JIT / CLR, .NET предоставляет множество библиотек (сборок), составляющих остальную часть .NET framework и предоставляющих множество возможностей и служб, которые могут вызывать .NET-приложения. Подавляющее большинство этих сборок представляют собой чистый код CIL, работающий в среде CLR. В Windows некоторые также обращаются к Win32 API. При установке .NET вы устанавливаете CLR, библиотеки классов (фреймворк) и набор инструментов разработки. Для каждой версии среды CLR обычно требуется полный набор этих «каркасных» сборок. Некоторые версии .NET (например, 3.0 и 3.5) добавляли дополнительные сборки инфраструктуры без обновления среды CLR или существующих сборок, связанных с этой средой CLR.

Формат файла Portable Executable (PE), в котором доставляется файл Windows .EXE, содержит заголовок, который описывает исполняемый файл и идентифицирует файл как файл .NET или собственный файл Win32. Когда Windows пытается запустить файл .NET, она видит этот заголовок и автоматически вызывает среду CLR от вашего имени. Вот почему файлы .NET EXE изначально запускаются в Windows.

Итак, как работает Mono?

Mono реализует CLR на Linux, Mac и других платформах. Среда выполнения Mono (CLR) - это собственное приложение, написанное в основном на языке C и скомпилированное до кода машинного языка для компьютерной системы, на которой она предназначена. Как и в Windows, среда выполнения Mono зависит от операционной системы и типа используемой вами машины.

Как и в Windows, среда выполнения Mono (CLR) компилирует байт-код CIL в исполняемом файле .NET точно в срок в собственный код, который ваш компьютер может понять и выполнить. Таким образом, файл .NET является таким же «родным» для Linux, как и для Windows.

Чтобы перенести Mono на новую архитектуру, вам необходимо перенести JIT / CLR. Это похоже на перенос любого собственного приложения на новую платформу.

Насколько хорошо .NET-код работает в Linux или Mac, на самом деле просто вопрос того, насколько хорошо CLR реализована в этих системах. Теоретически Mono CLR может выполнять код .NET в этих системах намного лучше, чем версия .NET для MS в Windows. На практике реализация MS обычно лучше (хотя и не во всех случаях).

В дополнение к CLR Mono предоставляет большую часть остальных библиотек (сборок), составляющих платформу .NET. Так же, как и в версии .NET от Microsoft (а точнее, даже больше), сборки Mono предоставляются в виде байт-кода CIL. Это позволяет взять файл * .dll или * .exe из Mono и запустить его без изменений в Windows, Mac или Linux, поскольку CIL является «родным» языком реализаций CLR в этих системах.

Как и в Windows, Mono поддерживает несколько версий CLR и связанных сборок:

Очень ранние версии Mono (до 1.2?) Поддерживали только CLR 1.0 или 1.1. Mono не поддерживал большие фрагменты фреймворка 2.0 до своей собственной версии 2.0.

Версии Mono до версии 2.4 поддерживали приложения CLR 1.1 и CLR 2.0.

Начиная с Mono 2.6, была добавлена ​​CLR 4.0, но CLR 2.0 по-прежнему использовалась по умолчанию.

Начиная с Mono 2.8, по умолчанию используется среда CLR 4.0, а среда CLR 1.1 больше не поддерживается.

Mono 2.10 продолжает использовать CLR 4.0 по умолчанию, а также поддерживает CLR 2.0.

Как и настоящий .NET (но в гораздо меньшем количестве случаев), есть некоторые сборки Mono, которые обращаются к собственным библиотекам. Чтобы сборка System.Drawing работала на Mono, команда Mono написала программу для Linux, имитирующую GDI + часть Win32 API в Linux. Эта библиотека называется libgdiplus. Если вы компилируете Mono из исходного кода, вы заметите, что вам нужно собрать этот файл libgdiplus, прежде чем вы сможете собрать mono. Вам не нужен libgdiplus в Windows, потому что часть GDI + Win32 API уже является частью Windows. Для полного переноса Mono на новые платформы требуется также портировать эту библиотеку libgdiplus.

В тех областях, где дизайн библиотеки .NET чрезмерно зависит от дизайна Windows и плохо подходит для таких систем, как Mac или Linux, команда Mono написала расширения для .NET framework. Расширения Mono также представляют собой байт-код CIL и обычно отлично работают в .NET.

В отличие от Windows, Linux обычно не обнаруживает исполняемые файлы .NET и по умолчанию запускает среду CLR. Обычно пользователь должен запускать среду CLR напрямую, набрав «mono appname.exe» или что-то подобное. Здесь mono - это приложение, реализующее CLR, а appname.exe - это EXE-файл, содержащий исполняемый код .NET.

Чтобы упростить пользователям задачу, приложения Mono часто заключаются в оболочку сценария, запускающего среду CLR. Это скрывает тот факт, что среда CLR используется так же, как в Windows. Также можно указать Linux запускать среду CLR при обнаружении файла, использующего формат файла PE. Обычно это не делается, поскольку формат PE-файла также используется для собственных исполняемых файлов Win32 Windows, которые, конечно, не поддерживает CLR (Mono).

Нет никакой технической причины, по которой средство запуска PE не может использоваться Linux, который затем запускает либо систему, которая понимает собственный код Windows (например, Wine), либо CLR (Mono), в зависимости от ситуации. Насколько мне известно, этого просто не было сделано.

Взад и вперед

Любой код .NET, который придерживается «полностью управляемого» кода, что означает, что он не вызывает код, отличный от .NET, должен нормально работать в Mono на всех платформах. Я обычно использую скомпилированные сборки .NET из Windows (для которых у меня нет кода) в Linux и Mac.

Я также могу взять любой код, который я компилирую в Mono, и запустить его в .NET в Windows. Я могу предоставить клиенту код, который я скомпилировал с помощью Mono, и не беспокоиться о том, работает ли он, например, в 32-битной или 64-битной Windows. Для курса у клиента должна быть установлена ​​правильная версия .NET (правильная среда CLR). CLR 2.0 существует уже очень давно, и можно поспорить, что он установлен почти у всех пользователей Windows. Компиляторы Mono и другой код также являются просто исполняемыми файлами CIL, поэтому они отлично работают в Windows, если хотите.

Совместимость с моно достаточно хороша, чтобы большие фрагменты реального кода Microsoft, такие как ASP.NET MVC, можно было взять (там, где это разрешено) из фактической версии .NET для MS и запустить на Mac или Linux. В целом команда Mono проделала огромную работу по реализации как CLR, так и остальной части фреймворка (библиотеки классов / сборки).

ASP.NET

В Windows Internet Information Server (IIS) знает, как вызвать среду CLR для выполнения .NET как части веб-приложения. В Linux / Mac есть модуль Apache (mod_mono), который предоставляет аналогичные возможности веб-серверу Apache. Это приложение написано на C и также должно быть перенесено на новые архитектуры.

Перенос Mono

В этом обсуждении были определены части Mono, которые созданы как «собственные» исполняемые файлы и должны существовать в системе, в которой вы хотите запускать приложения .NET.

  • CLR (включая JIT-компилятор) - обычно известный как Mono
  • libgdiplus (для систем, которые изначально не поддерживают GDI + API [только Windows поддерживает])
  • mod_mono (чтобы Apache мог вызывать CLR для веб-приложений .NET)

Эти три компонента с добавлением библиотек классов обеспечивают среду .NET, которая выглядит «родной» для исполняемых файлов .NET, которые необходимо запустить.

Так работает Mono.

person Justin    schedule 04.03.2011
comment
очень хорошее подробное описание. Хотя есть один вопрос. Когда вы запускаете скомпилированный .net exe, как ОС узнает, что через него нужно запускать JIT или нет? Разве он не должен использовать какой-то исполняемый файл PE32, который запускает JIT, если это необходимо? Но если это будет сделано, это сделает его зависимым от платформы? Как другая платформа будет использовать этот исполняемый файл, если он не понимает PE32? - person greatwolf; 14.05.2011
comment
@Victor - файловая структура PE (EXE) содержит заголовок. Необязательный раздел этого заголовка определяет файл как исполняемый файл .NET. До Windows XP исполняемый загрузчик не знал .NET и требовал встроенной инструкции перехода для вызова CLR. Начиная с XP, загрузчик просматривает заголовок и напрямую вызывает CLR (собственный код не требуется). CLR вызывает JIT. Для Mono типично запускать среду CLR вручную во время запуска (например, набрав mono somefile.exe). Хакерство PE - это просто данные в заголовке. Ни Mono, ни современная Windows не используют нативный код из EXE. - person Justin; 20.05.2011
comment
@Victor - JIT вызывается каждый раз, когда вы запускаете исполняемый файл CIL (.NET). Он не компилируется в собственный код до времени выполнения. Именно поэтому он называется Just-in-Time. Вы можете делать такие вещи, как компиляция AOT в Mono (или использовать ngen.exe в .NET) для предварительной компиляции некоторого кода. Этот предварительно скомпилированный код не переносится. JIT по-прежнему вызывается во время выполнения, но при необходимости может использовать предварительно скомпилированный код из кеша. AOT / Ngen не типичны, хотя MonoTouch (.NET на iOS) требует этого и использует исключительно полный AOT. - person Justin; 20.05.2011
comment
+1, хороший и исчерпывающий ответ. Небольшие придирки все еще могут быть разрешены: Mono реализует CLR на Linux, Mac и других платформах. Строго говоря, нет. Согласно стандарту (ECMA-335, 5-е издание, раздел 1, глава 12) среда выполнения Mono реализует VES (виртуальная исполнительная система), часть среды выполнения CLI. CLR - это просто реализация Microsoft VES. - person Frank; 22.02.2012
comment
Теоретически Mono CLR может выполнять код .NET в этих системах [Linux и Mac] намного лучше, чем версия .NET для MS в Windows. Как же так? Не могли бы вы подробнее рассказать об этом? - person Drasive; 20.03.2015
comment
где мы можем увидеть исходный код реализации CLR для Mono? - person Ehsan Sajjad; 01.04.2016
comment
Если бы я мог добавить еще 10 голосов, я бы это сделал. Это очень помогло мне понять общую картину того, как работает Mono. Прекрасная работа - person Everyone; 26.02.2017
comment
Вы уверены в этой строке - вы можете думать о ней как о машинном языке для идеализированного компьютера, которого на самом деле не существует. Раньше я думал, что CIL похож на код языка ассемблера и такой же для байт-кода java. - person Anjani; 15.03.2018

Фактически, вы можете запустить файл .NET .exe с помощью Mono в Linux. Для этого не требуется Wine. Фактически, Mono компилирует программы в файлы .exe, которые могут работать либо с Mono в Linux, либо как исполняемый файл в Windows.

person Greg Hewgill    schedule 19.10.2008
comment
Правильный. Mono реализует CLR (.NET), в то время как Wine пытается реализовать полную родную среду Windows (Win32 API и функции ядра). - person Justin; 04.03.2011

Mono - это реализация Microsoft .NET CLR (Common Language Runtime) с открытым исходным кодом. Это то, что запускает часть программ .NET, которые находятся не в собственном коде, а на CIL (Common Intermediate Language), языке и машинно-нейтральном промежуточном языке. Среда выполнения берет этот промежуточный код и переводит его в машинный код.

В текущем состоянии Mono вы можете взять программы .NET, которые используют основные части .NET (mscorlib.dll), и запускать их везде, где работает Mono, а не только в Windows.

person Quantenmechaniker    schedule 19.10.2008

Но, как уже упоминалось, Mono является открытым исходным кодом, и вы не можете просто полагаться, что это будет полная реализация .NET, у него есть некоторые элементы управления, которые не работают, вы также должны быть осторожны с P / Invokes, которые ваше приложение будет использовать. , например, ваше приложение будет взаимодействовать с MCI (интерфейс мультимедийного контроллера) под win32. Но я также использовал моно для написания приложений GTK #, но я также использовал свои приложения для Windows, которые работали без какой-либо перекомпиляции, как упоминалось выше нашими коллегами-программистами, то есть моно - это альтернатива Microsoft .NET с открытым исходным кодом, и по умолчанию, если вы создаете приложения WinForms или Gtk # mono будет компилироваться и создавать сборку .exe для каждого файла, и, конечно, если вы хотите, она создаст библиотеку динамической компоновки (DLL), почти так же, как это делается в .NET. Просто для предложения попробуйте написать немного Gtk # (с MonoDevelop IDE, в которой есть встроенный дизайнер графического интерфейса под названием stetic). И, конечно же, mono может быть отличной заменой веб-службам, которые вы можете создавать на .NET, и вы можете размещать их на Apache (потому что хостинг Linux в настоящее время дешевле, чем Windows), веб-службы и другие приложения asp.net будут работать под apache с модулем mod_mono, который должен быть включен в apache.

Немного не по теме, но я просто хотел рассказать вам немного о своем опыте.

person milot    schedule 19.10.2008

Также вы можете взглянуть на MoMA (если ваша цель - портировать приложения с Win на Lin).

Инструмент Mono Migration Analyzer (MoMA) помогает выявить проблемы, которые могут возникнуть при переносе вашего .Net-приложения на Mono. Это помогает точно определить вызовы, специфичные для платформы (P / Invoke), и области, которые еще не поддерживаются проектом Mono.

MoMA

Вот веб-приложение, которое сравнивает типы BCL, уже реализованные в Mono и .NET Framework 3.5.

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

person jaircazarin-old-account    schedule 19.10.2008

Чтобы продолжить ответ Майкла, я считаю, что вам придется перекомпилировать в Mono, чтобы приложение работало в среде выполнения Mono. Могут существовать исключения. Я только немного поигрался с Mono и всегда перекомпилировал исходный код. Я никогда не пробовал запускать .NET-приложение непосредственно на Mono.

Кроме того, предполагается, что Mono 1.9 полностью совместим с .NET 2.0. Предполагается, что Mono Olive и Moonlight добавляют функциональность .NET 3.0 (без WPF) и Silverlight.

person Community    schedule 19.10.2008
comment
Просто примечание. Вам, конечно, не нужно перекомпилировать приложение .NET, чтобы оно работало в Mono. - person Justin; 04.03.2011

Это может вам помочь, Как Mono's Компилятор C # работает?, а также Общие сведения о Mono Книга "Компилятор C #".

person user727071    schedule 17.02.2012
comment
Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки. - person Adi Lester; 27.10.2012