Перенос кода с windows на linux
Рост популярности ОС Linux и появление спроса на поддержку одновременно различных операционных платформ потребовал от разработчиков освоения технологии создания многоплатформного программного обеспечения.
В статье излагается конкретный опыт коллектива разработчиков геоинформационной системы «Панорама» по переносу этой системы с платформы Windows на Linux. Первая версия системы «Панорама» была создана специалистами Топографической службы Вооруженных Сил РФ в 1991 году. Программы были написаны на языке Си с применением встроенного ассемблера для системы MS-DOS.
Разработка оказалась достаточной удачной и при простом интерфейсе имела высокую скорость отображения растровой и векторной графики, а также профессиональный набор средств векторизации отсканированных карт местности. Это обеспечило относительное долголетие системы, которая широко применяется до сегодняшнего дня в целях создания электронных карт. Благодаря компактности системы на ее основе создана космонавигационная программа для станции «Мир». Одним из основных условий разработки данной программы было требование размещения загрузочного кода вместе с картой мира масштаба 1 : 40 млн. на одной дискете емкостью 1,2 Мбайт. При этом, программа должна еще показывать текущую орбиту, перемещать в реальном времени подспутниковую точку с учетом параметров орбиты, определять зоны дня и ночи, показывать зоны радиосвязи и выполнять другие необходимые расчеты.
С появлением Windows 95 ядро системы было переписано на языке С++ и расширено для создания ГИС, способной решать различные прикладные задачи (связь, навигация, экология, земельный кадастр и др.). Участие в разработке программ принимали Национальная картографическая корпорация, компании «Геоспектрум» и «Эпсилон Технологии». В результате на сегодняшний день создана ГИС «Карта 2000», инструментальные средства GIS Tool Kit, система земельного кадастра «Земля и право» и ряд других систем.
При разработке программ для Windows мы были уверены, что это не последняя платформа для работы их задач, поэтому разработка велась так, чтобы ядро системы не пришлось переписывать третий раз.
Исходные тексты программ системы имеют размер несколько десятков мегабайт на языке C++. Программное обеспечение работает с векторной и растровой графикой и выполняет большой объем специальных вычислений. В качестве платформ поддерживаются: Linux, QNX, OC-РВ, Windows CE, Windows 98/NT, Intel, MIPS и Sparc. При компиляции использовались трансляторы Borland C++, Visual C++, Watcom C++, GNU C++.
Некоторые правила
Прежде всего, необходимо так спроектировать систему или внести изменения в готовую, чтобы графический интерфейс был реализован отдельными подпрограммами. Даже если это программа графического редактирования, трехмерного моделирования и т.п., она должна быть разделена на уровне исходных текстов. Программы с графическим интерфейсом можно разделить на два типа: задачи потоковой обработки данных и задачи, выполняющиеся в интерактивном режиме.
Сценарий задач потоковой обработки данных может иметь следующий вид:
Графическая часть такой задачи может быть представлена в виде диалога, отображающего введенные данные и ход выполнения процесса. Сам процесс может быть реализован в виде отдельной библиотеки с определенной точкой входа. В качестве дополнительного параметра процессу передается идентификатор диалога, который может быть идентификатором окна в Windows или адресом функции обратного вызова, что позволяет организовать обратную связь. Такой подход облегчает смену инструментальных средств: при переносе переписывается только диалог по имеющемуся образцу. Кроме того, возможна специализация программистов на разработке диалогов и решении прикладных задач, что повышает уровень разработки и сокращает сроки.
Выполнение интерактивных задач (например, графического редактирования), основано на обработке событий, связанных с устройствами ввода/вывода: мышь, клавиатура, экран, таймер и т.п. Процесс обработки событий может быть реализован в виде отдельной библиотеки с несколькими универсальными точками входа либо число точек входа может соответствовать числу обрабатываемых событий. Обратная связь может выполняться через вспомогательный параметр, как для задач первого типа. Реализация графических функций может быть выполнена двумя способами.
Первый способ состоит в использовании области памяти, содержащей образ окна программы. Изображение строится в памяти и затем отображается на экране на основе минимального набора графических функций, доступных в операционной системе, например, BitBlt в Windows или XPutImage в подсистеме X Window в среде Linux. Функции, выполняющие отображение в память, должны быть независимы от размера палитры. Этого можно достичь путем применения макроопределений и вспомогательных переменных, описывающих текущие характеристики области памяти и палитры. Например, размер точки в байтах, ширина строки в байтах и т.д. Для упрощения логики задачи и ускорения работы можно применять 4 байта на точку, но это потребует дополнительных затрат оперативной памяти.
Второй способ - разработка своей собственной библиотеки графических функций, скрывающих особенности графической подсистемы на применяемой платформе. Здесь необходимо выполнить определение вспомогательных структур, констант и идентификаторов, скрывающих применяемые в конкретной графической подсистеме объекты. Например, координаты точки, координаты прямоугольной области, идентификатор окна, идентификатор палитры, элементы описания цвета точки и так далее.
Для написания пользовательского интерфейса могут применяться средства языка Java, что упрощает поддержку нескольких платформ - взаимодействие с библиотекой подпрограмм на языке C++ достаточно просто реализуется интерфейсом Jini.
При выполнении доступа к данным применяются различные функции операционной системы по работе с файлами и оперативной памятью. Такие функции обычно имеют посредников в стандартных библиотеках Cи или C++, однако, применение функций-посредников не всегда допустимо. Например, прямой вызов функции CreateFile() позволяет открыть файл с отключенной буферизацией на запись данных. Такая возможность может понадобиться при обработке некоторых категорий данных (журнал транзакций, файлы отката и т. п.), однако, вызов функции open() не обеспечивает такого режима записи.
При работе с оперативной памятью более гибкой является функция VirtualAlloc(), чем malloc() или new(). Кроме того, применение функций malloc() или new() может привести к ошибкам, когда в одном проекте применяются библиотеки, собранные разными трансляторами. В результате, возникает необходимость применения системно-зависимых функций.
Проблему переноса соответствующих исходных текстов можно решать двумя путями. Первый - применять функции стандарта POSIX, как наиболее распространенные. Второй - описывать макроопределения для требуемых функций, чтобы основной текст выглядел одинаково для разных платформ. Макроопределения функций и необходимых констант могут располагаться в заголовочном файле. Если компактность кода важнее производительности, то могут создаваться функции-посредники в виде отдельного набора исходных текстов.
Другая проблема, которая возникает при переносе программ на разные платформы, - учет требований процессоров по выравниванию данных и интерпретации числовых значений. Например, процессор Intel допускает обращение к числовым переменным, расположенным по адресу, не кратному длине операнда - порядок байт в слове: от младшего разряда к старшему. Компиляторы С/С++ для платформы Intel интерпретируют битовые структуры в порядке от младшего битового поля к старшему и такой же порядок байт в структуре. Процессоры MIPS и Sparc требуют выравнивания адреса переменной кратно ее длине (short - кратно 2, long - 4, double - 8), а порядок байт в слове: от старшего байта к младшему. Битовые поля в структуре располагаются от старшего поля к младшему в пределах байта, а байты от младшего к старшему (то есть обратно порядку битовых полей).
Так как выравнивание адресов переменных и размеров структур может быть обеспечено на любой платформе и повышает скорость выполнения программы (за счет уменьшения времени выборки данных процессором), то такой подход должен быть взят за правило при любой разработке.
Для корректной работы с двоичными данными, хранящимися в файле или базе данных, необходимо предусмотреть признак порядка расположения байт в структуре данных. Этот признак может учитываться при считывании данных в память, где может быть выполнен разворот байт. Для оптимизации многократного доступа к данным результаты разворота могут сохраняться в файле с соответствующим изменением признака. Для правильной интерпретации бит в пределах байта целесообразно в структурах применять макрокоманды, изменяющие порядок битовых полей в описании структур в соответствии с целевой платформой. Это упростит порядок преобразования данных.
Для хранения текстовых данных наиболее часто применяется кодировка OEM, ANSI, КОИ-8 и UNICODE. Функции по работе с символьными строками в разных операционных системах требуют разной кодировки. Для постоянного хранения данных целесообразно использовать одну кодировку для всех текстовых данных. Перед выводом текста на экран он может перекодироваться в соответствии с требуемой текущей кодировкой. Функция перекодировки может быть написана с применением макрокоманд. Для оптимизации многократного доступа к данным целесообразно завести в структуре данных признак применяемой кодировки. При смене кодировки данных признак соответственно обновляется.
Как сохранить надежность?
Поддержка в исходном тексте различных платформ усложняет программу, что может сказаться на ее надежности, поэтому для повышения качества работы программы необходимо руководствоваться рядом правил.
При выделении памяти под структуру или класс необходимо выполнить инициализацию значений каждой переменной. В самом простом случае можно применить функцию memset() для обнуления всех значений - не следует надеяться на опции транслятора по автоматической очистке памяти нулями. Особое внимание следует уделять вещественным переменным. В больших текстах подпрограмм рекомендуется устанавливать начальные значения и для локальных переменных. При ошибочном начальном значении переменной сбой может принимать самые разные формы. Но, при выполнении программы под управлением отладчика, память, как правило, очищается, что затрудняет локализацию ошибки.
Большая группа ошибок связана с применением указателей при программировании на языках Cи или C++. При передаче указателей в качестве параметров функций целесообразно предусмотреть передачу и размера области, на которую ссылается указатель. Если передается указатель на структуру, то в ней целесообразно предусмотреть поле размера структуры, которое должно заполняться до вызова функции. При получении параметра - указателя функция первым делом должна проверить, что указатель не равен нулю и размер соответствующей области имеет допустимое значение.
С учетом превышения темпов развития процессоров над темпами развития программного обеспечения излишняя осторожность такого подхода оправданна - фактор надежности гораздо важнее быстродействия.
Ошибочным действием является возврат из функции указателя на локальную переменную - такой код может долго работать правильно, но при переносе на другую платформу или использовании другого компилятора приведет к ошибке из-за различий в организации стека. Данные ошибки нужно исключать еще на этапе анализа исходного текста - либо функция должна возвращать значение локальной переменной, либо заполнять область данных, которая задана указателем и размером области.
Одна и та же область памяти может выделяться в программе несколько раз. При этом важно следить за тем чтобы эта память освобождалась, а указатель принудительно устанавливался в ноль. Анализ указателя при завершении программы и при перераспределении памяти поможет избежать потери ресурсов. Такой же подход целесообразен и при работе с идентификаторами файлов. Например:
В надежной программе результат операции выделения памяти всегда должен анализироваться. Ошибка при выделении памяти может приводить к исключительной ситуации или возврату нулевого значения. Это зависит от применяемого компилятора, его параметров и платформы. Для однозначной интерпретации может применяться следующий подход:
Операторы try и catch поддерживаются не на всех платформах, поэтому они могут быть заменены на макрокоманды, например:
Чтобы упростить сопровождение и модернизацию программного обеспечения, необходимо проектировать реентерабельные подпрограммы. Одно из условий этого - минимизация применения глобальных переменных: применять их для хранения констант или включать в текст подпрограмм критические разделы, семафоры и т.п. В большинстве случаев можно обойтись применением локальных переменных и передачей параметров. Но в этом случае может возникнуть ошибка, связанная с переполнением стека.
Для снижения нагрузки на стек целесообразно выделять в отдельные подпрограммы участки текста, требующие дополнительной памяти для выполнения операции. В этом случае можно использовать в качестве локальных переменных небольшие массивы, что эффективнее динамического выделения и освобождения памяти в программе.
Различные трансляторы Си/C++ используют свои умолчания при сокращенных объявлениях переменных. Они могут оказаться знаковыми либо нет, длинными или короткими целыми. Это же относится и к константам в программах. Все это может стать источником неожиданных ошибок при переносе программ на другие платформы. Чтобы избежать этого следует минимизировать разнотипность переменных. Например, исключить из применения для локальных переменных и параметров тип short int, а для функций внешнего интерфейса использовать параметры типа: signed long int, signed char *, double.
Навстречу новым платформам
Таким образом, поставив перед собой задачу разрабатывать многоплатформное программное обеспечение, можно заодно добиться повышения качества создаваемых текстов, надежности работы программ и более четкой организации работ. Время, потраченное на внедрение и поддержку соответствующих правил разработки вполне компенсируется на этапе сопровождения и модернизации сложных программных комплексов, а процесс переноса кода на новую платформу существенно упрощается.
Здравствуйте. Меня зовут Игорь и я веб-разработчик. Я постараюсь рассказать Вам о своем опыте миграции с Windows на Linux, поделиться методами решения возникших при этом проблем, а так же рассказать о причинах, побудивших меня написать эту статью. В сети немало подобных мануалов и статей, однако, они лишь частично отвечали насущным вопросам. Я же постараюсь сделать краткое, но емкое пособие по переходу на другую ОС.
Сразу оговорюсь, если Вы используете в своей работе «тяжелое» профессиональное ПО, вроде AutoCAD, 3D Max, Photoshop и т.п., то стоит серьезно подумать перед тем, как уходить с родной платформы. К примеру, я любитель посидеть в 3D Max, его нативный linux аналог (Blender) меня не устраивает, полноценный запуск родного редактора через wine вряд ли возможен, а запускать его через виртуальную машину — расточительство ресурсов, которых под 3D Max и без того всегда мало. Но, если используемый софт относительно прост и Вас не смущает перспектива сидеть в аналогах привычных программ
— переходите на Linux!
Логично начать с причин, побудивших меня уйти с родной платформы. Это не для того, чтобы «хвастаться перед пацанами», не из-за обилия вирусов и не из-за других причин, которые чаще всего называют. Решающей причиной стал интерфейс, который сложно назвать рабочим. В моем представлении самой удачной ОС семейства MS являлась и все еще является Windows XP. Это не причуды. Это естественное желание, чтобы работа в системе была удобной и интуитивной. Чтобы ничто не отвлекало и рабочий процесс протекал гладко. Месяца работы в Windows 7 мне не хватило, чтобы привыкнуть к ней. Пробовать работать в Windows 8 уже не хочу, а сидеть дальше в XP смысла нет. Что же на другом берегу?
Linux! У этой ОС свой шарм. Дело не в халяве. Дело в свободе, которую многие принимают за минус. В свободе делать что угодно и как угодно. На мой взгляд, это главный плюс и главное отличие от Windows. Для некоторых этот плюс превращается в свободу наступать на грабли, но их и по другую сторону баррикад много, как и желающих получить граблями в лоб. На мой взгляд, для работы в любой ОС (не на уровне домохозяйки) нужно понимать, хотя бы примерно, ее архитектуру, общую концепцию и иметь прямые руки. Беда в том, что многие проецируют свой опыт работы с другими системами на Linux. Не совершайте этой ошибки.
За последнее время Linux стал стремительно развиваться. Надеюсь, что эта тенденция сохранится и система год от года будет становиться лучше. А пока, среди лидеров десктопных ОС Linux, есть два отчетливых кандидата — Ubuntu (+ ее производные) и Fedora. Fedora показалась мне излишне сложной, поэтому в данном посте речь не о ней.
Чем ярче горят мосты за спиной, тем светлее дорога впереди! (с) Unknown.
Xubuntu
Актуальная версия Xubuntu на момент написания статьи 12.10
Для себя я выбрал Ubuntu. Далее, следует выбрать среду рабочего окружения. Я остановился на XFCE — она легкая, простая и производительная. Таким образом, мой выбор — Xubuntu. Дистрибутив, основанный на Ubuntu, который использует XFCE по молчанию.
Установка и настройка
Ссылка на страницу для скачивания Xubuntu.
Для установки Xubuntu удобнее всего сделать загрузочную флешку с помощью UNetbootin.
Пока Вы скачиваете установочный образ, настоятельно рекомендую ознакомиться со справочными материалами, предоставленными на сайте Ubuntu. Этот простой и наглядный мануал ответит на 90% Ваших не заданных вопросов.
Чтобы не быть «наполовину беременным», я не хотел держать две операционные системы на борту. Так что, мой вариант установки: перенести все пользовательские данные на другой носитель, отформатировать жесткий диск и разметить его по новой, исключая место для Windows. Исходя из личных предпочтений, моя разметка диска: 50 Гб под корневой раздел, 4 Гб swap, а все остальное под домашний каталог.
- Установите доступные обновления
- Установите проприетарные драйвера для видеокарты.
Для NVIDIA
Обзор программ
gedit + плагины
Вместо Notepad++ я поставил gedit c набором плагинов. Это лучшая замена, которую я смог найти для легковесного рабочего «блокнота». Рекомендую прочитать обзор плагинов к gedit от dreamhelg. Большая часть плагинов есть в репозитории.
Double Commander & Midnight Commander
Сложно заменить Total Commander на что-то другое. Тем не менее, лучше этой пары файловых менеджеров я не нашел. На ЛОРе плохо отнеслись к Double Сommander из-за того, что он написан на FreePascal\Lazarus. Для меня это не аргумент.
Особенно, если учесть стабильную работу в сочетании со всем необходимым функционалом. Midnight Commander советую ставить безоговорочно — лучшего решения для консоли Вы не найдете.
GIMP 2.8
Долгожданная версия графического редактора под linux.
XnView
На мой взгляд, лучшая программа для просмотра изображений. Взять можно отсюда.
Программу для Linux переделать под Windows
Ребят, такие дела, учусь на заочном, нужно сделать лабы, с плюсами никогда не встречался. Есть.
Отладка программы для Linux из под Windows
А не подскажите среду разработки под консольный Debian, который стоит на пк с архитектурой x86.
Как запускать программы для Windows под Linux?
Люди, подскажите, возможно ли запускать программы для Windows из-под Linux'a, и, если есть.
Установка Qt на Linux для кросс-компиляции: Linux 32/64 Windows 32/64
В силу объективных причин пришлось перейти на Linux, но столкнулся с проблемой установки окружения.
Qt - комбайн, который желает перекрыть всё что только возможно
Wx - только графика
БД - море, mariaDB, MySQL, PostgresDB, и множество иных.
Сам выбирай что и к чему.Если хочешь пересесть на линух - многое по-новому учить придётся (в первую очередь сам линух), т.к. элементарные проги доведены до совершенства и их очень просто использовать в C/C++ прогах.
Например:
1. Поиск COM-портов в системе:
Хотя применительно к LPT сть более адекватное решение: использование ieee1284.h
Такие же простые решения можно найти и в других областях.
QT - монстр, полностью его осилить - не один месяц постребуется. В то же время более простые весчи можно решить более простыми вещами - в консоли вообще не вижу смысла использовать QT, для простых диалогов с юзером - можно использовать скрипты с dialog и пр., Текстовый редактор с "причудами" возможно будет быстрее реализовать с FLTK+.
З.Ы. Для каждой вещи стоит использовать адекватный инструмент. В линухе несколько всё иначе, чем в винде. Многое решается без компиляции вообще - с помощью встроенных шелл-оболочек вроде /usr/bin/sh
Портирование программы с Linux на Windows
Подскажите, какие есть способы запустить на windows программу разработанную в Ubuntu . проблема.
программы написанные на си в windows работают в linux
Я написал программу на си в windows в visual studio 2010, проверил все отлично работает но дела в.
Если программировать программы на oc linux с компилятором qt creator будут ли они запускаться на windows?
Если программировать программы на oc linux с компилятором qt creator будут ли они запускаться на.
FTP больше не считается достаточно безопасным для использования в Интернете. В результате я сейчас пытаюсь продемонстрировать вам SCP. SCP действительно представляет собой систему, построенную на протоколе SSH. В результате вам потребуется пользователь с правом SSH для использования сервера. Ключи SSH могут использоваться для установления соединений SCP, так же, как они могут использовать SSH. Поскольку некоторые клиенты Windows могут управлять компьютерами Linux, я дополнительно расскажу вам, как использовать бесплатное приложение WinSCP для передачи файлов с Windows на сервер Ubuntu с помощью SCP в основной части этого руководства.
Метод 1: Использование SSH-сервера
SCP или SSH как потребитель включен во все системы Linux; следовательно, вам не нужно делать ничего особенного на стороне клиента. Возможно, нам придется развернуть сервер SSH только на стороне сервера на основе дистрибутива Linux. Мы должны обновить нашу систему до последней версии перед началом любого развертывания. Просто используйте следующую команду для компьютерных систем на базе Debian (включая Ubuntu и Kubuntu):
Обновление занимает немного времени. После обновления системы давайте установим SSH-сервер в нашей операционной системе Ubuntu 20.04. Итак, добавьте указанный ниже запрос в терминал и нажмите кнопку «Enter», чтобы продолжить установку.
Между обработкой установки OpenSSH-сервера он будет приостановлен, чтобы вас попросили подтвердить его. Система хочет, чтобы вы еще раз проверили, нужно ли вам устанавливать ее в операционной системе Ubuntu 20.04 или нет. Если вам это нужно, нажмите «Y» или нажмите «n», чтобы остановить процесс.
Теперь процесс установки возобновлен, как показано ниже. Когда он достигает 100%, это означает, что обработка завершена.
Последние несколько строк обработки оболочки терминала для OpenSSH-сервера приведены ниже.
Присоединитесь к серверу через SSH, чтобы увидеть, была ли выполнена конфигурация. Используя клиент Ubuntu или Mac, запустите консоль и введите регулярное выражение. Немедленно введите код для ключа SSH, если вы его используете. В качестве альтернативы должен быть предоставлен пароль пользователя хост-устройства. Когда все в порядке, теперь должен отображаться терминал внешнего компьютера. Если это не так, проверьте правила брандмауэра. Для SSH требуется порт 22 / tcp. Вы также можете проверить конфигурацию SSH-сервера, чтобы убедиться, что у вашего клиента есть соответствующие права. Мы можем разорвать соединение, как только оно будет успешно создано. Теперь вам нужно включить и разрешить порт 22 SSH-сервера в брандмауэре. Поэтому мы использовали приведенный ниже запрос в оболочке с правами sudo.
Нам нужно проверить статус порта SSH в нашей системе с помощью команды systemctl. Следовательно, попробовал следующую команду в нашей консоли и обнаружил, что наш порт SSH активно работает.
Теперь настройки настроены для порта SSH. Откройте блокнот из области поиска на рабочем столе Windows. Добавьте данные в текстовый файл блокнота и сохраните его на рабочем столе с расширением «.txt».
Теперь снова откройте командную строку из области поиска на рабочем столе Windows. Добавьте приведенную ниже команду, чтобы увидеть логику и синтаксис использования в ней команды SCP.
Мы видели, как настроен SCP и как его следует использовать в командной строке. Давайте переместим файл notepad test.txt, который мы только что создали на рабочем столе. Для этого вы должны следовать приведенному ниже общему синтаксису инструкции SCP. Сначала указывается путь к файлу, в который он был сохранен. Этот путь должен содержать имя файла. После этого укажите имя хоста, IP-адрес и путь, по которому вы хотите сохранить файл в системе Linux. Убедитесь, что папка должна существовать в вашей системе Linux, где вы хотите ее сохранить.
Path_to_file/filename hostname@hostIP:/path_to_save_the_file_in_host
Коснитесь клавиши Enter, чтобы продолжить подключение к главному устройству. После успешного установления соединения вы должны добавить свой пароль пользователя для системы Ubuntu. Таким образом, ваш файл test.txt будет перенесен в «домашнюю» папку Linux-системы Ubuntu 20.04.
Метод 2: Использование WinSCP
Еще один эффективный и простой способ переноса файлов Windows в операционную систему Linux — через WinSCP Tool. Итак, чтобы использовать этот инструмент, мы должны сначала загрузить его, чтобы установить. Откройте поисковую систему Google, напишите в ней WinSCP и нажмите Enter, чтобы продолжить. Нажмите на первую ссылку, которая была отображена в поисковой системе.
Теперь вам будет показан стандартный инструмент WINSCP Загрузить. Нажмите на «Загрузить WinSCP», чтобы быстро добавить его к своим загрузкам.
Это может занять до 20 минут в зависимости от скорости сети в вашей системе. После завершения загрузки щелкните загруженный файл, чтобы запустить его.
Появится диалоговое окно выбора режима установки, как на изображении ниже. Нажмите «Установить для всех пользователей (рекомендуется)», чтобы начать установку.
Теперь появится новое окно для установки WinSCP. Вы должны подписать лицензионное соглашение, нажав кнопку «Принять», как показано на снимке ниже.
Установите флажок «Тип установки» как «Обычная установка (рекомендуется)» и нажмите «Далее», чтобы продолжить.
Теперь программа установки для WinSCP готова к установке. Следовательно, нажмите кнопку «Установить», чтобы продолжить и начать установку WinSCP.
Теперь процесс установки запущен. Зеленая линия означает, что установка ближе к завершению. Это будет завершено через несколько секунд.
Заключение
SCP прост для понимания и способен безопасно передавать огромное количество данных через Сеть. Например, вы можете использовать WebDAV как вариант. В этом посте я продемонстрировал вам, как это работает. Если мы работаем с разными операционными системами, мы должны исследовать оба метода.
Читайте также: