Как открыть исполняемый файл в linux
Перейти к содержимому

Как открыть исполняемый файл в linux

  • автор:

Как установить и запустить EXE-файлы в среде Linux

Как установить и запустить EXE-файлы в среде Linux

Установка и запуск EXE-файлов в среде Linux иногда очень необходима. Есть несколько очень нужных приложений Windows, которые требуют установки в Linux и запуска exe-файла в Linux или Ubuntu OS. Я являюсь пользователем Ubuntu, ОС работает на ядре Linux, и мне интересно узнать: » может ли Linux запустить exe файл ?». Мне нужно, чтобы некоторые программы Windows иногда запускались на моем компьютере. Не всегда есть возможность переключить ОС для запуска конкретной программы Windows. Либо вам нужно загружать Windows с компьютера с двойной загрузкой, либо вам нужен отдельный ПК (на котором установлена ОС Windows). Лучше всего, если вам, так или иначе, удастся установить программное обеспечение Windows или exe-файлы и запустить его внутри Linux или Ubuntu OS .

Если вы новичок в Linux OS и мало что о ней знаете, то позвольте мне сначала дать определение Linux OS.

Linux OS — это операционная система с открытым исходным кодом, свободно распространяемая и кроссплатформенная операционная система, которая работает на базе Unix. Linux можно легко установить на ПК, ноутбук, мобильный телефон, планшет, компьютер, суперкомпьютер, игровую консоль (поддерживает конфигурации от low end до high end) и т.д. Более того, эта операционная система намного безопаснее и легче, чем другие популярные ОС, такие как Windows, Mac и так далее.

Linux в основном использует файловую систему ext4 ; формат файла полностью отличается от исполняемой файловой системы, т.е. .exe файла. Файлы EXE используются в ОС Windows. Поэтому, в принципе, трудно использовать exe-файл в архитектуре Linux. Но, используяразличных программ, таких как WineHQ, PlayOnLinux и т.д. в вашей операционной системе Linux, можно легко установить и запустить различные любимые программы Windows на Linux OS.

Как открыть, запустить или установить Exe файлы на Linux Ubuntu с помощью ‘Wine’

Знаете ли вы ответ на вопрос: «Может ли Linux запускать exe-файлы?». Чтобы запустить exe файлы в Linux вам нужно установить ‘Wine’ в Linux или Ubuntu. ‘Wine’ — это бесплатная программа с открытым исходным кодом на базе Linux, которая позволяет пользователям любой версии Linux (Ubuntu, Linux Mint) устанавливать и запускать приложения Windows. Wine очень полезна для программистов и разработчиков (с помощью программной библиотеки WineLib) для компиляции, модификации любых Windows-приложений в среде Unix.

Скачать и установить Wine:

