int main() {
configureRpcThreadpool(1, true /* callerWillJoin */);//1
sp<ServiceManager> manager = new ServiceManager();
setRequestingSid(manager, true);
if (!manager->add(serviceName, manager)) {
//2
ALOGE("Failed to register hwservicemanager with itself.");
}
TokenManager *tokenManager = new TokenManager();
if (!manager->add(serviceName, tokenManager)) {
ALOGE("Failed to register ITokenManager with hwservicemanager.");
}
// Tell IPCThreadState we're the service manager
sp<BnHwServiceManager> service = new BnHwServiceManager(manager);//3
IPCThreadState::self()->setTheContextObject(service);
// Then tell the kernel
ProcessState::self()->becomeContextManager(nullptr, nullptr);
int rc = property_set("hwservicemanager.ready", "true");
if (rc) {
ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
"HAL services will not start!\n", rc);
}
ALOGI("hwservicemanager is ready now.");
joinRpcThreadpool();
return 0;
}
/system/libhidl/transport/HidlTransportSupport.cpp
configureRpcThreadpool()-(直接调用)> configureBinderRpcThreadpool-(直接调用)>
/system/libhidl/transport/HidlBinderSupport.cpp
ProcessState::self()->setThreadPoolConfiguration
函数实现在
/system/libhwbinder/ProcessState.cpp
status_t ProcessState::setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool) {
…….
size_t kernelMaxThreads = maxThreads - 1;
//告诉kernel最多能创建几个线程,这个是配置线程池
if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) != -1) {
AutoMutex _l(mLock);
mMaxThreads = maxThreads;
mSpawnThreadOnStart = !callerJoinsPool;
} else {
……. }
return result;
}
实际上是向驱动层ioctl,mDriverFD是打开节点,可以接下来看
ProcessState::self()调用gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
ProcessState::ProcessState(size_t mmap_size)
: mDriverFD(open_driver())
……
, mMmapSize(mmap_size)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
//这个进程的Binder内核内存上限就是BINDER_VM_SIZE
mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
……
static int open_driver()
{
int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);
所以通过打开/dev/hwbinder节点,mmap一段虚拟内存,建立私有映射,用于binder通信接收数据。
更多的可能需要到底层去看下这个节点相关创建以及ioctl的用法
system/hwservicemanager/ServiceManager.cpp
manager->add(serviceName, manager)
这个类没有看到构造函数,
static std::string serviceName = “default”;
自己是manager同样也是server,所以将自己加入管理器
Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) {
……
for(size_t i = 0; i < interfaceChain.size(); i++) {
const std::string fqName = interfaceChain[i];
PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
HidlService *hidlService = ifaceMap.lookup(name);
//将服务插入ifaceMap
if (hidlService == nullptr) {
ifaceMap.insertService(
std::make_unique<HidlService>(fqName, name, service, callingContext.pid));
}
如果ifaceMap找不到要添加名字的服务,将当前服务插入ifaceMap
manager->add(serviceName, tokenManager)
后面再加入一个tokenManager。
out/soong/.intermediates/system/libhidl/transport/manager/1.1/[email protected]_genc++/gen/android/hidl/manager/1.1/ServiceManagerAll.cpp
BnHwServiceManager::BnHwServiceManager(const ::android::sp<IServiceManager> &_hidl_impl)
: ::android::hidl::base::V1_0::BnHwBase(_hidl_impl, "[email protected]", "IServiceManager") {
_hidl_mImpl = _hidl_impl;
auto prio = ::android::hardware::details::gServicePrioMap.get(_hidl_impl, {
SCHED_NORMAL, 0});
mSchedPolicy = prio.sched_policy;
mSchedPriority = prio.prio;
setRequestingSid(::android::hardware::details::gServiceSidMap.get(_hidl_impl, false));
}
创建一个BnHwServiceManager对象,_hidl_mImpl保存的是ServiceManager实例。
system\libhwbinder\ IPCThreadState.cpp
void IPCThreadState::setTheContextObject(sp<BHwBinder> obj)
{
mContextObject = obj;//赋值变量
}
ProcessState::self()->becomeContextManager(nullptr, nullptr);
主要调用result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
将本进程设置为binder系统的管理进程,只有servicemanager进程才会使用这个命令且只能调用一次。
看资料设置下去会生成节点,成为servicemanager在binder驱动的实体,现在不去关心,有机会看驱动在了解
/system/libhidl/transport/HidlTransportSupport.cpp
joinRpcThreadpool-(直接调用)-> joinBinderRpcThreadpool-(直接调用)-> IPCThreadState::self()->joinThreadPool()
进入到/system/libhwbinder/IPCThreadState.cpp
这个整体是个循环,用于接收消息,处理消息
void IPCThreadState::joinThreadPool(bool isMain)
{
……
do {
processPendingDerefs();//mPendingWeakDerefs和mPendingStrongDerefs中的指针引用减一
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
……
} while (result != -ECONNREFUSED && result != -EBADF);
后面调用情况
status_t IPCThreadState::getAndExecuteCommand()
{
…
result = talkWithDriver();
……
result = executeCommand(cmd);
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
……
// Return immediately if there is nothing to do. 不需要读写,直接返回
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
do {
…..
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
status_t IPCThreadState::executeCommand(int32_t cmd)
{
……
case BR_TRANSACTION:
{
……
error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
用binder驱动进行读写,读出来之后,执行executeCommand,判断命令执行对应的函数。
case BR_TRANSACTION 是比较重要的case,接收驱动的回应。
mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
mContextObject 就是我们前面设置的 BnHwServiceManager ,调用父类函数binder.cpp
status_t BHwBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback)
{
switch (code) {
default:
/* BnHwServiceManager 实现了 onTransact() */
err = onTransact(code, data, reply, flags,
[&](auto &replyParcel) {
replyParcel.setDataPosition(0);
ServiceManagerAll.cpp
::android::status_t BnHwServiceManager::onTransact 实现这个函数
So,管理服务线程就这样创建,进入循环 写入和度读取。
总结:
创建过程
1)首先打开“/dev/hwbinder”设备文件,映射内存
2)利用BINDER_SET_CONTEXT_MGR命令,让自己成为管理者 ServiceManager。维护service列表
3)进入一个无限循环,等待Client的请求到来。
通信过程
1) 整个进程间通信的大部分工作都是通过 open(), mmap()和 ioctl()等文件操作,在内核空间与用户空间中操作,来实现的
2) Binder驱动在内核空间中创建了一个Binder节点,隶属于Server们的进程,并分配一个句柄,给ServiceManager维护
3) Client通信,只要发送服务名字和数据包,发送给binder驱动,然后将包丢给ServiceManager,ServiceManager寻找服务返回句柄,返回给client。然后client就可以通过句柄通信。
关于这部分我也只是简单看了下,并没有深入,如果只学习camera部分可以当做黑盒,其实这就是服务的管理器,也是个服务,服务的本质就是响应客户端(比如cmaera provider)请求。要提供服务,就要循环接收请求,处理请求,应答客服端。这个hidl和aidl,本质都是一样的,通过底层节点传输数据,一边Transact,另一边onTransact ,实现进程间的通信。