Архітектура iOS
Все в курсі, що мобільні аксесуари Apple працюють під управлінням iOS. Багато хто знає, що iOS є полегшеною версією настільної Mac OS X. Деякі здогадуються, що в основі Mac OS X лежить POSIX-сумісна ОС Darwin, а ті, хто серйозно цікавиться IT, в курсі, що основа Darwin - це ядро XNU, що з'явилося світ у результаті злиття мікроядра Mach і компонентів ядра FreeBSD. Однак все це голі факти, які нічого не скажуть нам про те, як насправді працює iOS і в чому її відмінності від настільного побратима.
Mac OS X
Операційна система, встановлена сьогодні на всі маки та (у зміненому вигляді) на айдевайси, веде свою історію аж з 1988 року, який у світі IT відомий також тим, що став роком випуску першої бета-версії операційної системи NeXTSTEP. Сама NeXTSTEP була дітищем команди розробників Стіва Джобса, який на той час уже залишив Apple і заснував компанію NeXT, яка зайнялася розробкою комп'ютерів для освітніх потреб.
У момент своєї появи на світ NeXTSTEP була воістину передовою операційною системою, яка включала безліч технологічних новацій. В основі ОС було модифіковане мікроядро Mach, доповнене компонентами ядра FreeBSD, включаючи еталонну реалізацію мережевого стека. Більш високорівневі компоненти NeXTSTEP були написані з використанням мови Objective-C і надавали розробникам програм багатий об'єктно-орієнтований API. Система була забезпечена розвиненим і дуже зручним графічним інтерфейсом (ключові компоненти якого збереглися в OS X і навіть iOS) і потужним середовищем розробки, що включала в тому числі відомий всім сучасним розробникам візуальний дизайнер інтерфейсу.
Після провалу NeXT і повернення Стіва Джобса до компанії Apple у 1997 році NeXTSTEP лягла в основу проекту Rhapsody, в рамках якого почалася розробка системи-спадкоємця Mac OS 9. У 2000 році з Rhapsody було виділено відкритий проект Darwin, вихідники якого опубліковані під ліцензією а вже в 2001 році з'явилася світ OS X 10.0, побудована на його основі. Через кілька років Darwin ліг в основу операційної системи для смартфона, що готується до випуску, про який до 2007-го, крім чуток, не було відомо майже нічого.
XNU та Darwin
Умовно начинку OS X/iOS можна розділити на три логічні рівні: ядро XNU, шар сумісності зі стандартом POSIX (плюс різні системні демони/сервіси) та шар NeXTSTEP, що реалізує графічний стек, фреймворк та API додатків. Darwin включає в себе перші два шари і поширюється вільно, але тільки у версії для OS X. iOS-варіант, портований на архітектуру ARM і включає деякі доробки, повністю закритий і поширюється тільки в складі прошивок для айдевайсів (судячи з усього, це захист від портування iOS на інші пристрої).
За своєю суттю Darwin - це «гола» UNIX-подібна ОС, яка включає POSIX API, шелл, набір команд і сервісів, мінімально необхідних для роботи системи в консольному режимі і запуску UNIX-софту. У цьому плані він схожий на базову систему FreeBSD або мінімальну установку якогось Arch Linux, які дозволяють запустити консольний UNIX-софт, але не мають ні графічної оболонки, ні всього необхідного для запуску серйозних графічних програм із середовищ GNOME або KDE.
Ключовий компонент Darwin - гібридне ядро XNU, засноване, як уже було сказано вище, на ядрі Mach та компонентах ядра FreeBSD, таких як планувальник процесів, мережевий стек та віртуальна файлова система (шар VFS). На відміну від Mach і FreeBSD, ядро OS X використовує власний API драйверів, названий I/O Kit і дозволяє писати драйвери на C++, використовуючи об'єктно-орієнтований підхід, що дуже спрощує розробку.
iOS використовує дещо змінену версію XNU, проте через те, що ядро iOS закрите, сказати, що саме змінила Apple, важко. Відомо тільки, що воно зібране з іншими опціями компілятора та модифікованим менеджером пам'яті, який враховує невеликі обсяги оперативної пам'яті в мобільних пристроях. У всьому іншому це все те ж XNU, яке можна знайти у вигляді зашифрованого кеша (ядро + всі драйвери/модулі) у каталозі /System/Library/Caches/com.apple.kernelcaches/kernelcache на самому пристрої.
Рівнем вище ядра в Darwin розташовується шар UNIX/BSD, що включає набір стандартних бібліотек мови сі (libc, libmatch, libpthread і так далі), а також інструменти командного рядка, набір шеллів (bash, tcsh і ksh) і демонів, таких як launchd та стандартний SSH-сервер. Останній, до речі, можна активувати шляхом редагування файлу /System/Library/LaunchDaemons/ssh.plist. Якщо, звичайно, джейлбрейкнути девайс.
На цьому відкрита частина ОС під назвою Darwin закінчується, і починається шар фреймворків, які таки утворюють те, що ми звикли вважати OS X/iOS.
Фреймворки
Darwin реалізує лише базову частину Mac OS/iOS, яка відповідає лише за низькорівневі функції (драйвери, запуск/зупинка системи, керування мережею, ізоляція додатків тощо). Та частина системи, яка видна користувачеві та додаткам, до його складу не входить і реалізована в так званих фреймворках - наборах бібліотек та сервісів, які відповідають у тому числі за формування графічного оточення та високорівневий API для сторонніх та стокових додатків
Як і в багатьох інших ОС, API Mac OS та iOS поділено на публічний та приватний. Стороннім програмам доступний виключно публічний і сильно урізаний API, проте jailbreak-додатки можуть використовувати і приватний.
У стандартній поставці Mac OS і iOS можна знайти десятки різних фреймворків, які відповідають за доступ до різних функцій ОС - від реалізації адресної книги (фреймворк AddressBook) до бібліотеки OpenGL (GLKit). Набір базових фреймворків для розробки графічних програм об'єднаний у так званий Cocoa API, свого роду метафреймворк, що дозволяє отримати доступ до основних можливостей ОС. У iOS він має ім'я Cocoa Touch і відрізняється від настільної версії орієнтацією на сенсорні дисплеї.
Не всі фреймворки доступні в обох ОС. Багато хто з них специфічний тільки для iOS. Як приклади можна навести AssetsLibrary, який відповідає за роботу з фотографіями та відео, CoreBlueTooth, що дозволяє отримати доступ до синезуба, або iAd, призначений для виведення рекламних оголошень у додатках. Інші фреймворки існують тільки в настільній версії системи, проте час від часу Apple переносить ті чи інші частини iOS в Mac OS або назад, як, наприклад, трапилося з фреймворком CoreMedia, який спочатку був доступний лише iOS.
Усі стандартні системні фреймворки можна знайти у системному каталозі /System/Library/Frameworks/. Кожен з них знаходиться у своєму власному каталозі, званому бандлом (boundle), який включає в себе ресурси (зображення та опис елементів інтерфейсу), хідери мови сі, що описують API, а також бібліотеку, що динамічно завантажується (у форматі dylib) з реалізацією фреймворку.
Одна з цікавих особливостей фреймворків – їхня версійність. Один фреймворк може мати відразу кілька різних версій, тому програма, розроблена для застарілих версій системи, продовжуватиме працювати, навіть незважаючи на зміни, внесені до нових версій ОС. Саме так реалізовано механізм запуску старих iOS-додатків у iOS 7 та вище. Програма, розроблена для iOS 6, буде виглядати і працювати саме так, якби вона була запущена в iOS 6.
SpringBoard
Рівнем вище є програми, системні та встановлювані з магазину додатків. Центральне місце серед них займає, звичайно, SpringBoard (тільки в iOS), що реалізує домашній екран (робочий стіл). Саме воно запускається першим після старту системних демонів, завантаження в пам'ять фреймворків і старту дисплейного сервера (він же менеджер композитингу, він Quartz Compositor), що відповідає за виведення зображення на екран.
SpringBoard - це сполучна ланка між операційною системою та її користувачем, графічний інтерфейс, що дозволяє запускати програми, перемикатися між ними, переглядати повідомлення та керувати деякими налаштуваннями системи (починаючи з iOS 7). Але це також і обробник подій, таких як торкання екрана або переворот пристрою. На відміну від Mac OS X, яка використовує різні додатки та демони-агенти для реалізації компонентів інтерфейсу (Finder, Dashboard, LaunchPad та інші), в iOS майже всі базові можливості інтерфейсу користувача, у тому числі екран блокування та «шторка», укладені в одному SpringBoard.
На відміну від інших стокових додатків iOS, які розташовуються в каталозі /Applications, SpringBoard нарівні з дисплейним сервером вважається частиною фреймворків і знаходиться в каталозі /System/Library/CoreServices/. Для виконання багатьох завдань він використовує плагіни, що лежать у /System/Library/SpringBoardPlugins/. Крім усього іншого, там можна знайти, наприклад, NowPlayingArtLockScreen.lockboundle, що відповідає за відображення інформації про композиції, що програється на екрані блокування, або IncomingCall.serviceboundle, відповідальний за обробку вхідного дзвінка.
Починаючи з iOS 6 SpringBoard поділено на дві частини: сам робочий стіл та сервіс BackBoard, відповідальний за комунікації з низькорівневою частиною ОС, що працює з обладнанням (рівень HAL). BackBoard відповідає за обробку таких подій, як торкання екрана, натискання клавіш, отримання показання акселерометра, датчика положення та датчика освітленості, а також керує запуском, призупиненням та завершенням програм.
SpringBoard і BackBoard мають настільки велике значення для iOS, що, якщо будь-яким чином їх зупинити, вся система застигне на місці і навіть запущена в даний момент програма не буде реагувати на торкання екрана. Це відрізняє їх від домашнього екрану Android, який є лише стандартним додатком, який можна зупинити, замінити або взагалі видалити з системи (у цьому випадку на екрані залишаться цілком робочі кнопки навігації і рядок стану зі «шторкою»).
Програми
На самій вершині цієї піраміди знаходяться програми. iOS розрізняє вбудовані (стокові) високопривілейовані програми та сторонні, що встановлюються з iTunes. І ті та інші зберігаються в системі у вигляді бандлів, багато в чому схожих на ті, що використовуються для фреймворків. Різниця полягає лише в тому, що бандл додатку включає дещо іншу метаінформацію, а місце динамічної бібліотеки займає виконуваний файл у форматі Mach-O.
Стандартний каталог зберігання стокових додатків – /Applications/. В iOS він абсолютно статичний та змінюється лише під час оновлень системи; користувач отримати доступ до нього не може. Сторонні програми, що встановлюються з iTunes, навпаки, зберігаються в домашньому каталозі користувача /var/mobile/Applications/ всередині підкаталогів, що мають вигляд 4-2-2-2-4, де два і чотири - це шістнадцяткові числа. Це так званий GUID – унікальний ідентифікатор, який однозначно ідентифікує додаток у системі та потрібен у тому числі для створення ізольованої пісочниці (sandbox).
Sandbox
В iOS пісочниці використовуються для ізолювання сервісів та додатків від системи та один від одного. Кожна стороння програма і більшість системних працюють у пісочниці. З технічної точки зору пісочниця є класичний для світу UNIX chroot, посилений системою примусового контролю доступу TrustedBSD MAC (модуль ядра sandbox.kext), яка відрізає додаткам не тільки доступ до файлів за межами домашнього каталогу, але й прямий доступ до заліза та багатьох системних функцій ОС.
Загалом укладений у sandbox додаток обмежений у таких можливостях:
Доступ до файлової системи за винятком власного каталогу та домашнього каталогу користувача.
Доступ до каталогів Media та Library всередині домашнього каталогу за винятком Media/DCIM/, Media/Photos/, Library/AddressBook/, Library/Keyboard/ та Library/Preferences/.
Доступ до інформації про інші процеси (додаток «вважає» себе єдиним у системі).
Прямий доступ до заліза (дозволено використовувати тільки Cocoa API та інші фреймворки).
Обмеження використання оперативної пам'яті (контролюється механізмом Jatsam).
Всі ці обмеження відповідають sandbox-профілю (набору обмежуючих правил) container і застосовуються до будь-якої сторонньої програми. Для стокових додатків, у свою чергу, можуть застосовуватися інші обмеження, м'якіші або жорсткіші. Як приклад можна навести поштовий клієнт (профіль MobileMail), який має такі ж серйозні обмеження, як і сторонні програми, але може отримати доступ до всього вмісту каталогу Library/. Зворотна ситуація - SpringBoard, що взагалі не має обмежень.
Усередині пісочниць працюють багато системні демони, включаючи, наприклад, AFC, призначений для роботи з файловою системою пристрою з ПК, але що обмежує область видимості тільки домашнім каталогом користувача. Усі доступні системні sandbox-профілі розташовуються в каталозі /System/Library/Sandbox/Profiles/* і є наборами правил, написаних мовою Scheme. Крім цього, додатки також можуть включати додаткові набори правил, званих entitlement. По суті, це все ті ж профілі, але вшиті прямо до бінарного файлу додатка (своєрідне самообмеження).
Сенс існування всіх цих обмежень подвійний. Перше (і головне) завдання, яке вирішує sandbox, - це захист від шкідливих програм. Разом з ретельною перевіркою опублікованих у iTunes додатків та забороною на запуск не підписаних цифровим ключем додатків (читай: будь-яких, отриманих не з iTunes) такий підхід дає чудовий результат і дозволяє iOS перебувати на вершині у списку найзахищеніших від вірусів ОС.
Друга проблема - це захист системи від самої себе та користувача. Баги можуть існувати як у стоковем софті від Apple, так і в головах користувачів. Sandbox захищає від обох. Навіть якщо зловмисник знайде дірку в Safari та спробує її експлуатувати, він все одно залишиться у пісочниці та не зможе нашкодити системі. А користувач не зможе «зламати свій улюблений телефон» і не напише гнівних відгуків на адресу Apple. На щастя, знаючі люди завжди можуть зробити jailbreak і обійти захист sandbox (власне, в цьому є сенс джейлбрейка).
Багатозадачність
Одна з найспірніших особливостей iOS – це реалізація багатозадачності. Вона начебто і є, а з іншого боку, її немає. У порівнянні з традиційними настільними ОС та горезвісним Android iOS не є багатозадачною операційною системою у звичному значенні цього слова і не дозволяє програмам вільно працювати у фоні. Натомість ОС реалізує API, який програма може використовувати для виконання окремих завдань, поки вона знаходиться у фоновому режимі.
Вперше такий API з'явився в iOS 4 (до цього фонові завдання могли виконувати тільки стокові програми) та нарощувався у міру розвитку операційної системи. Сьогодні (йдеться про iOS 7) так званий Background API дозволяє робити таке:
програвати аудіо;
здійснювати VoIP-дзвінки;
отримувати інформацію про зміну розташування;
отримувати push-сповіщення;
планувати відкладений висновок повідомлень;
вимагати додатковий час для завершення роботи після переходу у фоновий режим;
обмінюватись даними з підключеними до девайсу аксесуарами (у тому числі Bluetooth);
отримувати та надсилати дані по мережі (починаючи з iOS 7).
Такі обмеження на роботу у фоні необхідні в першу чергу для того, щоб зберегти заряд батареї та уникнути лагів інтерфейсу, так знайомих користувачам Android, де програми можуть робити у фоні все, що захочуть. Насправді Apple настільки сильно дбає про збереження батареї, що навіть реалізувала спеціальний механізм для угруповання фонових дій додатків та їх запуску в потрібні моменти, наприклад тоді, коли смартфон активно використовується, підключений до Wi-Fi-мережі або зарядного пристрою.
Шість стадій завантаження iOS
Boot ROM. Після увімкнення пристрою першим запускається мінімалістичний завантажувач, прошитий у постійну пам'ять пристрою. Його завдання - провести початкову ініціалізацію заліза та передати управління первинному завантажувачу LLB. Boot ROM завжди має заводську прошивку і не може бути оновлено.
Low Level Bootloader (LLB). Далі керування отримує LLB. Це первинний завантажувач, завдання якого - знайти в пам'яті пристрою iBoot, перевірити його цілісність і передати йому управління або переключити девайс в режим відновлення, якщо це не вдалося. Код LLB зберігається в NAND-пам'яті пристрою та оновлюється разом із встановленням нової версії прошивки. Крім іншого, він виводить на екран завантажувальний логотип.
iBoot. Це вторинний та основний завантажувач айдевайсів. Він включає драйвер файлової системи, за допомогою якого отримує доступ до вмісту NAND-пам'яті, знаходить ядро і передає йому управління. У iBoot також вбудований драйвер UART, за допомогою якого можна проводити налагодження ядра і ОС, підключивши аксесуар до COM-порту або USB-порту комп'ютера (за допомогою кабелю USB - UART).
Ядро. Тут все як завжди. Ядро здійснює ініціалізацію обладнання, після чого передає управління демону launchd.
Launchd. Це первинний процес iOS та Mac OS X, він підключає файлові системи, запускає демони/служби (наприклад, backupd, configd, locationd), дисплейний сервер, фреймворки, а на останньому етапі завантаження віддає керування SpringBoard. В iOS і Mac OS X launchd використовується як заміна стандартного /bin/init в UNIX, проте його функціональність набагато ширша.
SpringBoard. Ось і екран блокування!
Перші чотири етапи в цьому ланцюгу утворюють chain of trust, реалізований за допомогою звіряння цифрового підпису компонента, що завантажується. Цифровий підпис мають LLB, iBoot та ядро, що дозволяє виключити впровадження в ланцюжок хакнутого завантажувача або ядра, які можуть бути використані для завантаження сторонньої операційної системи або джейлбрейка. Єдиний спосіб обійти цей механізм - знайти дірку в одному із завантажувачів та скористатися нею для обходу перевірки. Свого часу було знайдено кілька таких дірок у Boot ROM (найбільш відомий експлойт limera1n від geohot, актуальний для iPhone 1-4), а на початку 2014 року в iBoot (хакер iH8sn0w, експлойт так і не був опублікований).
Утримуючи кнопку "Додому" при включенні iPhone, можна змусити iBoot завантажитися в так званий режим відновлення (Recovery), який дозволяє відновити прошивку iOS або оновити її, використовуючи iTunes. Однак механізм автоматичного OTA-оновлення використовує інший режим, який називається DFU (Device Firmware Upgrade), який активується на ранньому етапі завантаження відразу після Boot ROM і реалізований у двох компонентах: iBSS та iBEC. По суті це аналоги LLB і iBoot, кінцева мета яких - не завантажити ОС, а перевести смартфон в режим оновлення.
Джерела:
Last updated