ProcessState
一個單例類,開啟了Binder裝置、mHandleToObject快取了一堆BpBinder、快取了context_mgr、啟動binder執行緒
IPCThreadState
一個單例,保持了mProcess、儲存了程式pid和uid資訊、joinThreadPool讓Binder執行緒進入訊息迴圈getAndExecuteCommand、transact用來傳送訊息並接受返回。
下面是幾個通訊最小操作單元:
writeTransactionData 將資料寫入mOut緩衝器
talkWithDriver 一次ioctrl操作
waitForResponse 等待返回
executeCommand 執行命令
sendReply 傳送返回訊息
因此傳送transact = writeTransactionData + talkWithDriver + waitForResponse getAndExecuteCommend = talkWithDriver + executeCommand + sendReply
service_manager.c
binder_open -> binder_become_context_mgr -> binder_loop -> binder_parse -> BR_TRANSACTION -> func -> svcmgr_handle -> binder_send_reply
name, handle -----> svcinfo_list -> svcinfo -> handle、binder_node
複製程式碼
main_mediaserver.cpp
sp<ProcessState> proc(ProcessState::self());
MediaPlayerService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
複製程式碼
因為ProcessState是單例,多以必然會在當前程式開啟一次binder裝置檔案
其中MediaPlayerService繼承自BnMediaPlayService
而BnMediaPlayerService繼承自BnInterface
因此MediaPlayerService繼承與BnMediaPlayerService和IMediaPlayerService
繼承關係為:MediaPlayerService <- BnMediaPlayerService <- BnInterface 、IMediaPlayerService <- BBinder -> IBinder
因此MediaPlayerService可以看出是BBinder的包裝類,onTransact最終交由前者重寫的函式處理 資料最終根據code分發到IMediaPlayerService的介面中
IMediaPlayerService: sp createMediaRecorder() sp createMetadataRetriever() sp create(); status_t decode(...);
智慧時刻:
1.建構函式: 建立了XXXService -> IXXXService -> BnXXXService -> BBinder (訊息最終交由BBinder路由,分發到IXXXService不同函式中)
2.instantiate: IServiceManager->defaultServiceManager->addService(xxx, new XXXService) 首先拿到了BpServiceManager即BpBinder(0), 不明白看下面的解釋
呼叫了BpServiceManager-BpBinder(0)->transact, 程式碼看下面
IServiceManager
單例defaultServiceManager(),從ProcessState中取出了BpBinder,然後構建了IServiceManager和BpServiceManager的子類BpServiceManager (Bpxxx必須要繼承自Ixxx和BpInterface)
函式理解一下:
virtual sp<IBinder> getService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
複製程式碼
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
複製程式碼
總體上來說,是從ProcessState中利用handle拿到了BpBinder,然後構建了外觀類BpServiceManager,但最終通訊還是利用BpBinder->transact,實際上是利用IPCThreadState::transact傳送訊息,該函式利用mIn和mOut快取資料,利用BpBinder(0)->transact(ADD_SERVICE_TRANSACTION, data, &reply)利用一次ioctrl(fd, BC_CMD, &bwr)寫操作和一次ioctrl(fd, BC_CMD, &bwr)讀操作,來與驅動通訊。關注一下傳送的命令,ADD_SERVICE_TRANSACTION居然還藏著一個祕密,看看它是在哪被接收的吧!
IInterface.h
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
複製程式碼
該函式很常見,由一個BpBinder生成一個外觀類BpXXXService(繼承自BpRefBase、INTERFACE)
BpINTERFACE -> BpInterface 、INTERFACE、BpRefBase
複製程式碼
因此interface_cast相當於new BpINTERFACE(obj)
interface_cast相當於生成了IServiceManager子類new BpServiceManager(obj)
下面的程式碼很魔性,理解一下:
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
複製程式碼
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
複製程式碼
74#define DECLARE_META_INTERFACE(INTERFACE)
75 static const android::String16 descriptor;
76 static android::sp<I##INTERFACE> asInterface( const android::sp<android::IBinder>& obj);
78 virtual const android::String16& getInterfaceDescriptor() const;
79 I##INTERFACE();
80 virtual ~I##INTERFACE();
81
82
83#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
84 const android::String16 I##INTERFACE::descriptor(NAME);
85 const android::String16& I##INTERFACE::getInterfaceDescriptor() const {
87 return I##INTERFACE::descriptor;
88 }
89 android::sp<I##INTERFACE> I##INTERFACE::asInterface(const android::sp<android::IBinder>& obj)
91 {
92 android::sp<I##INTERFACE> intr;
93 if (obj != NULL) {
94 intr = static_cast<I##INTERFACE*>(obj->queryLocalInterface( I##INTERFACE::descriptor).get());
97 if (intr == NULL) {
98 intr = new Bp##INTERFACE(obj);
99 }
100 }
101 return intr;
102 }
103 I##INTERFACE::I##INTERFACE() { }
104 I##INTERFACE::~I##INTERFACE() { }
複製程式碼
BpBinder
繼承自IBinder,成員變數mHandle,關鍵函式transact呼叫IPCThreadState::transact
IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
複製程式碼
最終呼叫了talkWithDriver呼叫得到reply
Parcel.cpp
雜項資料和Binder的包裝類,主要包含mData和mObjects
依靠(uint8_t*)malloc(desired)來分配記憶體,並不斷擴容
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
複製程式碼
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
複製程式碼
1.以上函式說明BpBinder傳遞時,最終建立了一個flat_binder_object,並將handle寫入了flat_binder_object.handle中,最終記錄到了核心驅動binder_node.handle中
2.同理對於BBinder,將BBinder的物件地址寫到了flat_binder_object.binder和flat_binder_object.cookie中,最終記錄到了binder_node的binder和cookie中。傳送端傳送訊息時,先根據handle在核心中找到binder_ref,即找到了binder_proc和binder_node,選擇喚醒binder_proc上的等待佇列即喚醒binder執行緒,並將訊息交由binder執行緒返回給使用者空間,使用者空間取出flat_binder_object,根據裡面的cookie可以得到BBinder物件。最終根據code分發給BBinder的處理函式onTransact中,由BpXXX來分發給IXXX。
binder驅動
binder執行緒ioctrl讀資料進入休眠
IPCThreadState::transact 進行寫資料
第一步:開始寫資料,記錄到binder_work, 並喚醒binder執行緒,binder_thread_read從wait_event中醒來,並將binder_work中的buffer資料取出來放到binder_transaction_data中,最後利用copy_to_user(ptr, &tr, sizeof(tr))寫入使用者空間binder_write_read bwr的ptr,函式返回。至此,上層就可以從ptr取出資料,並進行資料分發了。
從這裡可以看出來:
A.使用者空間BpXXX裡面使用Parcel寫入strongBinder資料flat_binder_object
B.使用者空間IPCThreadState中首先將flat_binder_object寫入binder_transaction_data的中,並寫入mOut中,接著從mOut中取出資料放入到binder_write_read.write_buffer中,最後呼叫ioctrl(fd, BC_CMD, bwr)傳送資料了
binder_transaction_data tr;
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
複製程式碼
資料包裝的結構為 binder_write_read包含binder_transaction_data包含flat_binder_object,額外資料放到了binder_transaction_data->data.ptr.buffer中,而flat_binder_object放到了data_ptr_offsets中
應用層Parcel -> flat_binder_object + data -> binder_transaction_data -> binder_write_read
進入核心空間 -> 傳送端的binder_write_read 取出binder_transaction_data,放入接收端的binder_write_read.buffer中,至此已經將資料傳入到應用接收層了
binder通訊總結
- 第一階段:新建服務,在核心中建立binder_node (第一次與實名binder通訊時,在核心中建立)
- 第一階段:傳送binder_node到一個程式,建立binder_ref引用
- 第三階段:利用binder_ref傳送資料到binder_node程式,並進入等待reply
- 第四階段:binder_node程式接收並處理資料,傳送binder_reply
binder資料流向
傳送端 | 接收端 |
---|---|
XXXService->IXXXService | |
BpXXXService | BnXXXService |
BpInterface | BnInterface |
BpBinder | BBinder |
IPCThreadState::transact | IPCThreadState::getAndExecuteCommand |
/dev/binder | /dev/binder |
binder_ioctl | binder_ioctl |
binder_write_thread | binder_read_transaction |
binder_transaction | binder_transaction |