Вам необходимо скачать определенную версию Wine с официального сайта WineHQ (https://www.winehq.org/). На странице загрузки вы получите все основные версии Wine для Linux. Выберите версию Linux (среди всех версий Linux, таких как Ubuntu, Red Hat и т.д.), которую вы используете, и скачайте программу Wine. Если вы не можете найти точную версию ОС, то попробуйте найти родственную версию из списка, которая является базовой (например, Debian является базовой версией Linux Mint). Соответствующая версия Wine должна работать на вашем компьютере с Linux. Щелкните на предпочтительной ссылке и нажмите на экранную инструкцию по установке. После загрузки программы Wine по ссылке, щелкните правой кнопкой мыши на значке программы, выберите установитьи выполните следующие шаги. После успешной установки приложения Wine оно создаст новую папку (.wine) в каталоге home/user-name (имя пользователя должно быть именем пользователя, указанным вами при создании профиля пользователя).
Первоначально, папка .wine будет невидима для вас, пока вы не нажмете кнопку Ctrl+H вместе, чтобы показать скрытые файлы. Затем откройте папку .wine и перейдите по пути ../.wine/drive_C/Program Files . Полный путь будет таким:

Это ваша папка program files , куда вы можете поместить приложения Windows и установить их в Linux. На следующем этапе вам нужно скачать файл .exe и переместить его в папку program files . Затем щелкните правой кнопкой мыши на этом файле и выберите опцию открыть с помощью . Выберите Wine windows program loader для установки и запуска Windows-приложения в Linux.

Пользователи Linux Ubuntu 10.04 и более поздних версий могут установить Wine на свою систему Linux прямо из «Ubuntu Software Center». Метод следующий:

Откройте Приложения и перейдите в Центр программного обеспечения.

В строке поиска введите ‘Wine’ и нажмите Enter для поиска.

Нажмите на кнопку Установить Wine, которую вы получите из списка поиска.

Он автоматически создаст виртуальный диск C:\ на вашей Ubuntu.

Теперь вы можете открывать .exe файлы и устанавливать их на виртуальный c:\ диск вашей Linux системы.

Пользователи более старых и других версий должны выполнить следующие шаги для добавления Wine в Linux:

Перейдите к Система » Администрирование » Источники программного обеспечения .

Выберите раздел Другое программное обеспечение и выберите кнопку Добавить .

Затем, чтобы установить программу Wine в Linux, добавьте в поле терминала следующую строку: ppa:ubuntu-wine/ppa

Альтернативно, вы можете использовать команду из терминала для установки add Wine:

Каждая версия Linux следует отдельной процедуре установки. Но существует общий метод установки программы Wine на любую ОС Linux. Для установки Wine необходимо выполнить команду в терминале Linux.

Для установки Wine в Linux необходимо иметь активное подключение к Интернету и права суперпользователя (root-доступ). Пользователь Ubuntu может использовать ярлык Alt+F2 , чтобы открыть окно запуска, введите » gnome-terminal » и нажмите Enter , чтобы открыть терминал. Введите su , чтобы изменить доступ на root-доступ. Вам будет предложено ввести пароль администратора или root, а затем выполнить команды.

Шаги по установке Wine на Linux Ubuntu:

Ubuntu является самой популярной версией среды Linux. Здесь я описываю шаги по установке Wine в Ubuntu 19.10. Для разных версий Ubuntu, указанная команда требует некоторых изменений, о которых я также подробно рассказываю ниже.

  • Нажмите и удерживайте Ctrl+Alt+T вместе, чтобы открыть окно Terminal в Ubuntu.
  • Введите следующую команду терминала для включения 32-битной поддержки. Пароль учетной записи является обязательным на этом шаге.
  • Чтобы добавить и установите ключ репозитория Wine , введите следующую команду для добавления поддержки:
  • Теперь выполните указанную команду для добавления репозитория Wine только в Ubuntu 19.10:
  • Используйте модифицированную команду для добавления репозитория Wine для Ubuntu 18. 04 и Linux Mint 19.x :
  • Используйте команду для добавления репозитория Wine в Ubuntu 16.04 и Linux Mint 18.x :
  • **libfaudio0** очень необходим для использования WineHQ и используйте следующую команду для его добавления.
  • Вот и все. Теперь ваша ОС Ubuntu готова к запуску файлов Windows/.exe файлов . Как запустить и установить Exe файл в Linux или Ubuntu:

Метод #1: В вышеприведенном разделе я уже описал процесс установки программы Windows на ОС Linux. Однако если этот метод не работает, вы можете использовать командный метод для открытия и запуска exe-файла. Команда должна быть примерно такой:

A L inux Mint Для этой же цели пользователь может использовать команду:

Примечание : Замените ‘app-setup-file-name’ на фактическое имя файла установки.
Перед этим измените расположение каталога на ту папку, в которой находится установочный файл. Например, если вы сохранили установочный файл exe на рабочем столе, то перед выполнением вышеуказанной команды вам нужно выполнить другую команду, т.е.

В противном случае, перейдя по пути Приложения » Wine » Программы ииз списка программ, вы можете запустить программу exe на вашем компьютере Linux.

Метод #2 (Альтернативный метод):

После выполнения вышеуказанных действий по установке WineHQ на ваш Linux ПК, вам необходимо перезагрузить компьютер и убедиться, что WineHQ правильно установлен на ваш ПК.

Теперь загрузите исполняемый файл Windows, т.е. .exe файл на ваш Linux компьютер.

Щелкните правой кнопкой мыши на файле и выберите опцию Wine Windows Program Loader из контекстного меню правой кнопки мыши. Если опция недоступна в контекстном меню правой кнопки мыши, попробуйте выбрать опцию Другое и найти там опцию Wine Windows Program Loader.

Wine может запросить установку Wine Gecko и Wine Mono инсталляторов. Установите их соответствующим образом.

Теперь вы готовы пройти через мастер установки программ Windows.

Завершите процесс установки Windows .exe файла/программного обеспечения и запустите его на вашей ОС Linux.

Примечание: Wine создает среду для установки и запуска приложений windows в Linux . Но иногда Wine не может запустить некоторые приложения. В этом случае вы можете попробовать использовать PlayOnLinux для запуска этих программ.

Установка Windows-приложений в Linux Ubuntu с помощью ‘PlayOnLinux’

Как и ‘Wine’, PlayOnLinux обеспечивает уровень совместимости, который позволяет пользователям Linux устанавливать программы и exe-файлы на базе Windows. Новичок в Linuxпользователь сталкивается с проблемами при установке Wine. Однако PlayOnLinux очень легко установить. Она обладает идентичной функциональностью, как и Wine. Кроме того, программа поддерживает широкий спектр приложений. Вы можете назвать его графическим фронт-энд инструментом Wine, который обеспечивает очень простое решение для установки Windows OS.

PlayOnLinux поддерживает популярные приложения Windows, такие как Adobe Photoshop, браузер Safari, MS Office и т.д. Компания исправляет все ошибки и предоставляет пользователям плавный опыт работы с программами, приложениями и .exe файлами установки Windows. Он также поддерживает современные игры и патчи.

Вы можете скачать PlayOnLinux по следующей ссылке:

Для установки программы используйте следующие пошаговые команды:

Любитель игр может воспользоваться помощью Lutris, чтобы поиграть в простую и стратегическую игру на ПК с Linux. Для установки Lutris используйте следующую команду:

В этом руководстве я описал как установить и запустить exe файлы (исполняемые файлы Windows) на компьютере Linux (Ubuntu или Linux Mint PC). На данный момент Wine является единственной программой, которая позволяет устанавливать программы Windows на Linux. Однако PlayOnLinux — это современная альтернатива, которая поможет вам установить .exe в Linux , чтобы вы могли запускать ваши любимые Windows-приложения на вашей Linux OS.

Также полезно: Как играть в Candy Crush Sega на Windows PC

YouTube видео: Как установить и запустить EXE-файлы в среде Linux

Вопросы и ответы по теме: “Как установить и запустить EXE-файлы в среде Linux”

Как запустить файл EXE в Linux?

Для этого достаточно установить VirtualBox, KVM или VMWare, создать новую виртуальную машину и установить на ней Windows. Затем вы можете просто запустить виртуальную машину и запустить Windows внутри вашей ОС на базе Linux.Сохраненная копия

Как запустить .EXE файл в Ubuntu Wine?

Для запуска Windows приложений в Linux обычно достаточно дважды кликнуть по ним. Но может быть так, что .exe файл будет открываться менеджером архивов или другим приложением (обычно менеджером архивов). В этом случае кликните по файлу правой кнопкой мыши, выберите пункт «Открыть с помощью» и выберите Wine.

Как запустить EXE в Wine?

Во многих дистрибутивах Wine установлен «из коробки» — достаточно выполнить двойной щелчок на файле с расширением .exe, и, вполне вероятно, все заработает.

Как запустить EXE файл?

В Windows Exe объект открыть можно с помощью стандартного установщика или утилиты 7Zip. Для запуска файла достаточно дважды кликнуть по нему мышкой или запустить объект через меню архиватора. Для запуска в MacOS следует установить эмулятор ОС Windows и в нем открыть файл Exe.

Как запустить EXE файл в ALT Linux?

Re: как запустить EXE файлОткройте терминал и введите su -, после чего нажмите Enter, введите пароль суперпользователя (он не показывается) и нажмите Enter.

unixforum.org

Запуск программ в Linux (Помогите уж новичку. )

Модератор: Bizdelnick

Запуск программ в Linux

Сообщение Tenk » 13.10.2007 15:25

Re: Запуск программ в Linux

Re: Запуск программ в Linux

Re: Запуск программ в Linux

Ярлык — это как? Просветите

Re: Запуск программ в Linux

В контекстном меню рабочего стола выбираем создать, потом файл, потом ссылку на приложение. А там, думаю, разберешься.

Или Главное_меню/выполнить_программу. Тут уже нужно знать, что запускаем.

как открыть исполняемый файл в linux

kak zapustit exe v

Запуск EXE-файлов в Linux — задача несложная, однако небольшие трудности заключаются в поиске инструментов, позволяющих справиться с этим. Популярной программой является Wine, и ее аналогов почти нет, а существующие неизвестны практически никому. Поэтому в сегодняшней статье мы поговорим именно об этом решении. Начать стоит с его добавления в дистрибутив, поскольку по умолчанию Wine отсутствует в любой сборке ОС, основанной на Linux.

Способ 1: Менеджер приложений

Существует несколько доступных вариантов инсталляции Wine. Первый подразумевает использование менеджера приложений, который встроен в популярные дистрибутивы, основанные на Debian или RedHat. В первую очередь рассмотрим именно этот вариант, а осуществляется поставленная цель так:

otkrytie menedzhera prilozhenij dlya ustanovki wine v

perehod k poisku prilozheniya wine v linux dlya dalnejshej ustanovki

uspeshnoe nahozhdenie prilozheniya wine v linux dlya dalnejshej ustanovki

knopka dlya nachala ustanovki na stranicze prilozheniya wine v

podtverzhdenie nachala ustanovki wine v linux cherez menedzher prilozhenij

ozhidanie zaversheniya installyaczii prilozheniya wine v linux cherez menedzhe prilozhenij

otkrytie programmy wine v linux posle ustanovki cherez menedzher prilozhenij

Сейчас давайте приступим к рассмотрению альтернативного варианта инсталляции, если этот вам не подходит, а о предварительной настройке установленного инструмента поговорим в отдельном шаге данного материала.

Способ 2: Официальные репозитории

Как известно, программы в «Менеджере приложений» находятся в официальных репозиториях, а принцип их установки основан на терминальных командах. Именно их и следует задействовать в тех случаях, когда нет возможности открыть решение с GUI или оно попросту отсутствует в используемом дистрибутиве. Не переживайте, управление консолью не является чем-то сложным, в чем и удостоверимся далее.

zapusk terminala dlya ustanovki wine v linux cherez oficzialnye repozitorii

vvod komandy dlya ustanovki wine v linux cherez oficzialnye repozitorii

podtverzhdenie ustanovki wine v linux cherez oficzialnye repozitorii

odobrenie uvedomleniya o zanyatom prostranstve pri ustanovke wine v

ozhidanie zaversheniya ustanovki programmy wine v linux cherez terminal

На этом инсталляция завершена. Имеются еще и другие альтернативные методы добавления Wine в операционную систему, но их детальный разбор сейчас не имеет смысла, поэтому перемещаемся к следующему этапу.

Шаг 2: Первый запуск и настройка Wine

К счастью, большинство параметров рассматриваемой программы уже настроены автоматически, а недостающие компоненты так же самостоятельно загружаются. Однако юзеру все-таки придется выполнить несколько действий перед переходом к запуску EXE-файлов.

zapusk programmy wine v linux posle ustanovki cherez terminal

podgotovka programmy wine v linux dlya funkczionirovaniya

polzovatelskaya nastrojka programmy wine v linux posle ustanovki cherez terminal

На этом процедура конфигурации успешно завершена, а значит, можно переходить к непосредственному запуску имеющихся EXE-файлов.

Шаг 3: Запуск EXE-файлов через Wine

Перед началом выполнения поставленной задачи хотим отметить, что не стоит рассматривать Wine как полноценное средство работы с программами для Windows. Конечно, он является эмулятором, но потребление системных ресурсов при запуске софта поднимается в несколько раз, а также могут отсутствовать какие-либо опции, изначально работающие в Windows. Далее мы расскажем о более подходящих решениях для использования ПО в Linux, а сейчас давайте все-таки разберемся с выполнением EXE-объектов.

perehod k fajlu dlya ego dalnejshego zapuska wine v

perehod k vyboru prilozheniya dlya zapuska programmy cherez wine v

vybor programmy wine v linux v kachestve sredstva zapuska exe fajla

ustanovka exe fajla v wine v linux dlya dalnejshego zapuska

ozhidanie zaversheniya ustanovki programmy exe cherez wine v

zapusk ustanovlennoj cherez wine v linux programmy dlya ispolzovaniya

Как уже было сказано ранее, запуск EXE-файлов — не лучший способ взаимодействовать с программами в Linux. Сейчас многие разработчики создают версии, корректно функционирующие в разных дистрибутивах, однако часто их нет в официальных репозиториях, то есть скачать из менеджеров приложений такой софт не получится. Приходится скачивать отдельные DEB или RPM-пакеты либо же вообще вручную распаковывать архивы. Не потрудитесь отыскать сборку требуемого софта для вашего дистрибутива, а затем установите ее, используя инструкции из приведенной далее статьи.

Это было все, что мы хотели рассказать о запуске ПО для Windows в Linux. Как видно, лучшее решение всего одно, поэтому его и задействуют абсолютно все пользователи, желающие реализовать данную цель. Остается только следовать инструкциям, чтобы без каких-либо проблем открыть EXE-элемент и начать взаимодействие с ним.

Помимо этой статьи, на сайте еще 12375 инструкций.
Добавьте сайт Lumpics.ru в закладки (CTRL+D) и мы точно еще пригодимся вам.

Отблагодарите автора, поделитесь статьей в социальных сетях.

Как сделать файл исполняемым в Astra Linux и запустить его?

Друзья, приветствую! Продолжаем решать практические задачи на примере Astra Linux CE Орел. При скачивании игры (или какого либо полезного софта) мы иногда получаем файлы-сценарии, которые для запуска сначала нужно сделать исполняемыми.

В Windows мы привыкли, что файлы программ (или программы инсталляторы) уже являются исполняемыми. Определить это можно по их названию (setup, install) или расширению *.exe, *.com или *.bat.

В линуксе механизм другой. Возможность запуска файла определяется не расширением — а разрешением полномочий. Проще говоря, по умолчанию Linux «разрешает» только читать и копировать файл. А исполнять нет.

Устанавливается (или убирается) соответствующий флаг в свойствах файла и операционная система ведет себя соответственно.

В разрезе пользователей (и групп) можно выставить права на чтение, запись, исполнение конкретного файла. И тогда его можно будет запустить как программу. Такова идеология Linux.

Как сделать файл исполняем в Astra Linux через менеджер файлов?

Все это может показаться сложным, но на самом деле, все просто. В Linux Astra установлен дружественный графический интерфейс, есть встроенный графический менеджер — проводник.

И сделать нужный файл исполняемым у Вас получится легко, быстро, привычно. Для примера скачал игру Kerbal Space Programm и сейчас мы подготовим ее файлы на Linux Astra CE.

Сначала правой кнопкой мыши откроем свойства нужного файла, открыв его расположение через файловый менеджер:

img 5e4edb831963b

Как сделать исполняемый файл в Astra Linux через терминал Fly?

Навыками работы с терминалом необходимо владеть. Все, что мы сделали в графике, можно повторить через консоль Fly. Команда CHMOD позволяет менять права доступа к файлам и каталогам в Linux.

Синтаксис ее обширен и позволяет вносить изменения двумя способами — буквенном или числовым обозначением прав.

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

Синтаксис команды будет следующим, если мы даем всем пользователям полные права (чтение, запись, исполнение):

CHMOD 777 kerbal_space_program_russian_1_9_0_02781_36048.sh

В терминале нужно еще добраться до папки с игрой. Предлагаю попрактиковаться и попутно изучить две полезные команды терминала, без которых трудно в Линуксе. Посмотрите видео, операция занимает минуту (когда набита рука) :

Запускаем терминал Fly. В моем случае игра лежит в папке game на на первом рабочем столе. И в терминале я прописываю команду:

img 5e4fb3e0c1571

Приглашение показывает, что я внутри. Естественно, не помню, как называется следующая папка и файл. Чтобы узнать — ввожу следующую команду:

img 5e4fb4b17e015

Получаю на экране наименование следующей папки (KerbalSpace); копирую его в буфер обмена ( Ctrl+Ins ). Нажимаю ↑ на клавиатуре, пока не добираюсь до команды:

CD / home/superuser/Desktops/Desktop1/game/ вставляю наименование из буфера в конец строки через знак / ( Shift+Ins )

img 5e4fb6912d411

Обратите внимание, файл который мы уже сделали исполняемым через графический файловый менеджер зеленого цвета. Сейчас мы дадим права на исполнение файлу который выше, это другая часть той же игры.

Копируем имя файла в буфер обмена (чтобы руками не набирать) и в итоге получилась вот такая команда:

chmod 777 kerbal_space_program_making_history_dlc_russian_1_9_0_02781_36048.sh

img 5e4fb950305b4

Далее, не выходя из терминала можно установить игру. Для этого набираем команду:

sudo apt install «имя файла» (без кавычек)

Или в менеджере файлов запускаем его на исполнение привычным способом. У меня всё, пока!

Как открыть исполняемый файл в linux

bash shell script

Новые пользователи Linux часто задают вопросы: Как запустить исполняемый файл в Linux? Как выполнить файл. sh в Linux?

Bash — это оболочка, или интерпретатор командного языка, для операционной системы Linux. Это название является аббревиатурой от Bourne-Again SHell.

Как же запустить shell скрипт в Linux?

Откроем терминал. Обычно он вызывается комбинацией клавиш Ctrl+Shift+T. Используйте консольный текстовый редактор вроде vi/vim или nano чтобы создать shell скрипт в линукс:

Сделайте скрипт исполняемым

$ chmod +x myscript.sh

Запустите shell скрипт, написал в терминале:

Теперь давайте рассмотрим другой пример создания sh скрипта в Linux.

Создадим новый файл скрипта test.sh:

Нажмем i или Insert на клавиатуре, чтобы перейти в режим вставки текста. Скопируем туда или напишем следующее:

Чтобы сохранить файл, нажмем ESC, затем напишем 😡 и нажмем ENTER.

Попробуем запустить скрипт:

Ошибка появилась потому что мы не сделали файл исполняемым. Сделаем это. Как и выше, чтобы сделать файл sh в линукс исполняемым, выполним команду:

Запустим его снова:

Мы пишем ./ потому что находимся в той же директории, где и расположен скрипт. Так же мы можем использовать полный путь для запуска из другого места. Например, если скрипт находится в директории /home/user/ то можно запустить так из любого места:

Что у нас есть в скрипте test.sh?

Первая строка #!/bin/bash указывает на интерпретатор, спомощью которого будет исполняться скрипт. В нашем случае это Bash.

Вторая строка использует глобальную переменную $USER, которая содержит имя текущего пользователя, от которого исполняется скрипт. Мы получим «Hello, user», если нашего пользователя зовут user.

В третьей строке мы используем переменную, содержащую текущую дату и время — $(date).

Как запустить программу на Linux

kak zapustit programmu na

По сути операционная система состоит из ядра и огромного набора программ, которые предназначены для выполнения различных задач, обслуживания системы и удовлетворения потребностей пользователя. Почти все взаимодействие пользователя и операционной системы выполняется с помощью программ. Поэтому новичкам важно понять как запустить программу на Linux, что происходит во время запуска и какие есть способы запуска.

Дальше мы рассмотрим виды программ, их запуск программ на Linux различными способами и другие полезные для новичков вещи, опытным пользователям это все и так уже известно.

Виды программ в Linux

Перед тем, как мы перейдем к запуску программ, нужно сначала понять что представляет из себя программа. В Linux программы отличаются от других файлов только тем, что для них установлен флаг исполняемости. Я уже подробно писал об этом в статье что такое исполняемость поэтому не буду повторяться.

Все программы можно поделить на несколько типов:

А теперь перейдем к запуску программ.

Запуск программ в терминале

Изначально в операционных системах Unix и Linux не было графического интерфейса, поэтому программы запускались командами из терминала. Сейчас это тоже возможно и достаточно активно используется опытными пользователями. Синтаксис запуска программы выглядит таким образом:

kak zapustit programmu na

kak zapustit programmu na

И можно передать параметры после пробела:

kak zapustit programmu na

Когда программа находится не в этих каталогах, нужно указать к ней полный путь:

kak zapustit programmu na

Иногда возникает необходимость передать программе, какие-либо особые переменные окружения. Например, переменная EDITOR указывает какой текстовый редактор нужно использовать по умолчанию. Вы можете указать имя переменной и ее значение перед именем команды используя синтаксис:

kak zapustit programmu na

По умолчанию эта команда открывает настройки утилиты sudo в редакторе Vim, но с этой переменной окружения настройки откроются в редакторе nano.

Запуск программ от имени другого пользователя

kak zapustit programmu na

kak zapustit programmu na

Команда whoami (кто я) выводит имя текущего пользователя.

Как запустить программу в фоне

Иногда возникает необходимость запустить долго выполняющуюся программу в терминале так, чтобы она не мешала дальше работать. Для этого можно использовать запуск программы в фоновом режиме linux:

kak zapustit programmu na

Система выведет PID, уникальный идентификатор программы, который вы потом можете использовать чтобы закрыть ее командой kill:

kak zapustit programmu na

Как запустить скрипт в Linux

Мы уже говорили, что программы делятся на бинарные и интерпретируемые. Раньше мы говорили только про бинарные программы. Для запуска интерпретируемых нужен непосредственно интерпретатор, к таким программам относятся написанные на таких языках, как Java, Python, Perl, Ruby, PHP, NodeJS и многих других. Синтаксис запуска такой программы отличается:

интерпретатор /путь/к/файлу/программы параметры

Разные интерпретаторы ведут себя по разному, поэтому лучше сразу указывать полный путь к программе. Python обычно подхватывает скрипты из текущей папки без указания полного пути:

А Java программы нужно запускать так:

Для файлов интерпретируемых программ флаг исполняемости необязательный, поскольку они передаются в виде параметра основной программе. Только Bash скрипты составляют исключение. Вы можете запустить скрипт интерпретатором:

Или же просто набрать путь к скрипту:

Оболочка сама определяет свои скрипты по флагу исполняемости и выполняет их. Если флаг исполняемости не установлен, то его стоит добавить:

Поэтому то и для большинства интерпретируемых программ созданы простые sh скрипты которыми их можно быстро запустить.

Запуск программ Linux в графическом интерфейсе

Намного удобнее запускать программы через графический интерфейс. Если консольные программы так запускать невозможно, то для всех графических утилит существуют ярлыки, которые вы можете найти в главном меню системы:

kak zapustit programmu na

Кроме того, вы можете запустить программу из файлового менеджера, двойным кликом мышью, но тогда для нее обязательно должен быть установлен флаг исполняемости.

kak zapustit programmu na

kak zapustit programmu na

Точно так же работает запуск скриптов в графическом интерфейсе. Вы можете найти все ярлыки из меню в каталоге /usr/share/applications/. Любую программу можно запустить двойным щелчком отсюда. Но давайте посмотрим что находится внутри ярлыка, для этого откройте его в текстовом редакторе:

kak zapustit programmu na

kak zapustit programmu na

Кроме всего прочего, в строке Exec указана команда, которая выполняет запуск программы linux, когда вы делаете двойной клик на ярлыке. Вы можете взять один из существующих ярлыков и сделать на его основе свой. Здесь указано просто имя программы. Но важно заметить, что лучше указывать полный путь в таких местах, как ярлыки, скрипты, cron и так далее это уменьшит количество ошибок, поскольку вы не можете знать проверяет ли система в этом случае PATH или ищет программу только в текущем каталоге. Теперь вы знаете все о том как запустить программу на linux.

Выводы

В этой статье мы рассмотрели как запустить программу через терминал ubuntu или в других дистрибутивах Linux. Несмотря на то, что это кажется очень простой темой, тут есть свои интересные моменты, которые могут быть полезны. Но вы о них уже знаете. Если у вас остались вопросы, спрашивайте в комментариях!

Как сделать файл исполняемым в Linux

Операционная система Linux, в отличие от Windows, определяет какие файлы являются программами не по расширению, а по специальному флагу исполняемости. У каждого файла есть три основных флага, чтение, запись и исполнение. Они определяют что система может делать с этим файлом.

Что такое исполняемость?

Уже много написано о том, как установить флаг исполняемости. Но что происходит с файлом во время этого, что такое исполянемость и как это работает?

Как сделать файл исполняемым в Linux?

В операционной системе Linux, для управления флагами файлов используется утилита chmod. Синтаксис вызова утилиты:

$ chmod категория действие флаг адрес_файла

Например, чтобы сделать исполняемый скрипт в linux для владельца файла, достаточно выполнить:

chmod u+x адрес_файла

bin1

Этого в большинстве случаев бывает достаточно, но если мы хотим чтобы файл могли выполнять и другие пользователи, нужно указать также другие категории: g и o:

chmod ugo+x адрес_файла

Посмотреть флаги в терминале можно с помощью утилиты ls:

bin2

Снять флаг исполняемого файла очень просто. Используется та же команда только со знаком минус:

chmod u-x адрес_файла

Как установить фалг исполняемости в GUI

Вы можете сделать файл исполняемым в linux не только через терминал. Такая функциональность есть во всех файловых менеджерах. Возможно, на первых порах это будет для вас проще. Рассмотрим на примере файлового менеджера GNOME, Nautilus. Кликните правой кнопкой по нашему файлу программы или скрипта, чтобы открыть контекстное меню, затем выберите свойства:

bin3Дальше перейдите на вкладку права и установите галочку Разрешить выполнение файла как программы:

bin4

Готово, исполняемый файл linux может быть запущен системой, прямо из файлового менеджера.

Выводы

Вот и все, теперь вы знаете как сделать файл исполняемым в linux. И если нужно будет запустить скрипт или установщик из интернета, у вас не возникнет никаких проблем. Если остались вопросы, спрашивайте в комментариях!

Пошаговый запуск программы в Linux x86, или как добраться до main()?

Статья предназначена для тех, кто хочет понять процесс загрузки программ в Linux. В частности, здесь пойдет речь о динамической загрузке файлов ELF x86. На основе изложенной информации вы сможете лучше понять, как устранять проблемы, возникающие в программе еще до запуска main .

Весь этот материал является актуальным, но кое-какие моменты в нем были опущены, так как к основной цели отношения не имеют. Кроме того, если вы выполняете линковку статически, то некоторые нюансы будут отличаться. Все эти детали я разбирать не стану, но к завершению вы будете знать достаточно, чтобы разобраться самостоятельно.

Вот предстоящий нам маршрут:


Схема получена с помощью dot-фильтра, используемого для рисования направленных графов

К концу статьи вам все это станет понятно.

Как мы попадаем в main?

Мы соберем простейшую программу Си с пустой функцией main , а затем рассмотрим ее дизассемблированную версию, чтобы понять весь путь запуска. В ходе этого процесса вы увидите, что первым делом выполняется линкуемая с каждой программой функция _start , которая в конечном итоге приводит к выполнению main .

Если хотите, можете сохранить копию этой программы как prog1.c и повторять за мной. Первым делом я выполню ее сборку:

Прежде, чем переходить к отладке последующей версии этой программы ( prog2 ) в gdb , мы ее дизассемблируем и узнаем некоторые детали о процессе запуска. Я покажу вам вывод objdump -d prog1 , но не в порядке фактического вывода, а в порядке его выполнения. (В идеале вам следует сделать это самим. Например, сохранить копию с помощью objdump -d prog1 >prog1.dump , чтобы потом просмотреть ее в привычном редакторе).

Для начала разберемся, как мы попадаем в _start

При запуске программы оболочка или GUI вызывают execve() , которая выполняет системный вызов execve() . Если вы хотите побольше узнать об этом системном вызове, то просто введите в оболочке man execve . Он находится в разделе 2 мануала вместе со всеми остальными системными вызовами. Если кратко, то он настраивает стек и передает в него argc , argv и envp .

Дескрипторы файлов 0 , 1 и 2 ( stdin , stdout , stderr ) остаются со значениями, установленными для них оболочкой. Загрузчик проделывает много работы, настраивая релокации и, как мы увидим позднее, вызывая пре-инициализаторы. Когда все готово, управление передается программе через вызов _start() .

Вот соответствующий раздел objdump -d prog1 :

Операция XOR элемента с самим собой устанавливает этот элемент на нуль. Поэтому xor %ebp,%ebp устанавливает %ebp на нуль. Это предполагается спецификацией ABI (Application Binary Interface) для обозначения внешнего фрейма.

Далее мы извлекаем верхний элемент стека. Здесь у нас на входе argc , argv и envp , значит операция извлечения отправляет argc в %esi . Мы планируем просто сохранить его и вскоре вернуть обратно в стек. Так как argc мы извлекли, %esp теперь указывает на argv . Операция mov помещает argv в %ecx , не перемещая указатель стека.

Теперь мы выполняем для указателя стека операцию and с маской, которая обнуляет нижние четыре бита. В зависимости от того, где находился указатель, он переместится ниже на величину от 0 до 15 байт, что приведет к выравниванию кратно 16 байтам. За счет подобного выравнивания элементов стека повышается эффективность обработки памяти и кэша. В частности, это необходимо для SSE (Streaming SIMD Extensions), инструкций, способных одновременно обрабатывать вектора с плавающей точкой одинарной точности.

В конкретно этом случае %esp на входе в _start имел значение 0xbffff770 . После того, как мы извлекли argc , %esp стал 0xbffff774 , то есть сместился на более высокий адрес (добавление элементов в стек ведет к перемещению по памяти вниз, а их извлечение – вверх). После выполнения and значение указателя стека вновь стало 0xbffff770 .

Далее устанавливаем значения для вызова __libc_start_main

Теперь мы начинаем передавать в стек аргументы для _libc_start_main . Первый, %eax , является мусором, который передается только потому, что в стек мы собираемся поместить 7 элементов, а для 16-байтового выравнивания требуется 8-й. Использоваться он не будет. Сама функция _libc_start_main линкуется из glibc . В дереве исходного кода glibc она находится в файле csu/libc-start.c . Определяется _libc_start_main так:

Итак, мы ожидаем, что _start передаст обозначенные аргументы в стек в обратном порядке до вызова _libc_start_main .

Содержимое стека перед вызовом __libc_start_main

__libc_csu_fini линкуется в наш код из glibc и находится в файле csu/elf-init.c дерева исходного кода. Это деструктор нашей программы на уровне Си, и чуть позже я разберу его подробно.

Так, а где переменные среды?

Вы заметили, что мы не получили из стека envp , указатель на наши переменные среды? Среди аргументов _libc_start_main его тоже нет. Но мы знаем, что main называется int main(int argc, char** argv, char** envp) , так в чем же дело?

Что ж, _libc_start_main вызывает _libc_init_first , которая с помощью секретной внутренней информации находит переменные среды сразу после завершающего нуля вектора аргументов, после чего устанавливает глобальную переменную _environ , которую _libc_start_main при необходимости использует впоследствии, в том числе в вызовах main .

После установки envp функция _libc_start_main использует тот же трюк и…вуаля! Сразу за завершающим нулем в конце массива envp находится очередной вектор, а именно вспомогательный вектор ELF, который загрузчик использует для передачи процессу определенной информации. Для просмотра его содержимого достаточно просто установить перед запуском программы переменную среды LD_SHOW_AUXV=1 . Вот результат для нашей prog1 :

Разве не интересно? Тут полно всяческой информации.

  • Здесь мы видим AT_ENTRY , представляющую адрес _start , где находится наш userid , действующий userid и groupid .
  • Очевидно, что используется платформа 686 , а частота times() равна 100 тактов/с.
  • AT_PHDR указывает расположение ELF-заголовка программы, в котором хранится информация о нахождении всех сегментов этой программы в памяти, а также о записях релокаций и всем остальном, что нужно знать загрузчику.
  • AT_PHENT – это просто количество байт в записи заголовка.

__libc_start_main в общем

На этом я закончу разбор деталей _libc_start_main и лишь добавлю, что в общем он:

  • Реализует функционал безопасности с помощью вызовов setuid и stgid ;
  • Запускает потоковую обработку;
  • Регистрирует аргументы fini (для нашей программы) и аргументы rtld_fini (для загрузчика среды выполнения), которые запустит at_exit для выполнения процедур очистки программы и загрузчика.
  • Вызывает аргумент init ;
  • Вызывает main с передаваемыми ей аргументами argc и argv , а также аргументом global_environ , о чем я писал выше;
  • Вызывает exit с возвращаемым main значением.

Вызов аргумента init

Аргумент init для _libc_start_main устанавливается на _libc_csu_init , который также линкуется в наш код. Он компилируется из программы Си, расположенной в файле csu/elf-init.c дерева исходного кода glibc , и линкуется в нашу программу. Его код Си похож на (но содержит намного больше #ifdef )…

Конструктор нашей программы

_libc_csu_init для нашей программы очень важен, так как конструирует ее исполняемый файл. Я уже слышу, как вы говорите: «Это же не C++!». Все верно, но принцип конструкторов и деструкторов не принадлежит к C++ и предшествовал этому языку.

Наш исполняемый файл и любой другой его аналог получает на уровне Си конструктор _libc_csu_init и деструктор _libc_csu_fini . Внутри конструктора, как вы увидите далее, исполняемый файл ищет глобальные конструкторы уровня Си и вызывает любой, который найдет. В программе Си они также могут присутствовать, и в ходе статьи я это продемонстрирую. Хотя, если для вас будет удобнее, можете называть их инициализаторы и финализаторы. Вот код ассемблера, сгенерированный для _libc_csu_init :

Что такое thunk?

Говорить здесь особо не о чем, но я подумал, что вы захотите это увидеть. Функция get_pc_thunk весьма интересна. Она вызывается для настройки позиционно-независимого кода. Чтобы все сработало, указатель базы должен иметь адрес GLOBAL_OFFSET_TABLE . Соответствующий код выглядел так:

Посмотрим на происходящее подробнее. Вызов _get_pc_thunk_bx , как и любой другой, помещает в стек адрес следующей функции, чтобы при возвращении выполнение продолжилось с очередной инструкции. В данном случае нам нужен тот самый адрес. Значит, в _get_pc_thunk_bx мы копируем адрес возврата из стека в %ebx . Когда происходит возврат, очередная инструкция прибавляет к нему _GLOBAL_OFFSET_TABLE_ , разрешаясь в разницу между текущим адресом и глобальной таблицей смещений, используемую позиционно-независимым кодом.

В этой таблице хранится набор указателей на данные, к которым мы хотим обратиться, и нам лишь нужно знать их смещения. При этом загрузчик сам фиксирует для нас нужный адрес. Для обращения к процедурам существует аналогичная таблица. Было бы поистине утомительно программировать подобным образом в ассемблере, но можно просто написать нужный код на Си/С++ и передать аргумент -pic компилятору, который сделает это автомагически.
Встречая данный код в ассемблере, вы можете сделать вывод, что исходник был скомпилирован с флагом -pic .

Но что это за цикл?

Цикл из _libc_csu_init мы рассмотрим сразу после вызова init() , который фактически вызывает _init . Пока же просто имейте ввиду, что он вызывает для нашей программы любые инициализаторы уровня Си.

Вызов _init

Хорошо. Загрузчик передал управление _start , которая вызвала _libc_start_main , которая вызвала _libc_csu_init , которая теперь вызывает _init :

Начинается она с регулярного соглашения о вызовах Си

Если вы хотите побольше узнать об этом соглашении, почитайте Basic Assembler Debugging with GDB. Если коротко, то мы сохраняем указатель базы вызывающего компонента в стеке и направляем указатель базы на верхушку стека, после чего резервируем место для своего рода 4-байтовой локальной переменной.

Интересен здесь первый вызов. Его задача во многом аналогична вызову get_pc_thunk , который мы видели ранее. Если посмотреть внимательно, то он направлен к следующему по порядку адресу. Это переносит нас к очередному адресу, как если бы мы просто продолжили, но при этом в качестве побочного эффекта данный адрес оказывается в стеке. Он помещается в %ebx , а затем используется для установки доступа к глобальной таблице доступа.

Покажи мне свой профиль

Далее мы захватываем адрес gmon_start . Если он равен нулю, то мы его просто проскакиваем. В противном случае он вызывается для запуска профилирования. В этом случае происходит запуск процедуры для начала профилирования и вызов at_exit , чтобы по завершению сработала другая процедура и записала gmon.out .

Вызов frame_dummy

В любом из случаев дальше мы вызываем frame_dummy . Вообще нам нужно вызвать _register_frame_info , а frame_dummy просто устанавливает для этой функции аргументы. Конечная цель – настроить разворачивание стековых фреймов для обработки исключений. Это интересно, но к нашему разбору не относится, и в данном случае все равно не используется.

Переходим к конструкторам!

В завершении мы вызываем _do_global_ctors_aux . Если у вас сложности с программой, которые возникают до запуска main , то искать, возможно, нужно именно здесь. Конечно, сюда помещаются конструкторы для глобальных объектов С++, но кроме них тут могут находиться и другие компоненты.

Создадим пример

Теперь давайте изменим prog1 , создав prog2 . Самая интересная часть – это __attribute__ ((constructor)) , который сообщает gcc , что компоновщик должен поместить соответствующий указатель в таблицу, используемую _do_global_ctors_aux . Как видите, наш фиктивный конструктор выполняется. (компилятор заполняет _FUNCTION_ именем функции. Это магия gcc ).

_init в prog2 практически не изменяется

Чуть позже мы подключим к процессу gdb и разберем эту программу. Ну а пока же рассмотрим ее _init .

Как видите, адреса немного отличаются от prog1 . Похоже, дополнительный элемент данных сместил все на 28 байт. Итак, здесь у нас имена двух функций, a_constructor (14 байт с завершающим нулем) и main (5 байт с завершающим нулем), а также две форматирующих строки %s\n (2*4 байта с символом переноса строки и завершающим нулем).

Итого получается 14+5+4+4 = 27. Хмм…одного не хватает. Хотя это просто предположение, проверять я не стал. Позже мы все равно сделаем остановку на вызове _do_global_ctors_aux , сделаем один шаг и проанализируем происходящее.

А вот и код, который будет вызван

Чисто в качестве подсказки приведу код для _do_global_ctors_aux , взятый из файла gcc/crtstuff.c исходного кода gcc .

Как видите, он инициализирует p из глобальной переменной _CTOR_END_ и вычитает из нее 1 . Напомню, что это арифметика указателей, а указатель указывает на функцию, значит в данном случае -1 приводит к смещению на один указатель функции назад или на 4 байта. Мы также увидим это в ассемблере.

Несмотря на то, что указатель не имеет значения -1 (приведение к указателю), мы вызовем функцию, на которую указываем, после чего снова переведем указатель функции назад. Очевидно, что таблица начинается с -1 , после чего идет некоторое количество (возможно даже 0) указателей функции.

То же самое в ассемблере

Вот код ассемблера, соответствующий полученному из objdump -d результату. Прежде, чем переходить к трассировке с помощью отладчика, мы внимательно по нему пройдемся, чтобы вам было понятнее.

Сначала пролог

Здесь у нас типичный пролог с добавлением резервирования %ebx , так как мы собираемся использовать его в функции. Помимо этого, мы резервируем место для указателя p . Вы заметите, что несмотря на резервирование под него места в стеке, хранить мы его там не будем. Вместо этого p будет размещаться в %ebx , а *p в %eax .

Далее подготовка к циклу

Похоже, произошла оптимизация. Вместо загрузки _CTOR_END_ с последующим вычитанием из него 1 и разыменовыванием мы переходим далее и загружаем *(__CTOR_END__ — 1) , который представляет непосредственное значение 0x8049f14 . Его значение мы помещаем в %eax (помните, что инструкция $0x8049f14 означала бы помещение этого значения, а ее вариант без $ — помещение содержимого этого адреса).

Следом мы сравниваем это первое значение с -1 , и если они равны, то заканчиваем и переходим к адресу 0x8049f14 , где очищаем стек, извлекая все сохраненные в нем элементы и делая возврат.

Предполагая, что в таблице функций есть хотя бы один элемент, мы также перемещаем непосредственное значение $8049f14 в %ebx , который является нашим указателем функции f , после чего выполняем xchg %ax,%ax .

Что это вообще такое? Эта команда используется в качестве NOP (No OPeration) в 16- и 32-битных x86. По факту она ничего не делает. В нашем случае ее задача в том, чтобы цикл (верхняя его часть – это вычитание на следующей строке) начинался не с 8048466 , а с 8048468 . Смысл здесь в выравнивании начала цикла с 4-байтовой границей, в результате чего весь цикл с большей вероятностью впишется в одну строку кэша, не разбиваясь на две. Это все ускорит.

И вот мы у вершины цикла

Далее мы вычитаем 4 из %ebx , подготавливаясь к очередному циклу, вызываем функцию, адрес которой получили в %eax , перемещаем следующий указатель функции в %eax и сравниваем его с -1 . Если они не равны, возвращаемся к операции вычитания и повторяем цикл.

Эпилог

В противном случае мы достигаем эпилога функции и возвращаемся к _init , которая сразу достигает своего эпилога и возвращается к _libc_csu_init_ , о котором вы уже наверняка забыли. Здесь все еще остается один цикл для завершения, но сначала…

Как я и обещал, мы займемся отладкой prog2 .

Напомню, что gdb всегда показывает очередную строку или инструкцию, которая будет выполнена.

Мы запустили программу в отладчике, включили disassemble-next-line , чтобы он всегда показывал очередную строку в дизассемблированном виде, и установили точку останова на строку в _init , где будем вызывать _do_global_ctors_aux .

Здесь я ввел r , чтобы запустить программу и достичь точки останова. Очередной командой для gdb стала si , инструкция шага, указывающая отладчику шагнуть на одну инструкцию вперед.

Теперь мы вошли в _do_global_ctors_aux . Далее вы заметите моменты, когда я будто бы не ввожу команды для gdb , хотя это не так. Дело в том, что при нажатии Ввода отладчик повторяет последнюю инструкцию. То есть, если я нажму Ввод сейчас, то еще раз выполню si .

Хорошо, с прологом мы закончили, пришло время реального кода.

После загрузки указателя мне стало любопытно, и я ввел p/x $eax , то есть попросил gdb вывести hex-содержимое регистра %eax . Это не -1 , значит можно предположить, что цикл мы проходим.

Теперь, поскольку последней командой был вывод, я не могу повторить si нажатием Ввода, и мне придется ее ввести.

Вот здесь очень интересно. Мы шагнули в вызов и теперь находимся в функции a_constructor . Поскольку у gdb есть для нее исходный код, он показывает исходник Си для следующей строки. А так как я включил disassemble-next-line , он также покажет нам соответствующий код ассемблера.

В данном случае это пролог функции, и мы получаем все его три строки. Разве не интересно? Далее я переключусь на команду n (next), потому что скоро покажется printf . Первая n пропустит пролог, вторая printf , а третья эпилог. Если вас когда-нибудь интересовало, почему при пошаговом продвижении с помощью gdb нужно делать дополнительный шаг в начале и конце функции, то теперь вы знаете почему.

Мы переместили адрес строки a_constructor в стек в качестве аргумента для printf , но он вызывает puts, поскольку компилятор догадался, что нас интересует только puts .

Раз мы трассируем программу, то она, естественно, выполняется, в связи с чем выше мы видим вывод a_constructor . Закрывающая скобка > соответствует эпилогу, поэтому он выводится сейчас. К слову отмечу, если вам не знакома инструкция leave , то выполняет она то же, что и:

Очередной шаг выводит нас из функции с возвращением ее результата. Здесь мне потребуется снова переключиться на si .

Мне снова стало интересно, и я решил еще раз проверить значение указателя функции. На этот раз он равен -1 , значит из цикла мы выходим.

Заметьте, что мы снова вернулись в _init .

Обратите внимание, что мы перепрыгнули обратно к _libc_csu_init , и здесь я ввел q для выхода из gdb . Вот и вся отладка, которую я обещал.

Теперь, когда мы вернулись в _libc_csu_init_ , нужно разобраться еще с одним циклом, через который я уже не буду шагать, а просто его проговорю.

Возвращаемся в __libc_csu_init__

Поскольку мы итак провели немало времени за работой с циклом в ассемблере, а ассемблерный код для этого конструктора еще более утомителен, то я оставлю эту задачу для тех, кому она будет интересна. Просто напомню, как он выглядит в Си:

Еще один цикл вызова функции

Что такое массив _init_ ? Я уж думал, вы и не спросите. На этом этапе вы также можете выполнять код. Поскольку идет он сразу после возвращения из _init , которая запускала наши конструкторы, то содержимое этого массива будет выполняться после завершения конструкторов. Вы можете сообщить компилятору, что хотите выполнить на этом этапе функцию, которая в результате получит те же аргументы, что и main .

Мы пока этого делать не будем, потому что есть и другие подобные моменты. Давайте просто вернем результат из _lib_csu_init . Помните, куда это нас приведет?

Мы вернемся аж к __libc_start_main__

Теперь он вызывает наш main , а результат передает в exit() .

exit() выполняет функции, зарегистрированные с помощью at_exit в порядке их добавления. Затем она выполняет очередной цикл функций, на этот раз из массива fini . Далее она выполняет еще один цикл функций, теперь уже деструкторов. (В реальности она находится во вложенном цикле и работает с массивом списков функций, но поверьте мне, завершаются они именно в этом порядке). Вот смотрите.

Эта программа, hooks.c, связывает все воедино

Если собрать и выполнить эту программу (я зову ее hook.c ), то выводом будет:

Конец

Еще раз продемонстрирую вам весь путь, который мы прошли, только теперь он должен быть вам уже более понятен.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *