LXF155:Android:программирование
Olkol (обсуждение | вклад) |
Olkol (обсуждение | вклад) (→Инструментарий разработчика Android) |
||
(не показана 1 промежуточная версия 1 участника) | |||
Строка 122: | Строка 122: | ||
./adb shell | ./adb shell | ||
− | + | [[Файл:Pic3_opt.jpeg | |thumb|400px|Программа-менеджер Android SDK.]] | |
предоставит вам примитивную оболочку командной строки на устройстве, с помощью которой вы можете вызвать утилиту chmod для изменения атрибутов файла. Если обе команды выполнились успешно – поздравьте себя: ваше устройство идеально подходит для изучения ОС Android. В этом случае вы даже можете выполнить файл программы непосредственно из оболочки adb. Но увы, из тех Android-устройств, что попадали в мои руки, только нетбук Toshiba AC-100 оказался настолько «сговорчивым». В других случаях устройства либо вообще отказывались выполнять команды push и shell, либо не позволяли выполнить команду chmod, без которой остальные действия не имеют смысла. | предоставит вам примитивную оболочку командной строки на устройстве, с помощью которой вы можете вызвать утилиту chmod для изменения атрибутов файла. Если обе команды выполнились успешно – поздравьте себя: ваше устройство идеально подходит для изучения ОС Android. В этом случае вы даже можете выполнить файл программы непосредственно из оболочки adb. Но увы, из тех Android-устройств, что попадали в мои руки, только нетбук Toshiba AC-100 оказался настолько «сговорчивым». В других случаях устройства либо вообще отказывались выполнять команды push и shell, либо не позволяли выполнить команду chmod, без которой остальные действия не имеют смысла. | ||
Строка 132: | Строка 132: | ||
Для создания программ, скомпилированных в машинные коды, нам понадобится Android Software Development Kit (далее – SDK) и Android Native Development Kit (далее – NDK). Традиционно SDK используется для написания программ Android, предназначенных для выполнения на виртуальной машине (чем мы в этой серии заниматься не будем). | Для создания программ, скомпилированных в машинные коды, нам понадобится Android Software Development Kit (далее – SDK) и Android Native Development Kit (далее – NDK). Традиционно SDK используется для написания программ Android, предназначенных для выполнения на виртуальной машине (чем мы в этой серии заниматься не будем). | ||
− | + | [[Файл:Pic4_opt.jpeg | |thumb|400px|Создание виртуальной машины для запуска Android.]] | |
NDK предназначен для создания разделяемых библиотек в кодах микропроцессора, которые подключаются к приложениям Android с помощью механизма JNI. Эти разделяемые библиотеки создаются для расширения доступной приложениям Android функциональности и для повышения производительности в тех случаях, когда производительности виртуальной машины не хватает. | NDK предназначен для создания разделяемых библиотек в кодах микропроцессора, которые подключаются к приложениям Android с помощью механизма JNI. Эти разделяемые библиотеки создаются для расширения доступной приложениям Android функциональности и для повышения производительности в тех случаях, когда производительности виртуальной машины не хватает. | ||
Строка 140: | Строка 140: | ||
В следующей части: знакомимся со специфическими возможностями ядра и библиотеки C для ОС Android. | В следующей части: знакомимся со специфическими возможностями ядра и библиотеки C для ОС Android. | ||
+ | |||
==О терминологии== | ==О терминологии== | ||
Если следовать терминологии, принятой в Java (Java Native Interface и т. д.), термином Native следует обозначать код, выполняющийся непосредственно на процессоре, минуя виртуальную машину. Но, поскольку мне уже встречалось применение термина Native именно к программам, написанным для виртуальной машины Android (или программ, которые частично выполняются в виртуальной машине, а частично – на железе), для своих программ, которые целиком выполняются на железе и не нуждаются в виртуальной машине, я буду использовать термин «программы Linux». Этот термин оправдан по следующим причинам: в результате сборки таких программ получаются файлы в формате ELF; некоторые из этих программ обладают двоичной совместимостью с другими системами ARM Linux; другие программы могут быть портированы на другие Unix-системы с минимальными изменениями или вовсе без изменений. Последнее замечание не относится, разумеется, к тем программам, которые используют специфические возможности ядра Android. | Если следовать терминологии, принятой в Java (Java Native Interface и т. д.), термином Native следует обозначать код, выполняющийся непосредственно на процессоре, минуя виртуальную машину. Но, поскольку мне уже встречалось применение термина Native именно к программам, написанным для виртуальной машины Android (или программ, которые частично выполняются в виртуальной машине, а частично – на железе), для своих программ, которые целиком выполняются на железе и не нуждаются в виртуальной машине, я буду использовать термин «программы Linux». Этот термин оправдан по следующим причинам: в результате сборки таких программ получаются файлы в формате ELF; некоторые из этих программ обладают двоичной совместимостью с другими системами ARM Linux; другие программы могут быть портированы на другие Unix-системы с минимальными изменениями или вовсе без изменений. Последнее замечание не относится, разумеется, к тем программам, которые используют специфические возможности ядра Android. |
Текущая версия на 03:03, 27 июня 2018
|
|
|
Ваши программные наработки не пропадут даром
[править] ARM и Android: Программирование
Часть 1: Введение. Андрей Боровский начинает рассказ о том, как перенести на Android программы Linux, написанные на C или C++.
ОС Android хороша тем, что позволяет нам писать собственные приложения для мобильных устройств самых разных классов. А еще эта ОС хороша тем, что основана на ядре Linux. Стандартного способа переноса и написания кода Linux на Android не существует, но настоящих линуксоидов никогда не пугали нестандартные подходы.
Что такое Android? Среди многих определений возможно и такое: Android – это первый дистрибутив (теперь уже целое семейство дистрибутивов) Linux, который пришелся по душе широким слоям пользователей. Мы давно уже не мечтаем о распространении Linux на рабочих столах. Когда в моду вошли нетбуки, мы надеялись, что именно эти устройства станут платформой, на которой Linux сумеет потеснить другие ОС. Но этого не случилось. Некоторые предсказывали, что Linux сможет отвоевать свою нишу при переходе с 32-битных ПК на 64-битные, но и этого не произошло. Успех пришел там, где его не очень-то и ждали – в мире мобильных телефонов и планшетных компьютеров. Является ли Android настоящей ОС Linux? На мой взгляд – безусловно. Ядро Android – это слегка модифицированное ядро Linux семейства 2.6.
Отличия ядра Android от стандартных ядер Linux 2.6.x перечислены и разобраны во многих публикациях, которые можно найти в сети. Мы не станем перечислять эти отличия, а познакомимся с некоторыми из них на практике. Как все вы, конечно, знаете, Android отличается от остальных систем на основе Linux тем, что прикладные программы пишутся на языке Java и выполняются на специальной виртуальной машине. Для вывода графики используется не X-сервер, а более подходящая для мобильных устройств графическая система.
[править] Разработка для Android: другой взгляд
Все это, однако, не мешает нам писать для Android программы на языках C и C++ и компилировать их в машинный код, который будет выполняться непосредственно процессором (в этих статьях мы рассматриваем системы Android на основе процессора ARM). Для этого нам нужно взглянуть на ОС Android как на особый вариант Linux со своим собственным набором библиотек и несколько нестандартными правилами сборки приложений.
[править] Зачем писать программы для Android на C?
О причинах популярности устройств с Android среди массового потребителя сказано уже много, и я распространяться на эту тему не буду. Но среди пользователей Android есть одна специфическая категория, к которой, я уверен, принадлежат и многие читатели нашего журнала. Речь идет о людях, которым скучно просто пользоваться устройством в установленных производителем рамках. Эти люди стремятся заглянуть под капот, узнать, как работает система изнутри, найти ей новые, остроумные и оригинальные применения. Тех, кто больше других преуспел в этом деле, уважительно именуют хакерами. Если вы хотите настраивать свои устройства под свои потребности и использовать при этом больше инструментов, чем доступно обычным разработчикам Android, тогда этот учебник для вас.
Но есть и еще одна категория программистов, которым изложенное далее может быть полезно. Это те люди, которые хотят изучить специфику программирования на микропроцессорах ARM. До появления устройств Android основным учебным пособием для программистов ARM были учебные и демонстрационные платы микроконтроллеров различного уровня. При этом, помимо собственно системы команд ARM, требовалось изучать много дополнительных вещей: принципы расположения программы в памяти, адреса регистров контроллеров и значения, которые в эти адреса нужно записывать.
Спору нет, если вы собираетесь программировать для ARM «на голом железе» (например, программировать микроконтроллеры), вы должны знать и понимать все эти вещи хотя бы для того типа микроконтроллеров, с которым вы работаете. Проблема заключается в том, что в разных архитектурах, основанных на ARM, все эти низкоуровневые детали реализованы по-разному. Иногда даже устройства из одного модельного ряда не обладают обратной совместимостью. Если вы только приступаете к изучению ARM, вам, вполне справедливо, захочется иметь дело с системой, которая бы позволяла сконцентрироваться на возможностях самого микропроцессора. Устройства Android предоставляют вам такую возможность. Девайсы, работающие под управлением Android – это своего рода IBM PC в мире ARM. Так же, как на ПК, вы можете начать программировать на ассемблере для ARM Android, не заботясь о таких вещах, как загрузка программы в память или инициализация таблицы векторов прерываний.
Третья причина для освоения механизмов, с помощью которых Android взаимодействует с кодом, написанным на C/C++, связана с естественным желанием разработчиков перенести имеющийся у них код Linux (будь то библиотеки или исполнимые файлы) на Android.
[править] Чем компилировать программы для ARM?
Хотя у устройств Android достаточно процессорной мощности для того, чтобы самим компилировать и собирать программы для себя, полноценных средств разработки под Android, работающих на платформе Android, пока что нет (впрочем, они могут появиться, и очень скоро). Сейчас программы для Android собираются на обычных ПК, а затем загружаются в устройство Android или в программный эмулятор такого устройства. У каждого устройства Android (по крайней мере, из тех, что я видел – а видел я много) есть отладочный разъем, через который можно загружать и отлаживать программы. Правда, не на всех устройствах этот механизм отладки предоставляет нам такую свободу, как нам бы хотелось (подробнее об этом будет сказано ниже). Что же касается эмуляторов, то они предоставляют нам полную свободу действий, при полной же невозможности что-нибудь сломать. Хотя выполнять программы в эмуляторе, конечно, не так интересно, как запускать их на настоящем железе.
Выбор средств, позволяющих собирать и отлаживать на ПК программы, предназначенные для ARM, весьма богат. Например, пакет Scratchbox 2, установленный совместно с эмулятором QEMU, позволит не только собирать программы для ARM на ПК x86, но и выполнять их на том же ПК в режиме эмуляции различных архитектур ARM. Одним из самых дружественных дистрибутивов с точки зрения кросс-платформенной разработки для ARM следует признать Ubuntu. Этот дистрибутив позволяет без труда установить инструментарий сборки, необходимый для ARM, и другие полезные инструменты. Впрочем, поскольку нашей целевой платформой является Android, мы сосредоточимся на средствах разработки, специально предназначенных для этой платформы.
[править] Что такое программа для ARM Linux
Совместимость программного обеспечения с некоторой операционной системой можно разделить на несколько уровней. На самом нижнем уровне – использование принятого в системе формата исполняемого файла и системных вызовов. На более высоком уровне совместимость предполагает использование приложением стандартных библиотек операционной системы. Иногда проблему совместимости на втором уровне можно обойти путем статической компоновки приложения с необходимыми ему библиотеками (в этом случае приложение может не полагаться на библиотеки ОС). Но это решение имеет очень ограниченную область применения. Многие разделяемые библиотеки являются «обертками», которые предоставляют прикладным программам доступ к различным компонентам системы. Скорее всего, сторонние аналоги этих библиотек, которые статически собранная программа принесет с собой, не будут работать правильно.
Что касается ARM Linux, то совместимость программ и ОС на нижнем уровне обеспечена стандартом EABI (который как раз и описывает порядок вызова функций и системные вызовы) и тем фактом, что при сборке программ для ARM с помощью инструментария GCC генерируются файлы в формате ELF. На уровне библиотек все обстоит сложнее. Поскольку в Linux существует давняя традиция собирать программы специально для конкретной версии ОС, многие дистрибутивы вообще не заботятся о том, чтобы стороннее приложение могло найти необходимые библиотеки. Из этого следует, что простейшие программы для Linux могут работать на всех системах ARM Linux, тогда как программы, предоставляющие более широкую функциональность, должны собираться специально для каждого дистрибутива. Что касается ОС Android, то с точки зрения доступных по умолчанию библиотек эта ОС отличается от других вариантов Linux больше, чем любые два других варианта Linux отличаются друг от друга. Начать хотя бы с того, что в качестве стандартной библиотеки C вместо glibc используется библиотека Bionic, специально разработанная для Android.
[править] Наши первые опыты
Собрать простейшую программу Linux, способную работать под управлением Android (и других ARM Linux), не так уж и сложно. Рассмотрим листинг (файл hello.c):
void _start() {
char * s = “Hello World\n”;
__asm__ (“mov r0, #0; mov r1, %[sptr]; mov r2, #13; swi 0 × 900004” // _write(0, s, 13);
- [sptr] “r” (s)
- “r0”, “r1”, “r2”);
__asm__ (“mov r0, #0; swi 0x900001”); // _exit(0);
}
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
В нашем примере мы вообще отказались от функции main() (за ненадобностью), а заодно отказались и от библиотеки времени выполнения (в ОС Android используется собственный вариант этой библиотеки). Вместо того, чтобы вызывать стандартные функции printf() и exit(), мы используем системные вызовы Linux напрямую. Тонкий вариант программы необходимо компилировать с ключом -nostdlib, который приказывает компоновщику вообще не подключать библиотеку времени выполнения к программе:
arm-linux-gnueabi-gcc hello.c -o hello -nostdlib
Теперь нужно скопировать получившийся двоичный файл на устройство Android и придать ему атрибут исполняемого файла с помощью команды chmod. Теперь получившийся файл можно запустить в эмуляторе терминала Android. Вы увидите строку «Hello World!» (или что вы там написали). Если вас пугает обилие встроенного ассемблера в приведенном примере, не переживайте. Мы откажемся от использования ассемблера, как только научимся подключать библиотеки Android к нашей программе.
Хотя рассмотренный пример не демонстрирует никаких особых возможностей Android, ознакомиться с ним полезно, особенно для тех, кто раньше не сталкивался с анатомией программ, предназначенных для Linux. Дело в том, что когда мы программируем с использованием glibc, мы можем не заботиться о том, какая функция является точкой входа в программу и какой системный вызов необходим для корректного завершения ее работы. Программисты, пишущие для обычных вариантов Linux, могут и вовсе этого не знать. При написании же программ Linux для Android знать эти вещи необходимо, поскольку по умолчанию система сборки кода ARM для Android ориентирована на сборку разделяемых библиотек, а не исполняемых файлов. Так что, например, библиотека Bionic не предоставляет нам функцию _start(), и нам придется самим реализовывать аналог этой функции.
В принципе говоря, даже простая возможность доступа к системным вызовам Linux позволяет программе сделать не так уж и мало. Но полноценное программирование на языке C для Android возможно только в том случае, если мы можем задействовать в своей программе «фирменные» библиотеки Android. А вот тут все становится гораздо сложнее.
[править] Системные вызовы ARM Linux
Мера и порядок передачи аргументов системных вызовов ARM Linux соответствуют таковым на платформе Intel, так что для описания конкретного вызова можно использовать документацию по вызовам для Intel.
Относительно специфики ARM прежде всего нужно отметить, что существует два режима системных вызовов – старый и новый (новый является частью стандарта EABI). Нынешние ядра ARM Linux поддерживают оба режима (и в приведенном выше примере мы использовали старый вариант), но использовать режим EABI, разумеется, предпочтительнее. У двух режимов много общего: аргументы вызова передаются в регистрах r0–r6, а сам вызов выполняется с помощью инструкции SWI. Ограничение в 7 регистров унаследовано от Linux x86; на RISC-платформе ARM можно было бы использовать больше регистров.
При старом режиме вызова номер вызова является частью операнда инструкции SWI. Вот как выглядит вызов write() (0 × 04):
MOV r0, дескриптор_файла;
MOV r1, адрес_буфера;
MOV r2, длина_буфера;
SWI 0x900004;
В режиме EABI номер вызова передается в регистре r7, а операндом SWI всегда является значение 0 × 0. Еще одно отличие связано с передачей 64-битных аргументов. В обоих режимах их передают в паре 32-битных регистров, но в старом режиме это просто два следующих незанятых регистра, а в режиме EABI – следующая пара регистров, в которой первый регистр имеет четный номер. Тот же вызов _write() в режиме EABI будет выглядеть так:
MOV r0, дескриптор_файла;
MOV r1, адрес_буфера;
MOV r2, длина_буфера;
MOV r7, #4;
SWI 0x0;
Помимо прочего, между двумя режимами существует одно, не сразу заметное, но важное различие: режим EABI может использоваться как в режиме ARM MODE (32-битные инструкции), так и в более компактном THUMB MODE. Старый режим не может использоваться в THUMB MODE просто потому, что число 0 × 900000 не поместится в 16-битном операнде инструкции SWI режима THUMB.
[править] Преодоление препятствий
После того как программист собрал программу, у него возникает вполне естественное желание установить эту программу на целевом устройстве и запустить. С устройствами, работающими под управлением Android, этот процесс может натолкнуться на некоторые сложности. А может и не натолкнуться. Все зависит от устройства – точнее, от того, какая именно версия Android на нем используется и какие дополнения внес в нее производитель.
В принципе, все, что нам нужно сделать – это скопировать файл программы в устройство хранения данных Android (желательно, в раздел, отформатированный в файловой системе Ext3) и придать файлу атрибуты исполняемого с помощью команды chmod. Самый простой способ сделать это – воспользоваться утилитой adb (Android Debug Dridge), которая входит в состав Android SDK. Чтобы воспользоваться командами утилиты adb, необходимо подключить устройство Android к ПК через USB-порт, по которому устройство Android подключается как внешнее устройство (а не как хост-устройство). Обычно этот разъем выполнен в форм-факторе mini-USB (mini-A или mini-B; обзаведитесь соответствующим переходником). На самом устройстве Android необходимо включить режим отладки (он включается в разделе настроек устройства, в группе «Приложения»).
Если подключение выполнено правильно, на панели состояния Android появится значок с жучком и надпись «Отладка по USB разрешена».
Теперь можно попробовать достучаться до устройства Android с помощью утилиты adb. Команда
./adb devices
должна показать список подключенных устройств. Если эта команда со своей задачей не справилась, значит, либо что-то не так с подключением, либо устройство «не хочет» взаимодействовать с отладочной системой. Если устройство отобразилось в списке, можно попробовать другие команды. Команда
./adb push
скопирует файл программы с ПК на устройство Android, а команда
./adb shell
предоставит вам примитивную оболочку командной строки на устройстве, с помощью которой вы можете вызвать утилиту chmod для изменения атрибутов файла. Если обе команды выполнились успешно – поздравьте себя: ваше устройство идеально подходит для изучения ОС Android. В этом случае вы даже можете выполнить файл программы непосредственно из оболочки adb. Но увы, из тех Android-устройств, что попадали в мои руки, только нетбук Toshiba AC-100 оказался настолько «сговорчивым». В других случаях устройства либо вообще отказывались выполнять команды push и shell, либо не позволяли выполнить команду chmod, без которой остальные действия не имеют смысла.
Впрочем, отчаиваться рано. Есть много способов скопировать файл в хранилище данных Android. Можно подключить устройство к ПК как обычный внешний диск, можно даже установить на устройство Android сервер FTP. На устройство Android нужно установить также программу-эмулятор терминала. Запустив такую программу, вы попадете в ту же самую оболочку командной строки, которую предоставляет adb shell. Попробуйте вызвать команду chmod из эмулятора терминала. Если и это не удалось, значит, производитель вашего устройства надежно заблокировал возможность запуска на нем нестандартных программ. Помочь может получение прав администратора на устройстве («рутование»), которое каждый выполняет на свой страх и риск (как минимум, эта операция приводит к потере гарантии на девайс, но можно потерять и больше), или смена прошивки – еще более рискованное дело. Другой вариант – использовать для тестирования нестандартных программ программный эмулятор устройства Android, который также входит в состав SDK.
После того как виртуальное устройство создано и запущено, вы можете подключиться к нему с помощью все той же программы adb; при этом adb shell сразу предоставит вам полномочия администратора.
[править] Инструментарий разработчика Android
Для создания программ, скомпилированных в машинные коды, нам понадобится Android Software Development Kit (далее – SDK) и Android Native Development Kit (далее – NDK). Традиционно SDK используется для написания программ Android, предназначенных для выполнения на виртуальной машине (чем мы в этой серии заниматься не будем).
NDK предназначен для создания разделяемых библиотек в кодах микропроцессора, которые подключаются к приложениям Android с помощью механизма JNI. Эти разделяемые библиотеки создаются для расширения доступной приложениям Android функциональности и для повышения производительности в тех случаях, когда производительности виртуальной машины не хватает.
Процесс создания разделяемых библиотек для Android описан в документации к NDK, и заниматься им мы тоже не будем. Вместо этого мы, применив немного изобретательности, заставим NDK компилировать и собирать исполняемые файлы. Из SDK нам понадобятся только отдельные инструменты (например, уже упомянутая утилита adb).
Теперь, так или иначе, мы готовы приступить к написанию программ, которые смогут разговаривать с ОС Android на ее языке и введут в ступор тех пользователей, которые привыкли, что приложения для Android – это файлы с расширением apk.
В следующей части: знакомимся со специфическими возможностями ядра и библиотеки C для ОС Android.
[править] О терминологии
Если следовать терминологии, принятой в Java (Java Native Interface и т. д.), термином Native следует обозначать код, выполняющийся непосредственно на процессоре, минуя виртуальную машину. Но, поскольку мне уже встречалось применение термина Native именно к программам, написанным для виртуальной машины Android (или программ, которые частично выполняются в виртуальной машине, а частично – на железе), для своих программ, которые целиком выполняются на железе и не нуждаются в виртуальной машине, я буду использовать термин «программы Linux». Этот термин оправдан по следующим причинам: в результате сборки таких программ получаются файлы в формате ELF; некоторые из этих программ обладают двоичной совместимостью с другими системами ARM Linux; другие программы могут быть портированы на другие Unix-системы с минимальными изменениями или вовсе без изменений. Последнее замечание не относится, разумеется, к тем программам, которые используют специфические возможности ядра Android.