android 系统核心机制binder(03)binder C++层实现

112 篇文章 81 订阅

该系列文章总纲链接:专题分纲目录 android 系统核心机制 binder


本章关键点总结 & 说明:

这里主要关注➕ Binder C++部分即可,看到,也是本章节的核心内容,主要就是以C++封装的框架为主来解读binder。

之前的博客主要针对于底层驱动binder的 数据交互以及 如何注册服务、获取服务、使用服务;而android的C++层实际上仅仅是换了一种方式,加了框架的理念来更好的复用驱动层的代码而已;同时java层的封装更是为了上层的使用方便。

1 binder C++层实现框架案例

1.1 binder的C++ 相关类图 关系说明:

这里仅仅从 Binder的 客户端和服务端通信IPC角度 来看Binder的 C++实现框架,红色部分的mRemote在使用中 实际上就是 BpBinder,蓝色部分为 用户在使用 该binder C++框架时 需要自己编写的类,而其他未标明的类是系统本身自带的。该图描述了BpBinder BBinder IBinder BpRefBase IInterface BpInterface BnInterface BpHelloService BnHelloService之间的关系。

1.2 binder C++层 HelloService demo 代码实现

这里以HelloService为例,解读 binder的C++框架,看看几个关键类IHelloService、BpHelloService、BnHelloService 如何使用?

@1 IHelloService.h的实现如下:

#ifndef ANDROID_IHELLOERVICE_H
#define ANDROID_IHELLOERVICE_H

#include <utils/Errors.h>  // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#define HELLO_SVR_CMD_SAYHELLO     1
#define HELLO_SVR_CMD_SAYHELLO_TO  2
#define HELLO_SVR_CMD_GET_FD       3 //后面会单独分析这个部分

namespace android {
class IHelloService: public IInterface
{
public:
    DECLARE_META_INTERFACE(HelloService);
	virtual void sayhello(void) = 0;
	virtual int sayhello_to(const char *name) = 0;
	virtual int get_fd(void) = 0;
};

class BnHelloService: public BnInterface<IHelloService>
{
private:
	int fd;
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
	virtual void sayhello(void);
	virtual int sayhello_to(const char *name);
	virtual int get_fd(void); //后面会单独分析这个部分

	BnHelloService();
	BnHelloService(int fd);
};
}
#endif

@2 BnHelloService.cpp的实现如下(这里参考了 frameworks\av\media\libmedia\IMediaPlayerService.cpp):

