在Framwork源码解析(1)_Zygote进程启动流程一文中了解过,Android系统启动Zygote进程然后创建SystemService,再创建其他服务进程,ServiceManager 进程也是在这里启动的。查看/system/core/rootdir/init.rc
源码,可以找到启动servicemanager:
这里启动的是/frameworks/native/cmds/servicemanager
下的service_manager.c
文件,此目录下还有servicemanager.rc
配置,就是被zygote启动的。
查看service_manager.c
源码的main方法:
int main(int argc, char** argv){
// ......
if (argc > 1) {
driver = argv[1];
} else {
// 设置默认binder驱动文件路径
driver = "/dev/binder";
}
// 打开binder文件,并设置映射文件大小为128KB
bs = binder_open(driver, 128*1024);
// 成为上下文管理者
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
// ......
// 开启binder循环
binder_loop(bs, svcmgr_handler);
return 0;
}
主要做了三件事:
找到同级目录下的frameworks/native/cmds/servicemanager/binder.c
文件,该文件中找到binder_open
方法:
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
// 动态分配内存
bs = malloc(sizeof(*bs));
// 打开驱动文件,将文件句柄也就是c++的指针引用传给bs结构体的fd
bs->fd = open(driver, O_RDWR | O_CLOEXEC);
// 系统调用
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
fprintf(stderr,
"binder: kernel driver version (%d) differs from user space version (%d)\n",
vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
bs->mapsize = mapsize;
// 创建映射,mmap函数能够将用户空间的一段内存区域映射到内核空间,用户对该段内存的修改能直接反映到内核空间,
// 相反,内核空间的改动也可以映射到用户空间,这里将/dev/binder映射到内核空间,并赋值给bs的mapped属性,大小是128KB
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs;
}
bs = malloc(sizeof(*bs));
bs->fd = open(driver, O_RDWR | O_CLOEXEC);
ioctl(bs->fd, BINDER_VERSION, &vers)
ioctl(input/output control)
是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
源码中通过系统调用将"/dev/binder"驱动的引用传给驱动层,命令符是BINDER_SET_CONTEXT_MGR
。
1、开启binder循环
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
// 32位,2的32次方就是128kb
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
// 重置操作,将文件清空
binder_write(bs, readbuf, sizeof(uint32_t));
// 开启循环,读取数据并解析
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
// 不断的读获取服务的请求
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
// 解析binder内容
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
}
2、查看binder_parse
源码,源码路径/frameworks/native/cmds/servicemanager/binder.c
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
while (ptr < end) {
// ....
case BR_TRANSACTION: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
// 执行回调处理函数,将处理结果返回
res = func(bs, txn, &msg, &reply);
if (txn->flags & TF_ONE_WAY) {
binder_free_buffer(bs, txn->data.ptr.buffer);
} else {
// 向binder驱动发送执行结果
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
}
ptr += sizeof(*txn);
break;
}
}
return r;
}
这里执行完回调函数res = func(bs, txn, &msg, &reply);
并把结果发送binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
,再找到binder_send_reply
方法:
void binder_send_reply(struct binder_state *bs,
struct binder_io *reply,
binder_uintptr_t buffer_to_free,
int status)
{
// ....
binder_write(bs, &data, sizeof(data));
}
这里又走到了binder_write
方法:
int binder_write(struct binder_state *bs, void *data, size_t len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
// 向驱动文件写入数据,read_size = 0,也就是向驱动层写入数据,BINDER_WRITE_READ指令是读写指令,主要看read_size或wite_size谁是0
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
return res;
}
binder_write方法也调用了ioctl
方法,命令符是BINDER_WRITE_READ
,表示向驱动文件读或写入数据,read_size = 0,也就是向驱动层写入数据。
https://blog.csdn.net/yiranfeng/article/details/105210069