在Android中,ServiceManager是Binder服务框架中的核心组件,负责管理系统中所有的Binder服务。init进程通过init.rc和servicemanager.rc启动servicemanage函数,serviceManager的启动先于所有应用进程。
本文以Android 13源码为例进行分析。
1,在init.rc和servicemanager.rc中关于servicemanager的代码如下:
在system/core/rootdir/Init.rc中
on init
start servicemanager
在frameworks/native/cmds/servicemanager/servicemanager.rc中
service servicemanager /system/bin/servicemanager
class core animation //指定了servicemanager所属的服务类别。在这个例子中,它被归类为core和animation两个类别,不同的类别可能有不同的启动顺序或优先级
user system //指定了运行servicemanager服务的用户为system
group system readproc
critical
onrestart restart apexd
onrestart restart audioserver
onrestart restart gatekeeperd
onrestart class_restart --only-enabled main //指定了当servicemanager服务重启时,应该根据服务是否已启用(enabled)来重启属于main、hal和early_hal类别的服务。这允许系统仅重启那些已配置为启用且属于指定类别的服务。
onrestart class_restart --only-enabled hal
onrestart class_restart --only-enabled early_hal
task_profiles ServiceCapacityLow //表明在系统关闭过程中,servicemanager也被视为一个关键服务
shutdown critical
2,在frameworks/native/cmds/servicemanager/Android.bp中
cc_binary { // 定义了一个名为servicemanager的二进制文件,它使用了servicemanager_defaults默认设置,并指定了main.cpp作为源文件,同时指定了servicemanager.rc作为init脚本。
name: "servicemanager",
defaults: ["servicemanager_defaults"],
init_rc: ["servicemanager.rc"],
srcs: ["main.cpp"],
}
从上面的配置可以看出,servicemanager.rc文件解析后的入口函数是main.cpp。
3,在frameworks/native/cmds/servicemanager/main.cpp中
// main函数代码是Android Binder服务管理器(ServiceManager)的启动脚本,它负责初始化Binder系统,注册ServiceManager自身为服务,并进入一个事件循环以处理Binder通信。
int main(int argc, char** argv) {
#ifdef __ANDROID_RECOVERY__
android::base::InitLogging(argv, android::base::KernelLogger);
#endif
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
const char* driver = argc == 2 ? argv[1] : "/dev/binder"; //检查输入参数,如果参数为空,则driver为"/dev/binder"
sp<ProcessState> ps = ProcessState::initWithDriver(driver); // ProcessState::initWithDriver函数用于初始化Binder状态
ps->setThreadPoolMaxThreadCount(0); // 设置Binder线程池的最大线程数为0(表示使用默认设置)
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>()); // 创建一个ServiceManager实例
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { // 将其自身注册为一个服务。注册失败时打印错误日志
LOG(ERROR) << "Could not self register servicemanager";
}
// 将ServiceManager实例设置为当前IPC线程的上下文对象,并使其成为Binder的上下文管理器。这样,所有通过Binder进行的IPC调用都会通过ServiceManager进行路由。
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager(); //设置成为 binder上下文管理者
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/); // 创建一个Looper实例,用于处理事件循环
// 设置Binder回调和客户端回调到Looper。这些回调用于处理Binder通信中的特定事件。
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
// 进入一个无限循环,通过Looper的pollAll方法等待并处理事件。-1参数表示无限期等待,直到有事件到来。
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}
上面的代码调用 ProcessState::initWithDriver 初始化binder状态,每个进程只会有一个ProcessState对象。
4,在frameworks/native/libs/binder/ProcessState.cpp中
initWithDriver函数:
[[clang::no_destroy]] static sp<ProcessState> gProcess;
[[clang::no_destroy]] static std::mutex gProcessMutex;
// initWithDriver 函数返回一个指向 ProcessState 对象的智能指针 sp<ProcessState>,sp 是 Android 系统中常用的智能指针类型,用于自动管理对象的生命周期。
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
return init(driver, true /*requireDefault*/);
}
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
if (driver == nullptr) {
std::lock_guard<std::mutex> l(gProcessMutex);
if (gProcess) {
verifyNotForked(gProcess->mForked);
}
return gProcess;
}
// 声明一个带有 [[clang::no_destroy]] 属性的静态 std::once_flag 对象 gProcessOnce。这个属性告诉编译器不要销毁这个对象,因为 std::call_once 需要它在整个程序的生命周期内都保持有效。
[[clang::no_destroy]] static std::once_flag gProcessOnce;
// 调用 std::call_once,确保传入的 lambda 表达式只被执行一次。这是用来确保 ProcessState 的初始化只发生一次。
std::call_once(gProcessOnce, [&](){// 如下匿名函数只会执行一次。使用C++ 11新特性,std::once_flag和std::call_once使得在多线程环境下如下函数只会执行一次。这样就确保了一个进程当中只有一个ProcessState对象,所有线程共享一个ProcessState对象。
if (access(driver, R_OK) == -1) { // 访问指定的 driver 路径,检查它是否可读
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
driver = "/dev/binder"; //如果不可读则重新赋值为/dev/binder
}
// we must install these before instantiating the gProcess object,
// otherwise this would race with creating it, and there could be the
// possibility of an invalid gProcess object forked by another thread
// before these are installed
int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
ProcessState::childPostFork); //定义了fork进程的三个回调函数,目的是确保gProcess对象在父进程和子进程中状态的一致性
LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
std::lock_guard<std::mutex> l(gProcessMutex); // 再次使用 std::lock_guard<std::mutex> 锁定 gProcessMutex,以确保在创建或修改 gProcess 时没有其他线程同时访问它。
gProcess = sp<ProcessState>::make(driver); // 创建一个新的 ProcessState 实例,并将其智能指针赋值给 gProcess。创建gProcess对象,这里执行的是ProcessState的构造函数。
});
if (requireDefault) {
// Detect if we are trying to initialize with a different driver, and
// consider that an error. ProcessState will only be initialized once above.
LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
"ProcessState was already initialized with %s,"
" can't initialize with %s.",
gProcess->getDriverName().c_str(), driver); // 检查gProcess的driverName跟传入的是否一致
}
verifyNotForked(gProcess->mForked);
return gProcess;
}
ProcessState构造函数
ProcessState::ProcessState(const char* driver)
: mDriverName(String8(driver)),
mDriverFD(-1),
mVMStart(MAP_FAILED),
mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),
mThreadCountDecrement(PTHREAD_COND_INITIALIZER),
mExecutingThreadsCount(0),
mWaitingForThreads(0),
mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
mStarvationStartTimeMs(0),
mForked(false),
mThreadPoolStarted(false),
mThreadPoolSeq(1),
mCallRestriction(CallRestriction::NONE) {
// 调用 open_driver 函数尝试打开指定的 Binder 驱动文件
base::Result<int> opened = open_driver(driver); // open_driver
if (opened.ok()) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
// 调用mmap接口向Binder驱动申请内核空间的内存,并将其映射到进程的虚拟地址空间中,这块内存用于接收 Binder 事务。函数的返回值是最后文件映射到进程空间的地址.
//mmap 的作用是将 /dev/binder 设备文件的一部分内存映射到调用进程的虚拟地址空间。它将从 /dev/binder 开始的 BINDER_VM_SIZE 大小的内存区域映射到进程地址空间中的 mVMStart 地址。
//这种映射使得进程能够直接访问 Binder 驱动的数据区域,从而高效地进行进程间通信(IPC)。
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
opened.value(), 0);
if (mVMStart == MAP_FAILED) {
close(opened.value());
// *sigh*
opened = base::Error()
<< "Using " << driver << " failed: unable to mmap transaction memory.";
mDriverName.clear();
}
}
#ifdef __ANDROID__
LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating: %s",
driver, opened.error().message().c_str());
#endif
if (opened.ok()) {
mDriverFD = opened.value(); // 将打开的文件描述符(opened.value())赋值给 mDriverFD 成员变量,以便后续操作使用
}
}
becomeContextManager函数
bool ProcessState::becomeContextManager()
{ // 在 Android 的 Binder 架构中,上下文管理器是一个特殊的进程,负责管理 Binder 节点(Binder Nodes)和引用(References),以及处理跨进程通信中的安全上下文信息。
AutoMutex _l(mLock);
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
};
// 通过 ioctl 系统调用,使用 BINDER_SET_CONTEXT_MGR_EXT 命令和之前准备的 obj 对象尝试成为上下文管理器。
int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
// fallback to original method
if (result != 0) {
android_errorWriteLog(0x534e4554, "121035042");
int unused = 0;
result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
}
if (result == -1) {
ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
return result == 0;
}
在ProcessState构造函数中调用了open_driver函数打开binder驱动文件,通过mmap向Binder驱动申请内核空间的内存,并将其映射到进程的虚拟地址空间中。
open_driver函数
static base::Result<int> open_driver(const char* driver) {
int fd = open(driver, O_RDWR | O_CLOEXEC); // 打开binder驱动设备,得到文件描述符fd,内核里对应函数为binder_open
if (fd < 0) {
return base::ErrnoError() << "Opening '" << driver << "' failed";
}
// 下面的ioctl函数,在内核里对应的是binder_ioctl
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers); // 获取binder版本
if (result == -1) {
close(fd);
return base::ErrnoError() << "Binder ioctl to obtain version failed";
}
//如果 ioctl 调用返回值不为 0 或获取的版本号 vers 不等于用户空间协议版本 BINDER_CURRENT_PROTOCOL_VERSION,表示版本不匹配,关闭文件描述符并返回错误。
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
close(fd);
return base::Error() << "Binder driver protocol(" << vers
<< ") does not match user space protocol("
<< BINDER_CURRENT_PROTOCOL_VERSION
<< ")! ioctl() return value: " << result;
}
//设置 Binder 驱动的最大线程数,可以控制系统中用于处理 Binder 请求的并发线程数量。有助于防止资源过度消耗,提高系统稳定性和性能。(这里是15)
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
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); //启用 Binder 驱动的单向(oneway)垃圾检测功能,以防止 Binder 通信中可能的滥用行为。
if (result == -1) {
ALOGE_IF(ProcessState::isDriverFeatureEnabled(
ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
"Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
return fd;
}
在上面的open_driver函数中,ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable)启用 Binder 驱动的单向(oneway)垃圾检测功能,以防止 Binder 通信中可能的滥用行为。
单向消息(Oneway Message)分析:
定义:单向消息是一种特殊类型的 IPC(进程间通信)调用。与普通的同步 IPC 调用不同,单向消息是异步的,即调用者发出请求后立即返回,而不等待被调用者处理完成。
使用场景:单向消息通常用于不需要立即返回结果的操作。例如,发送通知或更新状态等。
单向垃圾(Oneway Spam)分析:
单向垃圾:单向垃圾指的是大量的、不受控制的单向消息。这些消息可能会被滥用,导致系统资源耗尽或性能下降。
滥用可能会导致资源耗尽和性能下降。
资源耗尽:频繁发送单向消息可能会占用大量的系统资源(如内存、CPU),影响系统的稳定性。
性能下降:过多的单向消息处理可能会导致系统响应变慢,影响用户体验。
单向垃圾检测(Oneway Spam Detection)
单向垃圾检测功能用于监控和限制单向消息的发送,以防止滥用行为。
通过启用单向垃圾检测,可以确保系统不会因为过多的单向消息而受到影响。