#define LOG_TAG "HelloService"
#include "IHelloService.h"
namespace android {
BnHelloService::BnHelloService()
{
}

BnHelloService::BnHelloService(int fd)
{
	this->fd = fd;
}

status_t BnHelloService::onTransact( uint32_t code,
                                const Parcel& data,
                                Parcel* reply,
                                uint32_t flags)
{
    switch (code) {
        case HELLO_SVR_CMD_SAYHELLO: {
			sayhello();
			reply->writeInt32(0);  /* no exception */
            return NO_ERROR;
        } break;
		
        case HELLO_SVR_CMD_SAYHELLO_TO: {
			//@1 读取传入参数,并转换
			int32_t policy =  data.readInt32();
			String16 name16_tmp = data.readString16(); /* IHelloService */
			String16 name16 = data.readString16();
			String8 name8(name16);
			//@2 调用对应函数
			int cnt = sayhello_to(name8.string());

			//@3 返回值转换,并发送
			reply->writeInt32(0);  /* no exception */
			reply->writeInt32(cnt);
			
            return NO_ERROR;
        } break;

        case HELLO_SVR_CMD_GET_FD: {
			int fd = this->get_fd();
			reply->writeInt32(0);  /* no exception */
			reply->writeDupFileDescriptor(fd);
            return NO_ERROR;
        } break;		
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

void BnHelloService::sayhello(void)
{
	static int cnt = 0;
	ALOGI("say hello : %d\n", ++cnt);
}

int BnHelloService::sayhello_to(const char *name)
{
	static int cnt = 0;
	ALOGI("say hello to %s : %d\n", name, ++cnt);
	return cnt;
}

int BnHelloService::get_fd(void)
{
	return fd;
}
}

@3 BpHelloService.cpp的实现如下:

#include "IHelloService.h"
namespace android {

class BpHelloService: public BpInterface<IHelloService>
{
public:
    BpHelloService(const sp<IBinder>& impl): BpInterface<IHelloService>(impl)
    {
    }

	void sayhello(void)
	{
        Parcel data, reply;
        data.writeInt32(0);
		data.writeString16(String16("IHelloService"));
        remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
	}
	
	int sayhello_to(const char *name)
	{
		Parcel data, reply;
		int exception;

		data.writeInt32(0);
		data.writeString16(String16("IHelloService"));
		data.writeString16(String16(name));
		remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
		exception = reply.readInt32();
		if (exception)
		    return -1;
		else
		    return reply.readInt32();
	}

	int get_fd(void)
	{
		Parcel data, reply;
		int exception;

		data.writeInt32(0);
		data.writeString16(String16("IHelloService"));
		remote()->transact(HELLO_SVR_CMD_GET_FD, data, &reply);

		exception = reply.readInt32();
		if (exception)
			return -1;
		else
		{
			int rawFd = reply.readFileDescriptor();
			return dup(rawFd);
		}
	}
};
IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");
}

@4 客户端代码 Test_client.cpp的实现如下:

#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0

#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <unistd.h>

#include "IHelloService.h"

using namespace android;

/* ./test_client <hello>
 * ./test_client <readfile>
 * ./test_client <hello> <name>
 */
 
int main(int argc, char **argv)
{
	int cnt;
	
	if (argc < 2){
        ALOGI("Usage:\n");
        ALOGI("%s <readfile>\n", argv[0]);
        ALOGI("%s <hello|goodbye>\n", argv[0]);
        ALOGI("%s <hello|goodbye> <name>\n", argv[0]);
        return -1;
	}

	/* getService */
	/* 打开驱动, mmap */
	sp<ProcessState> proc(ProcessState::self());

	/* 获得BpServiceManager */
	sp<IServiceManager> sm = defaultServiceManager();

	if (strcmp(argv[1], "hello") == 0)
	{
		sp<IBinder> binder = sm->getService(String16("hello"));
		if (binder == 0)
		{
		    ALOGI("can't get hello service\n");
			return -1;
		}

		// service肯定是BpHelloServie指针
		sp<IHelloService> service = interface_cast<IHelloService>(binder);

		/* 调用Service的函数 */
		if (argc < 3) {
			service->sayhello();
			ALOGI("client call sayhello");
		}
		else {
			cnt = service->sayhello_to(argv[2]);
			ALOGI("client call sayhello_to, cnt = %d", cnt);
		}
	}
	else if (strcmp(argv[1], "readfile") == 0)
	{

		sp<IBinder> binder =
		    sm->getService(String16("hello"));

		if (binder == 0)
		{
		    ALOGI("can't get hello service\n");
			return -1;
		}

		/* service肯定是BpHelloServie指针 */
		sp<IHelloService> service = interface_cast<IHelloService>(binder);

		/* 调用Service的函数 */
		int fd = service->get_fd();

		ALOGI("client call get_fd = %d", fd);

		char buf[500];
		int len;
		int cnt = 0;
		
		while (1)
		{
			//向 test_server 进程数据: Hello, test_server	*/
			len = sprintf(buf, "Hello, test_server, cnt = %d", cnt++);
			write(fd, buf, len);
			len = read(fd, buf, 500);
			buf[len] = '\0';
			ALOGI("%s\n", buf);
			sleep(5);
		}
	}
	return 0;
}

@5 服务端Test_server.cpp的实现如下:

#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0

#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "IHelloService.h"
#define SOCKET_BUFFER_SIZE      (32768U)

using namespace android;

class MyThread: public Thread {  
private:
	int fd;
public:  
    MyThread() {}
    MyThread(int fd) { this->fd = fd; }
	
    //说明:若返回true,循环调用此函数,返回false下一次不会再调用此函数  
    bool threadLoop()
    {
		char buf[500];
		int len;
		int cnt = 0;
		
		while(1)
		{
			len = read(fd, buf, 500);
			buf[len] = '\0';
			ALOGI("%s\n", buf);
			
			/* 向 test_client 发出: Hello, test_client */
			len = sprintf(buf, "Hello, test_client, cnt = %d", cnt++);
			write(fd, buf, len);
		}
		
       	return true;  
    }
  
};  

int main(void)
{
	int sockets[2];

	socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);

    int bufferSize = SOCKET_BUFFER_SIZE;
    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

	// 创建线程, 和test_client使用socketpiar通信
	sp<MyThread> th = new MyThread(sockets[0]);
	th->run();  

    // 关键点1 初始化binder
    sp<ProcessState> proc(ProcessState::self());
    
    // 关键点2 获得BpServiceManager
    sp<IServiceManager> sm = defaultServiceManager();
    
    // 关键点3
    sm->addService(String16("hello"), new BnHelloService(sockets[1]));

    // 关键点4 创建新的子线程,并开始处理驱动上报的消息
    ProcessState::self()->startThreadPool();
    
    // 关键点5 主线程 循环,循环并处理驱动上报的消息
	IPCThreadState::self()->joinThreadPool();//辅助类 IPCThreadState的分析

	return 0;
}

@6 最后描述下 Android.mk的实现

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	BnHelloService.cpp \
	BpHelloService.cpp \
	test_server.cpp

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	liblog \
	libbinder 


LOCAL_MODULE:= test_server
LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	BpHelloService.cpp \
	test_client.cpp

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	liblog \
	libbinder 


LOCAL_MODULE:= test_client
LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)

