轉(zhuǎn)載請注明出處:http://blog.csdn.net/zhaodai11?viewmode=contents
Binder是Android系統(tǒng)獨有的一種IPC通信機制,貫穿在整個Android系統(tǒng)中辉哥。
Binder通信使用C/S架構(gòu)搬设,除了C/S架構(gòu)所包括的Client端和Server端外汁汗,Android還有一個ServiceManager端,用來注冊和查詢服務(wù)。(注意這里的ServiceManager是指底層和驅(qū)動交互實現(xiàn)服務(wù)的注冊和查詢癣猾,并非Java類中的ServiceManager,這點很容易搞混)下面這張來自鄧凡平老師博客的圖片可以形象描繪出他們?nèi)咧g的關(guān)系余爆。
根據(jù)上面的圖,可以看出:
- Server進程注冊服務(wù)到ServiceManager蛾方,此時Server是ServiceManager的客戶端像捶,ServiceManager是服務(wù)端上陕。
- Client進程使用服務(wù),必須先要通過ServerManager獲取相應(yīng)的服務(wù)信息拓春。此時Client是客戶端释簿,ServiceManager是服務(wù)端。
- Client根據(jù)得到的服務(wù)信息建立與服務(wù)所在的Server進程通信的通路硼莽,然后就可以直接與Service交互了庶溶,此時Client是客戶端,Server是服務(wù)端懂鸵。
上面提到的ServiceManager很容易被大家誤以為是Java中ServiceManager偏螺,它真正的實現(xiàn)是在 source/android-6.0.1_r17/frameworks/native/cmds/servicemanager/service_manager.c中
//...
//svcmgr_handler是真正負(fù)責(zé)查找和添加服務(wù)信息的函數(shù)
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s, len));
return -1;
}
if (sehandle && selinux_status_updated() > 0) {
struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
if (tmp_sehandle) {
selabel_close(sehandle);
sehandle = tmp_sehandle;
}
}
switch(txn->code) {
//獲取某個Service信息
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
//添加service到servicemanager
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
//獲取當(dāng)前系統(tǒng)已經(jīng)注冊的所有service名稱
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
//.....
以上是簡單介紹,詳細(xì)原理匆光,給大家推薦兩個講解Binder比較全面細(xì)致的博客:
鄧凡平老師:http://blog.csdn.net/innost/article/details/47208049
羅升陽老師:http://blog.csdn.net/Luoshengyang/article/list/4
在Android系統(tǒng)源碼中套像,使用Binder時用了很多的代理,包括在很多博客的示例中也一樣终息,讓人感覺眼花繚亂夺巩。其實弄懂原理不用寫代理那些也能實現(xiàn)。
服務(wù)端:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <binder/IPCThreadState.h>
#include "binder/IPCThreadState.h"
#include "binder/IServiceManager.h"
#include "TestBinderService.h"
using namespace android;
int main()
{
printf("-------服務(wù)端啟動---------\n");
// 獲得一個ProcessState實例
sp<ProcessState> proc(ProcessState::self());
//調(diào)用defaultServiceManager獲取ServiceManger
sp<IServiceManager> sm = defaultServiceManager();
//創(chuàng)建TestBinderService服務(wù) 將服務(wù)注冊到ServiceManager中
TestBinderService::Instance();
//創(chuàng)建一個線程池
ProcessState::self()->startThreadPool();
//
IPCThreadState::self()->joinThreadPool(true);
return 0;
}
TestBinderService::Instance()實現(xiàn)
#define BINDER_TESTSERVICE "TestBinderService"
namespace android
{
TestBinderService* TestBinderService::gScrService = NULL;
int TestBinderService::Instance()
{
if(!gScrService)
{
//創(chuàng)建服務(wù)
gScrService = new TestBinderService();
//將服務(wù)注冊到serviceManager中
int ret = defaultServiceManager()->addService(String16(BINDER_TESTSERVICE), gScrService);
return ret;
}
return 0;
}
//.......
//與客戶端進行通信
status_t TestBinderService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
printf("命令碼 code=%d\n",code);
switch (code)
{
case BINDER_send:
{
int ivalue = data.readInt32();
String8 s = data.readString8();
// string str(s);
const char *cptr = s;
printf("服務(wù)端接收信息:數(shù)字 = %d 字符串 = %s\n", ivalue,cptr);
// reply->writeInt32(200);
String8 msg("收到了 謝謝V苷浮A!");
reply->writeString8(msg);
}
break;
case BINDER_get:
{
// int ivalue = data.readInt32();
String8 s = data.readString8();
const char *cptr = s;
printf("服務(wù)端接收信息:信息 = %s\n",cptr);
reply->writeInt32(600);
String8 msg("給你發(fā)個信息");
reply->writeString8(msg);
}
break;
default:
break;
}
return 0;
}
}
客戶端:
//獲取相關(guān)服務(wù)信息
TestBinderClient* client = new TestBinderClient();
//與服務(wù)端通信
client->sendMsg();
client->getMsg();
return (int)client;
TestBinderClient.cpp
sp<IBinder> binder;
TestBinderClient::TestBinderClient()
{
// printf("TestBinderClient::%s\n", __FUNCTION__);
getScrService();
}
TestBinderClient::~TestBinderClient()
{
// printf("TestBinderClient::%s\n", __FUNCTION__);
binder = 0;
}
void TestBinderClient::getScrService()
{
//獲取serviceManager
sp<IServiceManager> sm = defaultServiceManager();
//查找相關(guān)服務(wù)信息
binder = sm->getService(String16(BINDER_TESTSERVICE));
if(binder == 0)
{
printf("getScrService failed\n");
return;
}
}
//使用服務(wù)進行進程間通信
int TestBinderClient::sendMsg()
{
// printf("TestBinderClient::%s\n", __FUNCTION__);
Parcel data, reply;
data.writeInt32(100);
String8 msg("給你發(fā)個信息");
data.writeString8(msg);
binder->transact(BINDER_send, data, &reply);
// int ret = reply.readInt32();
String8 s = reply.readString8();
const char *cptr = s;
printf("客戶端接收回復(fù)信息:信息 = %s\n",cptr);
return 0;
}
int TestBinderClient::getMsg()
{
// printf("TestBinderClient::%s\n", __FUNCTION__);
Parcel data, reply;
// data.writeInt32(0);
String8 msg("給我來個信息");
data.writeString8(msg);
binder->transact(BINDER_get, data, &reply);
int ret = reply.readInt32();
String8 s = reply.readString8();
const char *cptr = s;
printf("客戶端接收回復(fù)信息:數(shù)字 = %d 字符串 = %s\n",ret,cptr);
return ret;
}
運行效果圖:
服務(wù)端:
客戶端:
編譯代碼需要在源碼環(huán)境下編譯续镇,將服務(wù)端和客戶端編譯成兩個可執(zhí)行文件征绎,push到手機中執(zhí)行。
當(dāng)然也可以增加編寫JNI接口磨取,編譯成靜態(tài)庫文件人柿,在APP中進行調(diào)用。不過這樣需要APP獲取ROOT權(quán)限或者將APP變成系統(tǒng)應(yīng)用忙厌。
相關(guān)代碼已經(jīng)傳到github: https://github.com/zhaodaizheng/BinderTest