1. 介紹
Binder是Android下基於C/S架構的IPC機制,基於開源OpenBinder
從實現上來說可分為Binder驅動、ServiceManager、Server、Client四個組成部分
2. Binder驅動
Binder驅動代碼主要位於drivers/android目錄
2.1 數據結構
數據結構 | 說明 |
binder_device | binder設備,系統初始化時會定義binder、hwbinder、vndbinder三個設備 |
binder_context | binder上下文,每個binder設備包含一個上下文結構 |
binder_proc |
binder進程記錄,每個打開binder設備的進程均包含該結構,用來記錄該進程的各種信息和狀態。例如:線程表、binder節點表、節點引用表 |
binder_thread | binder線程,記錄了線程相關的信息,例如需要完成的任務等 |
binder_node | binder節點 |
binder_transaction | binder事務 |
binder_buffer | binder緩沖區,由mmap創建,用於binder事務 |
binder_alloc | binder proc的地址空間 |
binder_ref | binder引用 |
2.2 初始化
binder_init() /* * 創建如下目錄和文件
* 目錄
* /sys/kernel/debug/binder
* /sys/kernel/debug/binder/proc
* 文件
* $(BINDER)/state -- 記錄狀態信息
* $(BINDER)/stats -- 記錄統計信息
* $(BINDER)/transactions -- 記錄transaction相關信息
* $(BINDER)/transaction_log -- 記錄transaction日志相關信息
* $(BINDER)/failed_transaction_log -- 記錄失敗的transaction日志相關信息
* 文件讀取函數依次為
* binder_state_show() * binder_stats_show() * binder_transactions_show() * binder_transactions_log_show() * - * $(BINDER) = /sys/kernel/debug/binder/ */ debugfs_create_dir("binder") debugfs_create_dir("proc") debugfs_create_dir("state") debugfs_create_dir("stats") debugfs_create_dir("transactions") debugfs_create_dir("transaction_log") debugfs_create_dir("failed_transaction_log") /* * 注冊/dev/binder, /dev/hwbinder, /dev/vndbinder設備
*/ init_binder_device() misc_register(binder_fops) /* binder設備操作集 */ static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, .compat_ioctl = binder_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, .release = binder_release, };
2.3 打開
當應用打開一個binder設備時,在內核中中會執行binder_open
- 分配並創建binder_proc結構
- 初始化binder_proc的context、tsk、todo、default_priority、context、alloc等成員變量
- 將binder_proc保存到file::private_data結構中, 以之后的mmap、ioctl中獲取
- 將binder_proc::proc_node插入全局變量binder_procs中
- 創建/sys/kernel/debug/binde/proc/`pid`文件
2.4 映射
當應用對binder設備執行mmap時,mmap首先會在調用進程的虛擬地址空間(struct vm_area_struct vma)創建一個地址到文件的映射,隨后在內核中會執行binder_mmap
- 初始化vma的vm_flags、vm_ops、vm_private_data成員變量
- 調用binder_alloc_mmap_handler(struct binder_alloc, struct vm_area_struct)建立映射
-- 通過get_vm_area()在內核vmalloc區域獲取vma相同大小連續空間(struct vm_struct area)
-- 根據area初始化binder_alloc的buffer、buffer_size、user_buffer_offset等成員變量
-- 通過kzalloc分配物理頁表項(struct page)並賦值給binder_alloc::binder_lru_page
-- 通過kzalloc分配一個binder_buffer結構用來分配物理頁,對vmalloc區域建立頁表映射關系
2.5 操作
應用執行ioctl時在內核執行binder_ioctl
命令 | 參數 | 含義 |
BINDER_WRITE_READ | struct binder_write_read | 向驅動讀取和寫入數據.可同時讀和寫 |
BINDER_SET_MAX_THREADS |
int | 設置線程池的最大的線程數,達到上限后驅動將不會在通知應用層啟動新線程 |
BINDER_SET_CONTEXT_MGR |
- | 將本進程設置為binder系統的管理進程,servicemanager進程使用,這個命令且只能調用一次 |
BINDER_THREAD_EXIT |
- | 通知驅動當前線程即將退出,以便驅動清理該線程相關的數據 |
BINDER_VERSION | struct binder_version | 獲取binder的版本號 |
值得一說的是首次調用ioctl時會為進程創建一個線程, 具體可參考binder_get_thread()
3. servicemanager
3.1 介紹
servicemanager由init在post-fs階段啟動,Android N以后由三個服務組成
- servicemanager: 使用/dev/binder設備,用於framework/app processes IPC
- hwservicemanager: 使用/dev/hwbinder設備,用於framework/vendor processes IPC
- vndservicemanager: 使用/dev/vndbinder設備,用於vendor/vendor processes IPC
servicemanager/vndservicemanager代碼位於frameworks/native/cmds/servicemanager
hwservicemanager代碼位於system/hwservicemanager(此處不分析)
servicemanager集中管理系統內的所有服務,提供了注冊、查找、遍歷服務的功能
3.2 代碼分析
/* * 服務列表 * struct svcinfo *svclist */ struct svcinfo { struct svcinfo *next; uint32_t handle; struct binder_death death; int allow_isolated; uint32_t dumpsys_priority; size_t len; uint16_t name[0]; }; main() binder_open() // 打開binder設備 open("/dev/binder" or "dev/vndbinder") // 獲取內核binder版本 ioctl(binder_fd, BINDER_VERSION, ) // 映射128k大小空間 mmap(128 * 1024) // 設置binder上下文管理者 ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0) // selinux相關設置 ... // 進入主循環 binder_loop() // 讀取請求 ioctl(binder_fd, BINDER_WRITE_READ, ) // 事件處理 binder_parse() // 處理BR_TRANSACTION事件 svcmgr_handler() // 查找服務 do_find_service() // 注冊服務 do_add_service()
4. Native Binder
Android中實現了如下native binder庫,
- libbinder: 用於servicemanager/vndservicemanager, 代碼位於frameworks/native/libs/binder
- libhwbinder: 用於hwservicemanager, 代碼位於system/libhwbinder
這里主要介紹一下libbinder庫、IServiceManager、libbinder使用實例
4.1 基礎類
/*
* I: Interface, 服務接口 * B: Binder * n: native, 服務方, 也即本地端 * p: proxy, 代表了調用方, 也即遠程端 */ android::BpRefBase - RefBase的子類, 提供remote()方法獲取遠程Binder android::IBinder - Binder抽象接口, BBinder和BpBinder都是該類的子類 android::IInterface: - Binder服務接口基類, Binder服務通常需要同時提供本地接口和遠程接口 android::IPCThreadState - 使用Binder的線程, 封裝了與Binder驅動通信的邏輯 android::ProcessState - 使用Binder的進程 android::BBinder - 本地Binder, 實現接受請求的接口 android::BpBinder - 遠程Binder, 實現發送請求的接口 android::BnInterface - 本地接口的基類, 繼承自BBinder, 本地接口是需要服務中真正實現的接口集 android::BpInterface - 遠程接口的基類, 繼承自Bpinder, 遠程接口是供客戶端調用的接口集
這些類的關系如下圖
下面介紹兩個重要的宏
/* * DECLARE_META_INTERFACE定義了 * - descriptor * - asInterface() * - getInterfaceDescriptor() * - constructor()/destructor() */ IMPLEMENT_META_INTERFACE(xxx, xxxdesc) #define DECLARE_META_INTERFACE(INTERFACE) \ static const ::android::String16 descriptor; \ static ::android::sp<I##INTERFACE> asInterface( \ const ::android::sp<::android::IBinder>& obj); \ virtual const ::android::String16& getInterfaceDescriptor() const; \ I##INTERFACE(); \ virtual ~I##INTERFACE(); \ /* * IMPLEMENT_META_INTERFACE實現了 * - descriptor * - asInterface() * - getInterfaceDescriptor() * - constructor()/destructor() */ #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const ::android::String16 I##INTERFACE::descriptor(NAME); \ const ::android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const ::android::sp<::android::IBinder>& obj) \ { \ ::android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \
4.2 IServiceManager
android::IServiceManager充當了servicemanager的代理接口,用來訪問servicemanager提供的服務
可通過defaultServiceManager()來獲取IServiceManager實例
class IServiceManager : public IInterface { public: sp<IBinder> getService(const String16& name); sp<IBinder> checkService(const String16& name); status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated, int dumpsysFlags) Vector<String16> listServices(int dumpsysFlags); }; /* * defaultServiceManager = new BpServiceManager(new BpBinder(0)); */ sp<IServiceManager> defaultServiceManager(); defaultServiceManager() ProcessState::self() new ProcessState("/dev/binder") open_driver("/dev/binder") mmap() ProcessState::getContextObject(NULL) getStrongProxyForHandle(0) BpBinder::create(NULL) new BpBinder(NULL, uid) interface_cast<IserviceManager>(new BpBinder()) IserviceManager::asInterface(new BpBinder()) new BpServiceManager(new BpBinder()) BpInterface::BpInterface() BpRefBase::BpRefBase()
4.3 實例
這里介紹以下使用libbinder實現native server和client的方法,以IFixMe為例
接口實現
// .h namespace android {
enum {
COMMAND_ONE = IBinder::FIRST_CALL_TRANSACTION,
COMMAND_TWO
};
class IFixMe: public IInterface { public: DECLARE_META_INTERFACE(FixMe) virtual int func1(const String16& str1) = 0; virtual void func2() = 0; } } //.cpp using namespace android; IMPLEMENT_META_INTERFACE(FixMe, "FixMeDesc");
Server實現
// .h class BnFixMe : public BnInterface<IFixMe> { public: virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0); }; // .cpp status_t BnFixMe::onTransact(uint32_t code,const Parcel & data,
Parcel * reply, uint32_t flags) { switch(code) { case COMMAND_ONE: { CHECK_INTERFACE(IFixMe, data, reply); const char *str = data.readCString(); // Do something with input string reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } case COMMAND_TWO: { CHECK_INTERFACE(IFixMe, data, reply); // Do something reply->writeNoException(); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } }
Client實現
// *.cpp class BpFixMe : public BpInterface<IFixMe> { public: BpFixMe(const sp<IBinder>& impl) : BpInterface<IFixMe>(impl){}; int func1(const char *str) { Parcel data, reply; data.writeInterfaceToken(IFixMe::getInterfaceDescriptor()); data.writeCString(str); remote()->transact(COMMAND_ONE, data, &reply); int32_t exception = reply.readExceptionCode(); return reply.readInt32(); } void func2() { Parcel data, reply; data.writeInterfaceToken(IFixMe::getInterfaceDescriptor()); remote()->transact(COMMAND_TWO, data, &reply); } };
測試程序
#define SERVICE_NAME "FixMe" // server test binary int main() { defaultServiceManager()->addService(String16(SERVICE_NAME), new BnFixMe()); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; } // client test binary int main() { sp<IBinder> binder = defaultServiceManager()->getService(String16(SERVICE_NAME)); // equal IFixMe::asInterface(binder) sp<IFixMe> service = interface_cast<IFixMe>(binder); service->func1("giveme5") service->func2() return 0; }
TIPS: 通常把接口實現、Server實現、Client實現放在一起
其他實例可參考MediaPlayerService、<NativeBinderTest>、<Android-HelloWorldService>、<native-service>
參考:
<理解Android Binder機制>
<Binder機制情景分析之深入驅動>
<Binder機制情景分析之native層淺析>