macOS GCD - Grand Central Dispatch
Базова інформація
Grand Central Dispatch (GCD), також відомий як libdispatch, доступний як в macOS, так і в iOS. Це технологія, розроблена Apple для оптимізації підтримки програм для одночасного (багатопотокового) виконання на багатоядерному обладнанні.
GCD надає та керує чергами FIFO, до яких ваша програма може надсилати завдання у вигляді блок-об'єктів. Блоки, надіслані в черги розподілу, виконуються в пулі потоків, повністю керованих системою. GCD автоматично створює потоки для виконання завдань у чергах розподілу та планує виконання цих завдань на доступних ядрах.
У підсумку, для виконання коду паралельно, процеси можуть надсилати блоки коду в GCD, який буде відповідати за їх виконання. Таким чином, процеси не створюють нові потоки; GCD виконує заданий код за допомогою свого власного пулу потоків.
Це дуже корисно для успішного управління паралельним виконанням, значно зменшуючи кількість потоків, які створюють процеси, та оптимізуючи паралельне виконання. Це ідеально підходить для завдань, які вимагають великої паралельності (брутфорс?) або для завдань, які не повинні блокувати основний потік: наприклад, основний потік на iOS відповідає за взаємодію з користувачем, тому будь-яка інша функціональність, яка може призвести до зависання додатка (пошук, доступ до веб-сайту, читання файлу...), керується цим способом.
Objective-C
У Objetive-C є різні функції для відправлення блоку на виконання паралельно:
dispatch_async: Надсилає блок для асинхронного виконання в чергу розподілу та повертається негайно.
dispatch_sync: Надсилає блок на виконання та повертається після завершення виконання цього блоку.
dispatch_once: Виконує блок лише один раз за час існування програми.
dispatch_async_and_wait: Надсилає робочий елемент на виконання та повертається лише після завершення його виконання. На відміну від
dispatch_sync
, ця функція поважає всі атрибути черги під час виконання блоку.
Ці функції очікують ці параметри: dispatch_queue_t
queue,
dispatch_block_t
block
Ось структура блоку:
І ось приклад використання паралелизму з dispatch_async
:
Swift
libswiftDispatch
- це бібліотека, яка надає зв'язки Swift до фреймворку Grand Central Dispatch (GCD), який спочатку був написаний на C.
Бібліотека libswiftDispatch
обгортає API GCD на C в більш дружній для Swift інтерфейс, що робить роботу з GCD легшою та інтуїтивно зрозумілою для розробників Swift.
DispatchQueue.global().sync{ ... }
DispatchQueue.global().async{ ... }
let onceToken = DispatchOnce(); onceToken.perform { ... }
async await
var (data, response) = await URLSession.shared.data(from: URL(string: "https://api.example.com/getData"))
Приклад коду:
Frida
Наступний скрипт Frida може бути використаний для підключення до кількох функцій dispatch
та витягування назви черги, стеку викликів та блоку: https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js
Ghidra
Наразі Ghidra не розуміє ні структуру ObjectiveC dispatch_block_t
, ні swift_dispatch_block
.
Тому, якщо ви хочете, щоб він їх розумів, ви можете просто оголосити їх:
Потім знайдіть місце в коді, де вони використовуються:
Зверніть увагу на всі посилання на "block", щоб зрозуміти, як ви можете зрозуміти, що структура використовується.
Клацніть правою кнопкою миші на змінну -> Перейменувати змінну та виберіть у цьому випадку swift_dispatch_block
:
Ghidra автоматично перепише все:
Last updated