到现在为止我对Binder 的了解只是知道它很难和它是 Android 系统中最核心的跨进程通信机制,仅此而已,所以接下来几篇文章都是学习的Android Binder 驱动的。
以安卓 12 源码为基础分析
相关文件:
frameworks/av/media/mediaserver/mediaserver.rc
frameworks/av/media/mediaserver/main_mediaserver.cpp
frameworks/native/libs/binder/ProcessState.cpp
frameworks/native/libs/binder/IServiceManager.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/libs/binder/ndk/service_manager.cpp
frameworks/native/libs/binder/IPCThreadState.cpp
我们关注的是:一个系统级 Native 服务(mediaserver)如何被创建,并通过 Binder 机制向系统注册其提供的服务
主线:
markdown
1. 内核启动 → 加载 Binder 驱动
↓
2. init 进程启动 → 解析 .rc 文件
↓
3. 启动 mediaserver 进程(fork + exec)
↓
4. mediaserver 初始化 ProcessState 和 IPCThreadState
↓
5. 实例化并注册媒体服务(如 MediaPlayerService)
↓
6. 服务通过 Binder 被 servicemanager 管理
↓
7. 其他进程可通过 Binder 获取服务代理
在开始之前我们要先简单了解下什么是Binder,首先我们都知道它可以用来跨进程通信,那么对跨进程该怎么理解呢:
每个 Android 应用通常运行在自己独立的进程中,拥有自己独立的内存空间。一个进程不能直接访问另一个进程的内存。当应用需要与其他应用或系统服务交互时,就必须通过 IPC 机制。
这个很简单,但是Binder 是如何实现跨进程通信的呢?
Binder 的架构基于客户端-服务器(Client-Server)模型 。它的核心思想是:虽然不能直接访问对方的内存,但可以通过内核空间(一个所有进程都能共享的区域)来间接地完成数据交换和方法调用。
这个也很好理解,Binder 就相当于做了各个进程之间的中转工作,和路由器的原理有点像,对客户端来说,你只需要调用一个简单的方法,Binder 就可以帮你完成跨进程的通信任务,我们对Binder 的理解先到这,先不去深究其实现。
另外 Binder 只需要一次数据拷贝(从用户空间到内核空间),相较于其他 IPC 机制性能更高,这也是安卓选它跨进程通信的原因之一!
Binder 驱动初始化(内核层)
- 内核启动时加载
binder
模块。 - 创建设备节点
/dev/binder
。 - 提供
open
、mmap
、ioctl
系统调用接口。
所有使用 Binder 的进程都必须先 open("/dev/binder")
。
mmap
映射一块内存用于 Binder 数据传输(减少拷贝)。
驱动已就绪!
init
解析 mediaserver.rc
frameworks/av/media/mediaserver/mediaserver.rc
csharp
on property:init.svc.media=*
setprop init.svc.mediadrm ${init.svc.media}
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
init 进程 在解析 init.rc
时会启动一个名为 mediaserver
的守护进程。
/system/bin/mediaserver
入口
frameworks/av/media/mediaserver/main_mediaserver.cpp
cpp
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
// 获取 ProcessState 单例(打开 /dev/binder,mmap)
sp<ProcessState> proc(ProcessState::self());
// 获取 ServiceManager 代理
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
// 实例化核心媒体服务
MediaPlayerService::instantiate();
// 媒体资源管理
ResourceManagerService::instantiate();
// 注册可选的媒体扩展服务(厂商定制或第三方插件)
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
// 启动 Binder 线程池
ProcessState::self()->startThreadPool();
// 当前线程加入线程池,等待 Binder 请求
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
sp<...>
是 Android 的强引用智能指针(StrongPointer
),用于自动管理 Binder 对象生命周期。
sp<ProcessState> proc(ProcessState::self());
执行 sp<ProcessState> proc(ProcessState::self());
来到ProcessState.cpp 中:
frameworks/native/libs/binder/ProcessState.cpp
执行代码:
cpp
sp<ProcessState> ProcessState::self() {
return init(kDefaultDriver, false /*requireDefault*/);
}
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) {
static sp<ProcessState> gProcess;
static std::mutex gProcessMutex;
static std::once_flag gProcessOnce;
if (driver == nullptr) {
std::lock_guard<std::mutex> l(gProcessMutex);
return gProcess;
}
std::call_once(gProcessOnce, [&](){
if (access(driver, R_OK) == -1) {
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
// 如果传入的 driver 设备文件不可访问,则退回 /dev/binder。
driver = "/dev/binder";
}
std::lock_guard<std::mutex> l(gProcessMutex);
// make 就是执行构造函数,等价于:new ProcessState("/dev/binder");
// make 属于sp 作用域,具体可以看 system/core/libutils/include/utils/StrongPointer.h
gProcess = sp<ProcessState>::make(driver);
});
if (requireDefault) {
LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
"ProcessState was already initialized with %s, can't initialize with %s.",
gProcess->getDriverName().c_str(), driver);
}
return gProcess;
}
构造函数 ProcessState::ProcessState(const char* driver)
cpp
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver)) // 保存驱动路径到 mDriverName
, mDriverFD(open_driver(driver)) // 打开驱动 → 调用 open_driver(driver) 返回 mDriverFD
, mVMStart(MAP_FAILED)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// 内存映射 (mmap) → 分配一块虚拟内存空间给 Binder 事务缓冲区
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
ALOGE("Using %s failed: unable to mmap transaction memory.\n",
mDriverName.c_str());
// 没有足够空间分配给 /dev/binder, 则关闭驱动
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0,
"Binder driver '%s' could not be opened. Terminating.", driver);
}
mmap:
- 作用:给 Binder 驱动分配一块进程虚拟内存,专门用来存放事务数据(Parcel 数据 buffer)。
- Binder 驱动通过 copy_from_user/copy_to_user 在内核和用户空间之间交换数据。
打开驱动:
cpp
static int open_driver(const char *driver)
{
// 打开驱动,得到一个文件描述符 → Binder 驱动的通信入口
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
// 确认内核和用户空间协议版本一致
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
// 告诉内核这个进程最多可以有多少个 Binder 线程(默认 15)
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
// 开启单向调用滥用检测(性能保护)
result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
if (result == -1) {
ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
open 是打开驱动、mmap 是映射驱动、ioctl 是操作驱动、close 是关闭驱动,分别对应以下函数:
binder_open()
:打开 Binder 设备(每个进程调用一次)binder_mmap()
:映射内核缓冲区到用户空间(用于高效数据传输)binder_ioctl()
:处理 Binder 通信命令(如 BC_TRANSACTION)binder_colse
:关闭驱动
sp<IServiceManager> sm(defaultServiceManager())
获取系统的 ServiceManager(服务的大管家),用来向 Binder 驱动注册/查询服务。
cpp
sp<IServiceManager> defaultServiceManager()
{
// call_once:确保里面的 lambda 函数 只执行一次,即使多线程调用 defaultServiceManager()
// 这是 C++ 中实现单例的经典模式
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
// 获取 Binder 驱动为每个进程自动提供的 "上下文管理者"(context manager) 的 Binder 引用。
// 这个"上下文管理者"其实就是 /dev/vndbinder 或 /dev/binder 上的 servicemanager 进程 的代理。
// 将原始的 IBinder 接口(BpBinder(0))转换为 AidlServiceManager 接口
sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
if (sm == nullptr) {
ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
// 因为 servicemanager 进程可能 还没有启动完成,等待一秒
sleep(1);
}
}
// 兼容层(Shim Layer)
// 在 Android 10 及之前:servicemanager 使用 HIDL 定义
// Android 11+ 开始:Google 将 servicemanager 重构为使用 AIDL
gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
});
return gDefaultServiceManager;
}
getContextObject(nullptr):
cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
// 传入 handle = 0,这是整个 Binder 架构中唯一硬编码的句柄
// handle=0 固定代表 ServiceManager
// 所有进程都知道:要找 ServiceManager,就去拿 handle=0 的代理。
sp<IBinder> context = getStrongProxyForHandle(0);
if (context) {
// The root object is special since we get it directly from the driver, it is never
// written by Parcell::writeStrongBinder.
internal::Stability::markCompilationUnit(context.get());
} else {
ALOGW("Not able to get context object on %s.", mDriverName.c_str());
}
return context;
}
cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
// mLock 是 ProcessState 的互斥锁
AutoMutex _l(mLock);
// struct handle_entry {
// IBinder* binder; // 对应的代理对象(BpBinder)
// weakref_type* refs; // 弱引用计数器
// };
//lookupHandleLocked 维护一个数组:mHandleToObject(Vector<handle_entry>)
// 所有 handle 的映射都集中管理,避免重复创建代理。
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
// 代理不存在 或 弱引用已失效 → 需要重建
if (handle == 0) {
IPCThreadState* ipc = IPCThreadState::self();
CallRestriction originalCallRestriction = ipc->getCallRestriction();
ipc->setCallRestriction(CallRestriction::NONE);
Parcel data;
// 即使 handle=0 存在,也不能保证 servicemanager 进程还活着
// 发送一个 PING_TRANSACTION 事务,如果返回 DEAD_OBJECT:说明 servicemanager 死了,不能返回代理
status_t status = ipc->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
ipc->setCallRestriction(originalCallRestriction);
if (status == DEAD_OBJECT)
return nullptr;
}
// 创建一个 BpBinder 对象,封装 handle
// BpBinder 是 Binder 代理的基类
// 所有跨进程调用最终都通过 BpBinder::transact() 发送到内核
sp<BpBinder> b = BpBinder::create(handle);
e->binder = b.get();
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// 代理存在且有效 → 直接返回强引用
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
流程图:
scss
getStrongProxyForHandle(handle)
↓
加锁 mLock
↓
lookupHandleLocked(handle) → 获取 handle_entry
↓
是否有有效代理?
├─ 是 → attemptIncWeak → 成功? → 返回强引用
└─ 否 →
handle == 0? → 是 → 发送 PING_TRANSACTION 检查存活
→ 失败? → 返回 nullptr
创建 BpBinder(handle)
保存到 handle_entry
返回 sp<BpBinder>
这样就拿到了 ServiceManager 的 Binder 代理对象。
MediaPlayerService::instantiate();
启动并向 ServiceManager 注册 MediaPlayerService
。
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
因为 defaultServiceManager()
返回的是 sp<IServiceManager>
对象, 所以可以在IServiceManager 中找到下面方法:
cpp
using AidlServiceManager = android::os::IServiceManager;
//...
class ServiceManagerShim : public IServiceManager
//...
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority)
{
Status status = mTheRealServiceManager->addService(
String8(name).c_str(), service, allowIsolated, dumpsysPriority);
return status.exceptionCode();
}
mTheRealServiceManager
是一个 AIDL 接口的客户端代理 ,指向真正的 AIDL 版 servicemanager
服务。
此处的 addService 就对应了 frameworks/base/core/java/android/os/ServiceManager.java 中的 addService 方法,代表着 Java 和 Native 都可以独立地向 servicemanager
注册服务:
java
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
ResourceManagerService::instantiate();
启动并注册 ResourceManagerService
,用于统一管理多媒体硬件资源(解码器、音视频硬件编解码能力)
cpp
void ResourceManagerService::instantiate() {
// 创建 ResourceManagerService 实例(使用 NDK AIDL 模式)
std::shared_ptr<ResourceManagerService> service =
::ndk::SharedRefBase::make<ResourceManagerService>();
// 将服务注册到 servicemanager
binder_status_t status =
AServiceManager_addService(service->asBinder().get(), getServiceName());
// 如果失败就直接返回,不继续初始化
if (status != STATUS_OK) {
return;
}
// 创建并设置观察者服务
std::shared_ptr<ResourceObserverService> observerService =
ResourceObserverService::instantiate();
// 使用观察者模式解耦资源管理和状态通知。
if (observerService != nullptr) {
service->setObserverService(observerService);
}
// TODO: mediaserver main() is already starting the thread pool,
// move this to mediaserver main() when other services in mediaserver
// are converted to ndk-platform aidl.
//ABinderProcess_startThreadPool();
}
这段代码的作用是: 使用现代 NDK AIDL 架构,创建并注册 ResourceManagerService
服务到 servicemanager
,同时设置其依赖的观察者服务,为 mediaserver
提供资源管理能力。
其中AServiceManager_addService 代码实现在 service_manager.cpp :
frameworks/native/libs/binder/ndk/service_manager.cpp
cpp
binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {
if (binder == nullptr || instance == nullptr) {
return EX_ILLEGAL_ARGUMENT;
}
sp<IServiceManager> sm = defaultServiceManager();
status_t exception = sm->addService(String16(instance), binder->getBinder());
return PruneException(exception);
}
IPCThreadState::self()->joinThreadPool();
将当前线程变成一个可处理传入和传出 Binder 请求的"Binder 线程",并进入一个无限循环,等待并执行来自其他进程的 Binder 调用。
关键源码:
cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
status_t result;
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
do {
processPendingDerefs();
// 等待并处理来自 Binder 驱动的消息
result = getAndExecuteCommand();
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
与驱动进行通信:
cpp
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD < 0) {
return -EBADF;
}
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
// 接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
alog << "Sending commands to driver: " << indent;
const void* cmds = (const void*)bwr.write_buffer;
const void* end = ((const uint8_t*)cmds)+bwr.write_size;
alog << HexDump(cmds, bwr.write_size) << endl;
while (cmds < end) cmds = printCommand(alog, cmds);
alog << dedent;
}
alog << "Size of receive buffer: " << bwr.read_size
<< ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
// 通过ioctl不停的读写操作,跟Binder Driver进行通信
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD < 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
//...
return err;
}
这里提一下 binder_write_read 可以把它理解为一个 双向信封:
- 一边装着 我要告诉驱动什么(write)
- 一边留着 驱动要告诉我什么(read)
write_size/buffer |
用户 → 内核 | 发送命令(BC_TRANSACTION 等) |
---|---|---|
read_size/buffer |
内核 → 用户 | 接收事件(BR_TRANSACTION 等) |
write/read_consumed |
内核 → 用户 | 告知处理进度 |
上面我们说过 所有跨进程调用最终都通过 BpBinder::transact() 发送到内核
cpp
sp<BpBinder> b = BpBinder::create(handle);
BpBinder 在 sp ProcessState::getStrongProxyForHandle 中被创建
cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");
status_t err;
// ...
waitForResponse(nullptr, nullptr);
//...
return err;
}
waitForResponse:
cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
// 调用 talkWithDriver
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
<< getReturnString(cmd) << endl;
}
switch (cmd) {
case BR_ONEWAY_SPAM_SUSPECT:
//..
case BR_TRANSACTION_COMPLETE:
//..
case BR_DEAD_REPLY:
//..
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_FROZEN_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
//..
case BR_REPLY:
//..
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
客户端通过 transact 发送消息, 调用 talkWithDriver 监听返回消息,至此形成闭环。
最后
本人能力有限,关于具体函数的介绍只能停留在表面上,分析不到之处还请不吝赐教,啊,头皮发麻...