Если вы считаете, что GIMP не ровня Photoshop, и не можете жить без офиса от Microsoft.
1. Wine
Название Wine расшифровывается как Wine Is Not an Emulator. Это своего рода прослойка между приложениями Windows и системой Linux. Он позволяет устанавливать и запускать многие популярные Windows-программы и работать с ними так, как будто это родные приложения Linux.
Чтобы установить Wine, воспользуйтесь соответствующей командой.
1. Ubuntu, Debian, Mint:
sudo dpkg --add-architecture i386
wget -nc https://dl.winehq.org/wine-builds/Release.key
sudo apt-key add Release.key
sudo add-apt-repository "deb https://dl.winehq.org/wine-builds/ubuntu/ artful main"
sudo apt-get update
sudo apt-get install --install-recommends winehq-stable
2. Fedora:
sudo dnf install winehq-stable
3. openSUSE:
sudo zypper install wine
4. Arch, Manjaro:
sudo pacman -S wine
Когда Wine установлен, откройте его через ваше меню приложений или с помощью команды winecfg
. При первом запуске Wine может попросить установить некоторые дополнительные пакеты — позвольте ему это сделать. После этого все Windows-программы формата EXE ассоциируются в системе с Wine.
Теперь скачайте установщик нужного вам приложения Windows, найдите папку с ним в вашем файловом менеджере и откройте файл. Либо введите команду wine путь_к_приложению
.
Windows-приложение запустится и будет работать так же, как и всегда. Если вы открыли установочный файл, начнётся установка приложения — как в Windows. Если программа не требует установки, вы сможете начать работать с ней немедленно.
Не все приложения могут быть установлены и запущены в Wine, хотя количество поддерживаемых впечатляет. Полный список можно посмотреть здесь.
2. Winetricks
Wine — неплохой инструмент, однако интерфейс у него оставляет желать лучшего. Если вы намучились с этой программой, но так и не добились результата, попробуйте Winetricks. У неё приятный графический интерфейс для установки и запуска Windows-приложений, в котором куда проще разобраться новичку.
Установить Winetricks можно так:
1. Ubuntu, Debian, Mint:
sudo apt-get install winetricks
2. Fedora:
sudo dnf install winetricks
3. openSUSE:
sudo zypper install winetricks
4. Arch, Manjaro:
sudo pacman -S winetricks
Winetricks позволяет установить различные версии Microsoft Office и Photoshop, плеер foobar2000 и множество других программ. Поддерживаются и такие популярные игры, как Call of Duty, Call of Duty 4, Call of Duty 5, Biohazard и Grand Theft Auto: Vice City. Некоторые программы загружаются автоматически, для других будет предложено вставить установочный носитель. И, естественно, вы можете открывать собственноручно скачанные файлы формата EXE.
3. PlayOnLinux
PlayOnLinux — ещё один удобный инструмент для запуска Windows-приложений в Linux. Как и Winetricks, он обладает простым графическим интерфейсом. Но, в отличие от него, PlayOnLinux позволяет вам выбирать конкретную версию Wine для того или иного приложения. Это полезно, если какая-то из нужных вам программ некорректно работает с новыми версиями Wine. В целом PlayOnLinux выглядит куда симпатичнее и практичнее, чем Winetricks.
Чтобы установить PlayOnLinux, выполните в терминале одну из следующих команд:
1. Ubuntu, Debian, Mint:
sudo apt-get install playonlinux
2. Fedora:
sudo dnf install playonlinux
3. OpenSUSE:
sudo zypper install playonlinux
4. Arch, Manjaro:
sudo pacman -S playonlinux
В меню установки PlayOnLinux можно найти множество предварительно сконфигурированных приложений и игр, которые вы можете загрузить и установить парой щелчков. Кроме того, PlayOnLinux можно скармливать собственные EXE-установщики. Приложение заботливо выберет за вас версию Wine и создаст значок установленной программы на рабочем столе.
4. Crossover
Изредка бесплатные PlayOnLinux и Winetricks не справляются с установкой какого-нибудь особенно привередливого приложения. В таком случае вам может помочь Crossover. Эта программа очень проста в использовании. Вам достаточно указать, какое приложение вы хотите установить, и подсунуть Crossover установочный файл. Всё остальное будет сделано за вас.
Лицензия Crossover на год стоит 39,95 доллара, но у программы есть и бесплатная пробная версия. Рекомендуется сначала установить необходимое вам приложение в ней, чтобы убедиться, что оно работает корректно.
Crossover →
5. VirtualBox
Если ваше приложение упорно отказывается запускаться в перечисленных выше программах, можно пойти на решительные меры и установить его в виртуальной машине. Учтите, что она отнимает гораздо больше системных ресурсов, поэтому использовать её стоит в крайних случаях.
Для запуска приложения в виртуалке вам понадобится установочный образ Windows в формате ISO. Загрузите и установите VirtualBox, создайте в нём виртуальную машину, укажите ей ISO с Windows, а затем просто установите систему как обычно.
Неоспоримый плюс виртуальной машины — в ней работает полноценная операционная система, а значит, запустится абсолютно всё. Минус — прожорливость в плане системных ресурсов, да и тратиться на лицензию Windows для виртуалки накладно.
VirtualBox →
Читайте также 🧐
- 6 задач, с которыми Linux справляется лучше, чем Windows
- Как реанимировать Windows и сохранить данные с помощью live-дистрибутива Linux
- Как обмениваться файлами по воздуху между Windows, macOS, Linux, iOS и Android
Рано или поздно может понадобиться запустить программы Windows на Linux. Для операционной системы Linux написано огромное количество программ, для решения одной определенной задачи, может быть даже несколько десятков программ. Но такая тенденция наблюдается только для широко распространенных задач, что же касается специализированных программ и игр, то тут ситуация совсем иная.
Программ, для решения узкоспециализированных задач, например, в той же сфере СЕО для Linux попросту нет, а игры начали появляться только последние несколько лет. Были и раньше простенькие игры с открытым исходным кодом, но популярные игры, класса ААА начали появляться только тогда, когда этой платформой заинтересовалась Valve. Но до сих пор ситуация с играми обстоит не так, как хотелось бы. Поэтому и возникает необходимость установки Windows программ в Linux.
Немного теории
Windows программы не могут запускаться просто двойным щелчком по исполняемому файлу. Формат исполняемых файлов Linux очень сильно отличается от Windows. Поэтому для их запуска необходимо использовать специальное программное обеспечение — wine. Название Wine образовано с помощью, почему-то популярного в мире свободного программного обеспечения способа — рекурсивный акроним, и расшифровывается как Wine is not emultor. И это правда, wine не является эмулятором.
Это программная оболочка, которая преобразует системные вызовы Windows программ в вызовы функций операционной системы Linux. Таким образом, wine представляет из себя прослойку между Windows программой и операционной системой Linux вместе с ее ядром и библиотеками.
Чтобы понять как работает Wine, нужно сначала сказать несколько слов о ядре Windows. У Windows, так же как и у Linux есть ядро. Как вы знаете ядро Linux состоит из одного файла и находится в папке boot. Ядро Windows совсем другое, по сути это набор dll библиотек, которые расположены в папке C:\windows\system32. Поэтому нам, чтобы заставить Windows программы работать в Linux достаточно реализовать dll библиотеки, которые нужны программе, так чтобы они вызывали необходимые нам функции из системы linux, что собственно и делает Wine. Но проект развивается очень медленно и разработчики не успевают реализовать все функции из системных библиотек Windows, поэтому работают далеко не все программы, особенно новые.
Популярные программы в Wine запускаются легко, и без дополнительных настроек. Но дело в том, что для решения популярных и востребованных задач в Linux есть достаточно альтернатив, а запускать нам придется специализированные программы и игры, требующие серьезных компонентов, еще не написанных в Wine. Вот тут и всплывает недоработанность этой программы. Но есть выход, его мы и рассмотрим дальше.
Основы использования Wine
Все файлы программ wine, установленные программы, библиотеки, файлы реестра, конфигурационные файлы находятся в домашнем каталоге, а точнее, в ~/.wine.
Поскольку для разных программ, понадобится разная архитектура библиотек и нужно будет подменять на оригинальные библиотеки от windows разные файлы была придумана такая возможность, как префиксы.
Папка ~/.wine это префикс, но мы можем создавать для каждой новой программы свой префикс и она будет работать только с ним. Чтобы задать префикс, с которым нужно работать wine используется переменная окружения WINEPREFIX, например:
export WINEPREFIX=~/program
Для разных программ может потребоваться различная архитектура системы, wine может запускать и 64 битные программы, но многим для правильной работы нужна архитектура х86.
Чтобы задать архитектуру используйте переменную WINEARCH. Например, для х86:
export WINEARCH=win32
Также не создавайте папку для нового префикса с помощью mkdir или файлового менеджера, пусть программа сама создаст эту папку при своем первом запуске.
Прослойка совместимости Wine поддерживает далеко не все программы, чтобы проверить поддерживается ли программа Wine вы можете воспользоваться сайтом appdb.winehq.org здесь есть поиск и перечислены все поддерживаемые и не очень программы для Linux.
Запуск exe программ в Linux с помощью wine
Первым делом, надо посмотреть страницу программы на сайте appdb.winehq.com. Здесь есть поиск, поэтому вы можете попытаться искать нужную программу. Например, я хочу установить довольно популярную программу Notepad++. Cначала надо посмотреть поддерживается ли она Wine. Для этого на сайте есть поиск:
На странице программы есть версия Wine, с которой она была протестирована, версия тестируемой программы, а также оценка. Оценка может быть Platinum, Gold, Silver или ниже, она зависит от того насколько хорошо программа работает:
Как видите, программа тестировалась с версией wine 5.0 и работала довольно неплохо. К тому же на странице есть ссылка на загрузку программы, так как она бесплатна. Если при запуске программы возникают сложности, то на странице winehq обычно сообщается что надо сделать чтобы программу всё-таки запустить.
Если вам нужно запустить программу, полностью поддерживаемую Wine, например, проводник или notepad, достаточно выполнить:
$ wine /адрес/файла/программы.exe
Например, для программы Notepad++ надо выполнить:
wine ~/Загрузки/npp/notepad++.exe
Здесь я использую portable версию, её надо перед этим скачать и распаковать. Как видите, программа полностью работает:
Но как я уже говорил, нам придется запускать мало таких программ, большинство из них будут требовать функциональности, которая ещё не реализован в wine. Тогда нам придется заменить библиотеки Wine, на оригинальные библиотеки Windows.
Конечно, есть оболочки для Wine, которые автоматизируют этот процесс, например, Crossover, PlayOnLinux, Lutris и другие. Но мы рассмотрим ручной вариант.
Для установки компонентов Windows в wine существует специальный инструмент — winetricks. Устанавливать его лучше из сайта программы, так версия будет новее:
wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
chmod +x winetricks
Чтобы установить нужный компонент достаточно передать имя этого компонента:
$ winetricks имя_компонента
С установкой компонентов более-менее понятно, но как узнать какие компоненты нужны? Скорее всего, вашу программу уже пытались устанавливать и другие пользователи нашли решение проблемы. Поэтому воспользуйтесь поиском Google для того, чтобы найти способы установки программы. Также очень полезным будет сайт appdb.winehq.org.
Давайте рассмотрим пример. Наберите в поиске по appdb.winehq.com программу Internet Explorer 8, это последняя версия программы, которую можно установить в Linux. Как видите, здесь бронза, значит программа поддерживается:
На её странице сообщается, что программа работает, но для её работы надо установить компонент msxml и urlmon:
winetricks msxml6 urlmon
После установки этих пакетов программа надо добавить ключ в реестр, который описан на странице winehq. После этого установщик запуститься и установит программу.
wine ~/Загрузки/iexplorer.exe
После установки вы можете её запустить:
Выглядит всё не очень, но зато работает. Инструкции не обязательно искать только на winehq, это могут быть различные форумы, блоги и так далее.
Остается вопрос, что же делать, если инструкций нет, информации минимум, а нужно чтобы программа работала. Мы можем анализировать вывод Wine при запуске программы. Причем нас будут интересовать не все сообщения из лога программы, а только последние, именно то что вызвало ошибку. Например если программа вывела:
fixme:richedit:ITextRange_fnEndOf (0xa04410)->(6 0 (nil)): stub
fixme:richedit:ITextRange_fnEndOf (0xa04410)->(6 0 (nil)): stub
fixme:richedit:ITextRange_fnEndOf (0xa04410)->(6 0 (nil)): stub
Осталось понять, что такое richedit, и Microsoft TechNet нам любезно сообщает что это их API и состоит оно из Riched32.dll, это последняя версия, но раньше это была riched20.dll, уже понимаете какие библиотеки нужны?
Их можно установить с помощью winetricks, но это делать необязательно, можно и вручную. Скачайте библиотеки, найти их не составит труда с помощью Google. Только ищите версию для Windows XP.
Копируем библиотеку в наш префикс, в папку system32:
cp ~/Загрузки/riched32.dll ~/program/drive_c/windows/system32/
cp ~/Загрузки/riched20.dll ~/program/drive_c/windows/system32/
Для 64 битных библиотек используется папка syswow64, а поскольку мы указали архитектуру 32 бит нужно и библиотеки использовать соответствующие. Затем запустите winecfg и на вкладке библиотеки, в поле новое замещение для библиотеки наберите *riched32, затем добавить и *riched20 и опять добавить:
Все, теперь можете пробовать запускать программу. Если программа снова падает с ошибкой, смотрите дальше логи и ищите библиотеки, которых ей не хватает.
Таким образом, вы можете заменить много библиотек Wine. Можно запустить практически любую программу, написанную несколько лет назад и не требующую сверх новых технологий. Достаточно только заменить нужные библиотеки. Вы можете не только использовать winetricks или копировать библиотеки из интернета, но и брать их прямо из Windows. Точно не стоит заменять gdi32.dll, kernel32.dll, и user32.dll — эти библиотеки реализуют функции ядра Windows на самом низком уровне, и если их заменить, это только нарушит работу Wine. Наверное, есть и другие библиотеки, которые нельзя заменять, но это вычисляется только путем экспериментов.
Вариант, который мы рассмотрели выше слишком сложный и не очень то подходит для новичков. Специально для таких ситуаций были придуманы различные программные решения вроде PlayOnLinux или CrossOver. Это оболочки над wine, которые уже знают какие библиотеки надо ставить для той или иной программы. Вы просто выбираете программу, выбираете установщик, а дальше программа сделает всё за вас сама.
Утилита Crossover поддерживает множество программ и работают они довольно неплохо, но единственный минус этой программы в том, что она платная. Программа PlayOnLinux бесплатная, но поддерживает намного меньше программ.
Запуск Windows программ в виртуальной машине
Если ни один из перечисленных выше способов вам не помог, осталось только последнее решение. Оно поможет, при условии, что у вас мощный компьютер. Вы можете установить виртуальную машину VirtualBox, затем установить туда Windows и уже там запускать вашу программу. Можно пойти ещё дальше и сделать из старого компьютера сервер, на котором будет запущена Windows, к которой вы сможете подключаться по VNC или RDP и делать там всё, что угодно. Это не совсем способы запуска exe в Linux, однако это решение будет работать почти всегда, где не будет работать wine.
Выводы
Теперь вы знаете как запустить exe на Linux. Не пренебрегайте инструментами упрощения установки вроде PlayOnLinux. Они очень сильно экономят ваше время, так как имеют уже готовые профили для многих программ. Экспериментируйте и пусть ваши программы работают без ошибок!
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Wine — это свободное программное обеспечение для запуска Windows-приложений на нескольких POSIX-совместимых операционных системах, включая Linux, macOS и BSD.
Если вы любите Linux, то наверняка когда-то запускали Wine. Возможно, для какой-то «важной» программы Windows, у которой нет аналога под Линуксом, или поиграться. Забавный факт: даже Steam Deck от Valve запускает игры через оболочку на основе Wine (она называется Proton).
За последний год я намучился с отладчиком, который позволяет одновременно дебажить и Wine, и Windows-приложение в нём. Разобраться во кишочках Wine оказалось очень интересно! Я-то раньше много им пользовался, но никогда не понимал механику целиком. Можно взять файл Windows — и просто запустить его в Linux без каких-либо изменений. Если вы хотите знать, как это сделано, добро пожаловать под кат.
Дисклеймер. В статье реальность сильно упрощается, а многие детали игнорируются. Текст даёт общее представление, как работает Wine.
© «Время приключений» (1 сезон, 18 серия) — прим. пер.
Wine — не эмулятор!
Прежде чем разбираться в работе Wine, нужно сказать, чем он НЕ является. Вообще, W.I.N.E. — это рекурсивный акроним, который расшифровывается как «Wine Is Not an Emulator». Почему? Потому что есть куча отличных эмуляторов и для старых архитектур, и для современных консолей, а Wine принципиально реализован по-другому. Давайте вкратце рассмотрим, как вообще работают эмуляторы.
Представьте простую игровую приставку, которая понимает две инструкции:
push <value>
— пушит заданное значение в стекsetpxl
— достаёт три значения из стека и рисует пиксель с цветомarg1
в точке(arg2, arg3)
(вполне достаточно для визуализации классных демок, верно?)
> dump-instructions game.rom
...
# рисуем красную точку по координатам (10,10)
push 10
push 10
push 0xFF0000
setpxl
# рисуем зелёную точку по координатам (15,15)
push 15
push 15
push 0x00FF00
setpxl
Бинарный файл игры (или картридж ROM) представляет собой последовательность таких инструкций, которые аппаратное обеспечение может загрузить в память и выполнить. Нативное железо выполняет их в натуральном режиме, но как запустить старый картридж на современном ноуте? Для этого делаем эмулятор — программу, которая загружает ROM из картриджа в оперативную память и выполняет его инструкции. Это интерпретатор или виртуальная машина, если хотите. Реализация эмулятора для нашей приставки с двумя инструкциями будет довольно простой:
enum Opcode {
Push(i32),
SetPixel,
};
let program: Vec<Opcode> = read_program("game.rom");
let mut window = create_new_window(160, 144); // Виртуальный дисплей 160x144 пикселей
let mut stack = Vec::new(); // Стек для передачи аргументов
for opcode in program {
match opcode {
Opcode::Push(value) => {
stack.push(value);
}
Opcode::SetPixel => {
let color = stack.pop();
let x = stack.pop();
let y = stack.pop();
window.set_pixel(x, y, color);
}
}
}
Настоящие эмуляторы намного сложнее, но основная идея та же: поддерживать некоторый контекст (память, регистры и т.д.), обрабатывать ввод (клавиатура/мышь) и вывод (например, рисование в каком-то окне), разбирать входные данные (ROM) и выполнять инструкции одну за другой.
Разработчики Wine могли пойти по этому пути. Но есть две причины, почему они так не поступили. Во-первых, эмуляторы и виртуальные машины тормозные по своей сути — там огромный оверхед на программное выполнение каждой инструкции. Это нормально для старого железа, но не для современных программ (тем более видеоигр, которые требовательны к производительности). Во-вторых, в этом нет необходимости! Linux/macOS вполне способны запускать двоичные файлы Windows нативно, их нужно только немного подтолкнуть…
Давайте скомпилируем простую программу для Linux и Windows и сравним результат:
int foo(int x) {
return x * x;
}
int main(int argc) {
int code = foo(argc);
return code;
}
Слева — Linux, справа — Windows
Результаты заметно отличаются, но набор инструкций фактически один и тот же: push
, pop
, mov
, add
, sub
, imul
, ret
.
Если бы у нас был «эмулятор», который понимает эти инструкции, то смог бы выполнить обе программы. И такой «эмулятор» существует — это наш CPU.
Как Linux запускает бинарники
Прежде чем запускать чужеродный двоичный файл, давайте разберёмся, как запускается под Linux родной бинарник.
❯ cat app.cc
#include <stdio.h>
int main() {
printf("Hello!\n");
return 0;
}
❯ clang app.cc -o app
❯ ./app
Hello! # работает!
Довольно просто, но давайте копнём глубже. Если сделать .app
?
❯ ldd app
linux-vdso.so.1 (0x00007ffddc586000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f743fcdc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f743fed3000)
❯ readelf -l app
Elf file type is DYN (Position-Independent Executable file)
Entry point 0x1050
There are 13 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000002d8 0x00000000000002d8 R 0x8
INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
...
Самое главное, что .app
— это динамически исполняемый файл. Он зависит от некоторых динамических библиотек и требует их присутствия в рантайме. Иначе не запустится. Другой интересный момент — запрос интерпретатора (requesting program interpreter
в последней строке листинга). Какой ещё интерпретатор? Я думал, что C++ — компилируемый язык, в отличие от Python…
В данном контексте интерпретатор — это «динамический загрузчик». Специальный инструмент, которая запускает исходную программу: разрешает и загружает её зависимости, а затем передаёт ей управление.
❯ ./app
Hello! # Работает!
❯ /lib64/ld-linux-x86-64.so.2 ./app
Hello! # Тоже работает!
# Домашнее задание: запустите это и попробуйте понять смысл выдачи.
❯ LD_DEBUG=all /lib64/ld-linux-x86-64.so.2 ./app
При запуске исполняемого файла ядро Linux определяет, что файл динамический и требует загрузчика. Затем оно запускает загрузчик, который выполняет всю работу. Это можно проверить, если запустить программу под отладчиком:
❯ lldb ./app
(lldb) target create "./app"
Current executable set to '/home/werat/src/cpp/app' (x86_64).
(lldb) process launch --stop-at-entry
Process 351228 stopped
* thread #1, name = 'app', stop reason = signal SIGSTOP
frame #0: 0x00007ffff7fcd050 ld-2.33.so`_start
ld-2.33.so`_start:
0x7ffff7fcd050 <+0>: movq %rsp, %rdi
0x7ffff7fcd053 <+3>: callq 0x7ffff7fcdd70 ; _dl_start at rtld.c:503:1
ld-2.33.so`_dl_start_user:
0x7ffff7fcd058 <+0>: movq %rax, %r12
0x7ffff7fcd05b <+3>: movl 0x2ec57(%rip), %eax ; _dl_skip_args
Process 351228 launched: '/home/werat/src/cpp/app' (x86_64)
Мы видим, что первая выполненная инструкция находится в библиотеке ld-2.33.so
, а не в бинарнике .app
.
Подводя итог, запуска динамически связанного исполняемого файла в Linux выглядит примерно так:
- Ядро загружает образ (≈ двоичный файл) и видит, что это динамический исполняемый файл
- Ядро загружает динамический загрузчик (
ld.so
) и передаёт ему управление - Динамический загрузчик разрешает зависимости и загружает их
- Динамический загрузчик возвращает управление исходному двоичному файлу
- Оригинальный двоичный файл начинает выполнение в
_start()
и в конечном итоге доходит доmain()
Понятно, почему исполняемый файл Windows не запускается в Linux — у него другой формат. Ядро просто не знает, что с ним делать:
❯ ./HalfLife4.exe
-bash: HalfLife4.exe: cannot execute binary file: Exec format error
Однако если пропустить шаги с первого по четвёртый и каким-то образом перескочить на пятый, то теоретически должно сработать, верно? Ведь с точки зрения операционной системы что значит «запустить» бинарный файл?
В каждом исполняемом файле есть раздел .text
со списком сериализованных инструкций CPU:
❯ objdump -drS app
app: file format elf64-x86-64
...
Disassembly of section .text:
0000000000001050 <_start>:
1050: 31 ed xor %ebp,%ebp
1052: 49 89 d1 mov %rdx,%r9
1055: 5e pop %rsi
1056: 48 89 e2 mov %rsp,%rdx
1059: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
105d: 50 push %rax
105e: 54 push %rsp
105f: 4c 8d 05 6a 01 00 00 lea 0x16a(%rip),%r8 # 11d0 <__libc_csu_fini>
1066: 48 8d 0d 03 01 00 00 lea 0x103(%rip),%rcx # 1170 <__libc_csu_init>
106d: 48 8d 3d cc 00 00 00 lea 0xcc(%rip),%rdi # 1140 <main>
1074: ff 15 4e 2f 00 00 call *0x2f4e(%rip) # 3fc8 <__libc_start_main@GLIBC_2.2.5>
107a: f4 hlt
107b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
...
Чтобы «запустить» бинарный файл, ОС загружает его в память (в частности, раздел .text
), устанавливает указатель текущей инструкции на адрес, где находится код, и всё — исполняемый файл типа «запущен». Как сделать это для исполняемых файлов Windows?
Легко! Просто возьмём код из исполняемого файла Windows, загрузим в память, направим %rip
в нужное место — и CPU с радостью выполнит этот код! Если архитектура процессора одинаковая, то процессору вообще без разницы, откуда выполнять ассемблерные инструкции.
Hello, Wine!
По сути, Wine — это «динамический загрузчик» для исполняемых файлов Windows. Это родной двоичный файл Linux, поэтому может нормально запускаться, и он знает, как работать с EXE и DLL. То есть своего рода эквивалент ld-linux-x86-64.so.2
:
# запуск бинарника ELF
❯ /lib64/ld-linux-x86-64.so.2 ./app
# запуск бинарника PE
❯ wine64 HalfLife4.exe
Здесь wine64
загружает исполняемый файл Windows в память, анализирует его, выясняет зависимости, определяет, где находится исполняемый код (т. е. раздел .text
), и переходит в этот код.
Примечание. В действительности он переходит к чему-то вроде
ntdll.dll!RtlUserThreadStart()
, это точка входа в «пространство пользователя» в мире Windows. Потом вmainCRTStartup()
(эквивалент_start
), и в самmain()
.
На данный момент наша Linux-система выполняет код, изначально скомпилированный для Windows, и всё вроде бы работает. За исключением системных вызовов.
Системные вызовы
Системные вызовы (syscall) — вот где основные сложности. Это вызовы к функциям, которая реализованы не в бинарнике или динамических библиотеках, а в родной ОС. Набор системных вызовов представляет системный API операционной системы. В нашем случае это Windows API.
Примеры системных вызовов в Linux: read
, write
, open
, brk
, getpid
Примеры в Windows: NtReadFile
, NtCreateProcess
, NtCreateMutant
😱
Системные вызовы не являются обычными вызовами функций в коде. Открытие файла, например, должно выполняться самим ядром, поскольку именно оно следит за файловыми дескрипторами. Поэтому приложению нужен способ как бы «прервать своё выполнение» и передать управление ядру (эта операция обычно называется переключением контекста).
Набор системных функций и способы их вызова в каждой ОС разные. Например, в Linux для вызова функции read()
наш бинарник записывает в регистр %rdi
дескриптор файла, в регистр %rsi
— указатель буфера, а в %rdx
— количество байт для чтения. Однако в ядре Windows нет функции read()
! Ни один из аргументов не имеет там смысла. Бинарник Windows использует свой способ выполнения системных вызовов, который не сработает в Linux. Не будем здесь углубляться детали системных вызовов, например, вот отличная статья о реализации в Linux.
Скомпилируем ещё одну небольшую программу и сравним сгенерированный код в Linux и Windows:
#include <stdio.h>
int main() {
printf("Hello!\n");
return 0;
}
Слева — Linux, справа — Windows
На этот раз мы вызываем функцию из стандартной библиотеки, которая в конечном итоге выполняет системный вызов. На скриншоте выше версия Linux вызывает puts
, а версия Windows — printf
. Эти функции из стандартных библиотек (libc.so
в Linux, ucrtbase.dll
в Windows) для упрощения взаимодействия с ядром. Под Linux сейчас частенько собирают статически связанные бинарники, не зависимые от динамических библиотек. В этом случае реализация puts
встроена в двоичный файл, так что libc.so
не задействуется в рантайме.
Под Windows до недавнего времени «системные вызовы bcgjkmpjdfkb только вредоносные программы»[нет источника] (вероятно, это шутка автора — прим. пер.). Обычные приложения всегда зависят от kernel32.dll/kernelbase.dll/ntdll.dll
, где скрывается низкоуровневая магия тайного общения с ядром. Приложение просто вызывает функцию, а библиотеки заботятся об остальном:
источник
В этом месте вы наверное поняли, что будет дальше. 😏
Трансляция системных вызовов в рантайме
А что, если «перехватывать» системные вызовы во время выполнения программы? Например, когда приложение вызывает NtWriteFile()
, мы берём управление на себя, вызываем write()
, а потом возвращаем результат в ожидаемом формате — и возвращаем управление. Должно сработать. Быстрое решение в лоб для примера выше:
// HelloWorld.exe
lea rcx, OFFSET FLAT:`string'
call printf
↓↓
// «Фальшивый» ucrtbase.dll
mov edi, rcx // Преобразование аргументов в Linux ABI
call puts@PLT // Вызов реальной реализации Linux
↓↓
// Real libc.so
mov rdi, <stdout> // запись в STDOUT
mov rsi, edi // указатель на "Hello"
mov rdx, 5 // сколько символов писать
syscall
По идее, можно сделать собственную версию ucrtbase.dll
со специальной реализацией printf
. Вместо обращения к ядру Windows она будет следовать формату интерфейсов Linux ABI и вызывать функцию write
из библиотеки libc.so
. Однако на практике мы не можем изменять код этой библиотеки по ряду причин — это муторно и сложно, нарушает DRM, приложение может статически ссылаться на ucrtbase.dll
и т. д.
Поэтому вместо редактирования бинарника мы внедримся в промежуток между исполняемым файлом и ядром, а именно в ntdll.dll
. Это «ворота» в ядро, и Wine действительно предоставляет собственную реализацию. В последних версиях Wine решение состоит из двух частей: ntdll.dll
(библиотека PE) и ntdll.so
(библиотека ELF). Первая часть — это тоненькая прокладка, которая просто перенаправляет вызовы в ELF-аналог. А уже он содержит специальную функцию __wine_syscall_dispatcher
, которая выполняет магию преобразования текущего стека из Windows в Linux и обратно.
Поэтому в Wine системный вызов выглядит следующим образом:
Диспетчер системных вызовов — это мост между мирами Windows и Linux. Он заботится о соглашениях и стандартах для системных вызовов: выделяет пространство стека, перемещает регистры и т. д. Когда выполнение переходит к библиотеке Linux (ntdll.so
), мы можем свободно использовать любые нормальные интерфейсы Linux (например, libc
или syscall
), реально читать/записывать файлы, занимать/отпускать мьютексы и так далее.
И это всё?
Звучит почти слишком просто. Но так и есть. Во-первых, под Windows много разных API. Они плохо документированы и имеют известные (и неизвестные, ха-ха) ошибки, которые следует воспроизвести в точности. (Вспомните, как при разработке Windows 95 туда скопировали утечку памяти из SimCity, чтобы популярная игра не крашилась в новой ОС. Возможно, такие специфические вещи приходится воспроизводить под Linux для корректной работы конкретных программ — прим. пер.). Большая часть исходного кода Wine — это реализация различных Windows DLL.
Во-вторых, системные вызовы можно выполнять по-разному. Технически ничто не мешает Windows-приложению выполнить прямой системный вызов через syscall
, и в идеале это тоже должно работать (как мы уже говорили, Windows-игры делают всякие безумные вещи). В ядре Linux специальный механизм для обработки таких ситуаций, который, конечно, добавляет сложности.
В-третьих, весь этот бардак 32 vs 64 бит. Есть много старых 32-битных игр, которые никогда не перепишут на 64 бита. В Wine есть поддержка обеих платформ. И это тоже плюс к общей сложности.
В-четвертых, мы даже не упомянули wine-server
— отдельный процесс Wine, который поддерживает «состояние» ядра (открытые дескрипторы файлов, мьютексы и т. д.).
И последнее… о, так вы хотите запустить игру? А не просто hello world? Ну так это совсем другое дело! Тогда нужно разобраться с DirectX, со звуком (привет, PulseAudio, старый друг), устройствами ввода (геймпады, джойстики) и т. д. Куча работы!
Wine разрабатывался в течение многих лет и прошёл долгий путь. Сегодня вы без проблем запускаете под Linux самые последние игры, такие как Cyberpunk 2077 или Elden Ring. Чёрт возьми, иногда производительность Wine даже выше, чем у Windows! В какое замечательное время мы живём…
P. S. На всякий случай повторим дисклеймер: статья даёт только базовое представление о работе Wine. Многие детали упрощены или опущены. Так что не судите очень строго, пожалуйста.
Содержание
- Шаг 1: Установка Wine
- Шаг 2: Первый запуск и настройка Wine
- Шаг 3: Запуск EXE-файлов через Wine
- Вопросы и ответы
Шаг 1: Установка Wine
Запуск EXE-файлов в Linux — задача несложная, однако небольшие трудности заключаются в поиске инструментов, позволяющих справиться с этим. Популярной программой является Wine, и ее аналогов почти нет, а существующие неизвестны практически никому. Поэтому в сегодняшней статье мы поговорим именно об этом решении. Начать стоит с его добавления в дистрибутив, поскольку по умолчанию Wine отсутствует в любой сборке ОС, основанной на Linux.
Способ 1: Менеджер приложений
Существует несколько доступных вариантов инсталляции Wine. Первый подразумевает использование менеджера приложений, который встроен в популярные дистрибутивы, основанные на Debian или RedHat. В первую очередь рассмотрим именно этот вариант, а осуществляется поставленная цель так:
- Откройте основное меню, кликнув по соответствующей кнопке, и запустите оттуда «Менеджер приложений».
- Отыщите кнопку поиска, чтобы открыть строку для ввода названия программы.
- Напишите
Wine
и опуститесь вниз по списку, чтобы найти подходящий вариант. - На странице программного обеспечения вас интересует кнопка «Установить».
- Для начала этой процедуры придется подтвердить подлинность учетной записи, введя пароль.
- Ожидайте завершения инсталляции. Данная операция займет несколько минут, поскольку Wine является объемным приложением.
- После нажмите на кнопку «Запустить», чтобы выполнить предварительную конфигурацию.
Сейчас давайте приступим к рассмотрению альтернативного варианта инсталляции, если этот вам не подходит, а о предварительной настройке установленного инструмента поговорим в отдельном шаге данного материала.
Способ 2: Официальные репозитории
Как известно, программы в «Менеджере приложений» находятся в официальных репозиториях, а принцип их установки основан на терминальных командах. Именно их и следует задействовать в тех случаях, когда нет возможности открыть решение с GUI или оно попросту отсутствует в используемом дистрибутиве. Не переживайте, управление консолью не является чем-то сложным, в чем и удостоверимся далее.
- Запустите «Терминал» удобным для вас образом, например, через меню приложений или горячую клавишу Ctrl + Alt + T.
- В появившейся строке введите
sudo apt install wine-stable
. Если вы используете дистрибутив, основанный, например, на RedHat, следует заменить пакетный менеджер APT на установленный в текущей сборке. Это может быть, например, YUM или Pacman. - Подтвердите действие, написав пароль суперпользователя. Учитывайте, что символы, вводимые таким образом, никогда не отображаются в консоли, однако существуют и исключения. В некоторых дистрибутивах при указании символов в строке появляются звездочки.
- Вы будете уведомлены об увеличении количества занятого пространства. Подтвердите это сообщение, выбрав вариант Д.
- Ожидайте окончания инсталляции. Во время этого не закрывайте «Терминал», иначе весь процесс будет сброшен.
На этом инсталляция завершена. Имеются еще и другие альтернативные методы добавления Wine в операционную систему, но их детальный разбор сейчас не имеет смысла, поэтому перемещаемся к следующему этапу.
Шаг 2: Первый запуск и настройка Wine
К счастью, большинство параметров рассматриваемой программы уже настроены автоматически, а недостающие компоненты так же самостоятельно загружаются. Однако юзеру все-таки придется выполнить несколько действий перед переходом к запуску EXE-файлов.
- Запустите софт, например, через «Менеджер приложений» или введя его название в консоли.
- Дождитесь завершения обновления конфигурации. Во время этого на экране будут появляться сообщения о надобности инсталляции дополнительных компонентов, включая .NET Framework и Gecko.
- После этого отобразится графическое меню с пользовательской конфигурацией. Здесь присутствуют детальные описания каждого пункта на русском языке, поэтому мы предлагаем разобраться с этим самостоятельно. Связано это и с тем, что все параметры устанавливаются по желанию пользователей.
На этом процедура конфигурации успешно завершена, а значит, можно переходить к непосредственному запуску имеющихся EXE-файлов.
Шаг 3: Запуск EXE-файлов через Wine
Перед началом выполнения поставленной задачи хотим отметить, что не стоит рассматривать Wine как полноценное средство работы с программами для Windows. Конечно, он является эмулятором, но потребление системных ресурсов при запуске софта поднимается в несколько раз, а также могут отсутствовать какие-либо опции, изначально работающие в Windows. Далее мы расскажем о более подходящих решениях для использования ПО в Linux, а сейчас давайте все-таки разберемся с выполнением EXE-объектов.
- Откройте файловый менеджер и переместитесь к расположению необходимого файла.
- Щелкните по нему правой кнопкой мыши и в контекстном меню выберите пункт «Открыть в другом приложении».
- Появится отдельное окно «Выбрать приложение». Здесь вас интересует пункт «Wine — загрузчик Windows программ».
- Если это уже полноценный софт, он откроется в новом окне и им можно управлять. В случае взаимодействия с инсталлятором начните стандартную операцию установки.
- Дождитесь окончания этой операции. Она может занять много времени, поскольку процессор в большинстве ситуаций нагружается на максимум.
- После этого вы можете запустить программу через значок на рабочем столе, графический интерфейс Wine или меню приложений.
Как уже было сказано ранее, запуск EXE-файлов — не лучший способ взаимодействовать с программами в Linux. Сейчас многие разработчики создают версии, корректно функционирующие в разных дистрибутивах, однако часто их нет в официальных репозиториях, то есть скачать из менеджеров приложений такой софт не получится. Приходится скачивать отдельные DEB или RPM-пакеты либо же вообще вручную распаковывать архивы. Не потрудитесь отыскать сборку требуемого софта для вашего дистрибутива, а затем установите ее, используя инструкции из приведенной далее статьи.
Подробнее: Установка программ в Linux
Это было все, что мы хотели рассказать о запуске ПО для Windows в Linux. Как видно, лучшее решение всего одно, поэтому его и задействуют абсолютно все пользователи, желающие реализовать данную цель. Остается только следовать инструкциям, чтобы без каких-либо проблем открыть EXE-элемент и начать взаимодействие с ним.
Загрузить PDF
Загрузить PDF
Из этой статьи вы узнаете, как установить и запустить Wine на компьютере с Linux. Wine — это программа, которая позволяет запускать программы для Windows на компьютере под управлением другой (не Windows) операционной системы.
-
1
Откройте терминал. Выберите «Терминал» в системном меню или в списке установленных программ.
- В большинстве дистрибутивов Linux можно нажать Ctrl+Alt+T, чтобы открыть терминал.
- В некоторых дистрибутивах Linux строка терминала находится в верхней части экрана.
-
2
Активируйте 32-разрядную архитектуру. Если на компьютере установлен 64-разрядный процессор, активируйте 32-разрядный режим. Для этого:
- введите
sudo dpkg --add-architecture i386
в терминале и нажмите ↵ Enter; - введите пароль администратора и нажмите ↵ Enter.
- введите
-
3
Свяжите загрузчик компьютера с веб-сайтом Wine. Это позволит компьютеру найти правильные файлы для загрузки. Для этого:
- введите
wget -nc https://dl.winehq.org/wine-builds/Release.key
и нажмите ↵ Enter; - введите
sudo apt-key add Release.key
и нажмите ↵ Enter; - введите пароль администратора.
- введите
-
4
-
5
Обновите загруженные пакеты. Введите
sudo apt-get update
и нажмите ↵ Enter. -
6
Выберите загрузку. По состоянию на март 2018 года стабильную версию Wine можно загрузить, если ввести
sudo apt-get install --install-recommends winehq-stable
и нажать ↵ Enter.[1]
- Возможно, будущие версии Wine будут поддерживать несколько разных типов стабильной загрузки.
-
7
Подтвердите загрузку. Введите y и нажмите ↵ Enter, а затем введите пароль администратора (если будет предложено). Начнется загрузка и установка Wine на компьютере.
-
8
Подождите, пока Wine загрузится и установится. На это уйдет 10 минут.
Реклама
-
1
Создайте домашний каталог Windows. Введите
winecfg
, нажмите ↵ Enter, а затем найдите подтверждающее сообщение «created the configuration directory ‘home/name/.wine» (создан каталог конфигурации home/name/.wine).- Если вам предлагается установить какие-либо недостающие пакеты, нажмите «Установить» и дождитесь, когда пакеты установятся.
-
2
Выберите версию Windows. Откройте меню «Версия Windows» внизу окна «Конфигурация Wine», а затем выберите версию Windows (например, «Windows 7»), которую вы хотите использовать.
- Если данная опция неактивна, сначала нажмите на вкладку «Приложения» в верхней части окна.
-
3
Нажмите Применить. Эта кнопка находится в нижней части окна. Настройки будут сохранены.
-
4
Щелкните по OK. Эта кнопка находится в нижней части окна. Окно закроется.
-
5
Загрузите программу для Windows в формате EXE. Найдите EXE-файл нужной программы (например, 7-zip) и скачайте его. Теперь можно установить программу.
- На веб-сайте Wine можно просмотреть полный список программ, совместимых с Wine.
Реклама
-
1
Откройте папку «Downloads». Вы найдете ее в папке «Home». Также папку «Downloads» можно открыть из меню «Приложения».
-
2
Найдите загруженный EXE-файл. Для этого прокрутите содержимое папки «Downloads».
-
3
Щелкните по файлу правой кнопкой мыши. Откроется выпадающее меню.
-
4
Нажмите Открыть с помощью Wine. Эта опция находится в верхней части меню. Откроется окно установки.
-
5
Щелкните по Установить. Эта опция находится внизу окна установки. Запустится установка программы на компьютер.
- Чтобы установить некоторые программы, нужно ввести дополнительные данные.
- Чтобы изменить папку, в которую будет установлена программа, нажмите «⋯» в правой части окна, а затем выберите другую папку на компьютере.
-
6
Щелкните по Закрыть, когда появится запрос. Эта опция станет доступной, когда программа устновится.
-
7
Запустите программу. Сделайте это в разделе «Приложения» системного меню.
Реклама
Советы
- Также можно установить пользовательский интерфейс Wine под названием PlayOnLinux, который позволяет устанавливать, удалять и получать доступ к программам Wine. Для этого откройте терминал, когда установите Wine, введите
sudo apt install playonlinux
, введите пароль и подтвердите загрузку, введя y. - Регулярно проверяйте сайт Wine на наличие обновлений.
Реклама
Предупреждения
- Wine является довольно совершенной программой, но в ней, как правило, нельзя запустить игры и мощные программы с нормальной частотой кадров.
Реклама
Об этой статье
Эту страницу просматривали 76 746 раз.