【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )(一)

简介: 【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )(一)

文章目录

一、系统服务

二、系统服务主函数

三、开启 Binder

四、注册上下文

五、开启 Binder 循环

六、binder_write 方法

七、binder_ioctl 内核方法

八、binder_ioctl_write_read 内核方法





一、系统服务


System Server 是由 Zygote 进程 fork() 出来的 ;


Init 进程 启动 Zygote , Zygote 启动 System Server 进程 ;


System Server 注册服务时 , 会执行 service_manager.c 中的方法 ;






二、系统服务主函数


service_manager.c 从 int main(int argc, char** argv) 方法开始执行 , 在该 main 函数中 , 执行了 3 33 个重要操作 :


① 开启 Binder : 获取 Binder 驱动 , 并且申请了 128 KB 的内存映射地址 , bs = binder_open(driver, 128*1024); ;

② 注册上下文 : 将自己注册成 Binder 进程的上下文 , binder_become_context_manager(bs) ;

③ 开启 Binder 循环 : 不停的轮询 , 是否有消息发送 , binder_loop(bs, svcmgr_handler); ;

int main(int argc, char** argv)
{
  // 开启 Binder , 获取 Binder 驱动 , 并且申请了 128 KB 的内存映射地址
    bs = binder_open(driver, 128*1024);
  // 将自己注册成 Binder 进程的上下文
    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/service_manager.c ;






三、开启 Binder


通过调用 bs = binder_open(driver, 128*1024); 开启 Binder 的方法 struct binder_state *binder_open(const char* driver, size_t mapsize) , 定义在 /frameworks/native/cmds/servicemanager/binder.c 中 ;


首先分析下 binder_state 结构体 , 其中有 3 33 个参数 ,


int fd : Binder 驱动的文件描述

void *mapped : 内存映射首地址

size_t mapsize : 内存映射的大小 , 128 KB

方法最终返回一个 binder_state 结构体 ;


struct binder_state
{
    int fd;   // Binder 驱动的文件描述
    void *mapped; // 内存映射首地址
    size_t mapsize; // 内存映射的大小 , 128 KB 
};
// 打开 Binder , 并获取 Binder 的状态描述
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
    struct binder_state *bs;  // 返回的结构体
    struct binder_version vers;
    bs = malloc(sizeof(*bs)); // 为返回值申请内存
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open %s (%s)\n",
                driver, strerror(errno));
        goto fail_open;
    }
    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;
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    if (bs->mapped == MAP_FAILED) {
        fprintf(stderr,"binder: cannot map device (%s)\n",
                strerror(errno));
        goto fail_map;
    }
    return bs;
fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}


完整代码参考 /frameworks/native/cmds/servicemanager/binder.c#97;






四、注册上下文


通过调用 binder_become_context_manager(bs) , 将自己注册成 Binder 进程的上下文 ; 其中调用的 ioctl 方法是内核中的方法 , 这是 IO Control 的简称 ; 这个代码得去内核中查找 ;


int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}


完整代码参考 /frameworks/native/cmds/servicemanager/binder.c#147


在 【Binder 机制】分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 ) 博客中分析了该 ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0) 方法对应的源码 ;






五、开启 Binder 循环


在 service_manager.c 的 main 函数中 , 调用 binder_loop(bs, svcmgr_handler) 开启 Binder 循环 ;


binder_loop 方法定义在 /frameworks/native/cmds/servicemanager/binder.c 中 ;


在 binder_loop 方法中 , 先调用了 binder_write 方法 , 然后开启了死循环 ;


void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    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);
        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }
  // 如果收到 Binder 读写消息信息 , 调用 binder_parse 方法处理 ;
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}


完整代码参考 /frameworks/native/cmds/servicemanager/binder.c ;



目录
相关文章
|
2月前
|
消息中间件 Unix Linux
Linux进程间通信(IPC)介绍:详细解析IPC的执行流程、状态和通信机制
Linux进程间通信(IPC)介绍:详细解析IPC的执行流程、状态和通信机制
60 1
|
4月前
|
缓存 负载均衡 Linux
内核:进程与调度机制(笔记)
内核:进程与调度机制(笔记)
62 0
|
6月前
|
消息中间件 弹性计算 网络协议
120 Storm进程间通信机制
120 Storm进程间通信机制
22 0
|
2月前
|
资源调度 算法 Linux
Linux进程/线程的调度机制介绍:详细解析Linux系统中进程/线程的调度优先级规则
Linux进程/线程的调度机制介绍:详细解析Linux系统中进程/线程的调度优先级规则
119 0
|
14天前
|
算法 Linux 调度
深入理解Linux内核的进程调度机制
【4月更文挑战第17天】在多任务操作系统中,进程调度是核心功能之一,它决定了处理机资源的分配。本文旨在剖析Linux操作系统内核的进程调度机制,详细讨论其调度策略、调度算法及实现原理,并探讨了其对系统性能的影响。通过分析CFS(完全公平调度器)和实时调度策略,揭示了Linux如何在保证响应速度与公平性之间取得平衡。文章还将评估最新的调度技术趋势,如容器化和云计算环境下的调度优化。
|
19天前
|
算法 Linux 调度
深度解析:Linux内核的进程调度机制
【4月更文挑战第12天】 在多任务操作系统如Linux中,进程调度机制是系统的核心组成部分之一,它决定了处理器资源如何分配给多个竞争的进程。本文深入探讨了Linux内核中的进程调度策略和相关算法,包括其设计哲学、实现原理及对系统性能的影响。通过分析进程调度器的工作原理,我们能够理解操作系统如何平衡效率、公平性和响应性,进而优化系统表现和用户体验。
|
存储 监控 安全
深度剖析Linux进程的内部机制:一探/proc/pid的奥秘
深度剖析Linux进程的内部机制:一探/proc/pid的奥秘
87 0
|
6月前
|
负载均衡 算法 Linux
深入理解Linux内核进程CPU负载均衡机制(上)
深入理解Linux内核进程CPU负载均衡机制
|
5月前
|
算法 Linux 调度
Linux进程调度机制
Linux进程调度机制
62 0
|
6月前
|
消息中间件 算法 网络协议
深入探讨进程间通信的重要性:理解不同的通信机制(下)
本文旨在探讨进程间通信的重要性,并介绍了不同的通信机制,如管道、消息队列、共享内存、信号量、信号和套接字。通过理解这些通信机制的特点和应用场景,可以更好地实现进程间的高效数据共享。同时,本文还强调了同步和互斥机制的重要性,以确保数据的一致性和正确性。最后,还介绍了套接字作为一种跨网络和同一主机上进程间通信的通信机制,为读者提供了更全面的了解。通过阅读本文,读者将能够深入理解进程间通信的概念和不同机制,为实现有效的数据共享提供指导。
深入探讨进程间通信的重要性:理解不同的通信机制(下)

相关实验场景

更多