几段代码的整体说明:

  1. 前三段代码实现了HelloService整个服务(接口IHelloService 和BpHelloService 和 BnHelloService)
  2. 服务端TestServer实现了Hello服务的注册和socket通信架构机制(读& 写)。
  3. 客户端TestClient实现了Hello服务的获取和使用,同时 获取了fd(服务端的socket句柄)并使用
  4. Android.mk的实现,可以直接编译即可使用。

根据上面的例子基本上就可以写出一个基于Binder的 C++ demo程序,如果仅仅是使用binder的话,那已经足够了。

2 binder C++层实现 BpServiceManager

这一部分专门解读下 BpServiceManager的通信流程框架和部分代码,因为针对于系统的ServiceManager服务而言,它本身就相当于BnServiceManager的角色,而我们在分析Binder C++层代码时,当时也陷入了一个误区,觉得有BpXXX就一定要有BnXXX,实际上是不一定的,ServiceManager本身就是一个很好的例子。

2.1 BpServiceManager 的单边类关系框架图如下:

1.1的框架图相比,实际上是少了BnInterface那一半的,而这一半实际上就是开机启动的那个程序 servicemanager,在下一章节中我们会专门讲解到。

2.2 IServiceManager的实现说明

@1 IServiceManager.h的实现如下:

#ifndef ANDROID_ISERVICE_MANAGER_H
#define ANDROID_ISERVICE_MANAGER_H

#include <binder/IInterface.h>
#include <binder/IPermissionController.h>
#include <utils/Vector.h>
#include <utils/String16.h>

namespace android {
class IServiceManager : public IInterface
{
public:
    DECLARE_META_INTERFACE(ServiceManager);

    virtual sp<IBinder>         getService( const String16& name) const = 0;
    virtual sp<IBinder>         checkService( const String16& name) const = 0;
    virtual status_t            addService( const String16& name,
                                            const sp<IBinder>& service,
                                            bool allowIsolated = false) = 0;
    virtual Vector<String16>    listServices() = 0;

    enum {
        GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
        CHECK_SERVICE_TRANSACTION,
        ADD_SERVICE_TRANSACTION,
        LIST_SERVICES_TRANSACTION,
    };
};

sp<IServiceManager> defaultServiceManager();

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
    const sp<IServiceManager> sm = defaultServiceManager();
    if (sm != NULL) {
        *outService = interface_cast<INTERFACE>(sm->getService(name));
        if ((*outService) != NULL) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}
//...

class BnServiceManager : public BnInterface<IServiceManager>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};
}; // namespace android

#endif // ANDROID_ISERVICE_MANAGER_H

@2 IServiceManager.cpp的实现如下:

#define LOG_TAG "ServiceManager"

#include <binder/IServiceManager.h>

#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>

#include <private/binder/Static.h>

#include <unistd.h>

namespace android {

sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
    
    return gDefaultServiceManager;
}
//。。。
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }

    virtual sp<IBinder> getService(const String16& name) const
    {
        unsigned n;
        for (n = 0; n < 5; n++){
            sp<IBinder> svc = checkService(name);
            if (svc != NULL) return svc;
            ALOGI("Waiting for service %s...\n", String8(name).string());
            sleep(1);
        }
        return NULL;
    }

    virtual sp<IBinder> checkService( 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;
    }

    virtual Vector<String16> listServices()
    {
        Vector<String16> res;
        int n = 0;

        for (;;) {
            Parcel data, reply;
            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
            data.writeInt32(n++);
            status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
            if (err != NO_ERROR)
                break;
            res.add(reply.readString16());
        }
        return res;
    }
};

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

// ----------------------------------------------------------------------

status_t BnServiceManager::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    //printf("ServiceManager received: "); data.print();
    switch(code) {
        case GET_SERVICE_TRANSACTION: {
            CHECK_INTERFACE(IServiceManager, data, reply);
            String16 which = data.readString16();
            sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
            reply->writeStrongBinder(b);
            return NO_ERROR;
        } break;
        //...
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

}; // namespace android

总结下,这两个文件主要实现了IServiceManager,BpServiceManager,BnServiceManager,然而这里最让人疑惑的就是BnServiceManager不是由 servicemanager替换了吗?那为什么还有BnServiceManager的存在?

BnServiceManager并没有在系统中注册,因此也就无法在驱动层生成对应的binder_node节点,事实上也没必要注册;因为servicemanager开机就启动,已经替代了所谓的BnServiceManager,同时在驱动层 给自己创建了对应的binder_node节点,所以最后的答案很简单,因为BnServiceManager压根就没有使用,只是一个摆设而已,真正实现功能的是servicemanager。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值