Binder 内存分配

本文详细介绍了Android 6.0中Binder内存分配的实现,包括binder_alloc_mmap_handler函数的映射过程,binder_alloc_new_buf分配缓冲区的步骤,以及释放内存的策略。重点讨论了两个红黑树如何分别管理已分配和未分配的buffer,并且阐述了相邻free_buffer的合并机制。

android6.0已经把binder_buffer有关的操作和binder.c分开了,实现在binder_alloc.c文件里面
一、binder_alloc_mmap_handler函数进行map,先看这个结构体:

struct binder_alloc {
    struct mutex mutex;
    struct vm_area_struct *vma;
    struct mm_struct *vma_vm_mm;
    void *buffer; // map 的地址就是这里了
    ptrdiff_t user_buffer_offset; //内核空间和用户空间的差
    struct list_head buffers; //所有的buffers列表
    struct rb_root free_buffers; //只进行了预定,没有分配,按大小排序
    struct rb_root allocated_buffers; //已经分配了,按地址排序
    size_t free_async_space; //用于异步请求的空间
    struct binder_lru_page *pages;//所有的pages
    size_t buffer_size; //总共的大小
    uint32_t buffer_free;
    int pid;
};

参数alloc和proc相关,也就是每个进程一个,vma用户调用传入参数
int binder_alloc_mmap_handler(struct binder_alloc *alloc,
struct vm_area_struct *vma);
这个函数流程比较简单,关键流程如下:
1、

area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
    alloc->buffer = area->addr;
    alloc->user_buffer_offset =vma->vm_start - (uintptr_t)alloc->buffer;

预定空间,初始化alloc的buffer和

<think>嗯,用户的问题聚焦在内核中Binder通信数据结构的kmalloc内存分配机制。用户引用了五篇技术文档片段,其中引用[2]明确提到kmalloc用于分配物理连续内存,最大128KB,而引用[1][4][5]详细描述了Binder驱动中进程级数据结构(如binder_proc、binder_thread)的创建流程。这需要我验证kmallocBinder子系统中的具体应用场景。 用户可能正在研究Android底层通信机制,或是调试内核模块时遇到了内存分配问题。从ta引用的技术细节来看,应该具备一定的内核开发基础,但需要确认kmallocBinder的耦合点。深层需求可能是想理解Binder如何在内核层保证进程隔离的同时实现高效通信。 结合引用[5]的binder_init初始化流程和binder_open操作,当进程首次打开/dev/binder时会调用binder_open(),此时需要为binder_proc分配内存。引用[2]的kmalloc特性完全匹配——binder_proc这类关键数据结构需要物理连续内存保证原子操作安全,且其大小远小于128KB限制。 特别要注意引用[4]提到的binder_thread创建流程:通过binder_get_thread()为每个线程分配结构体时,实际会调用kmalloc。这与用户问题中"每个进程的Binder通信数据结构"完全对应,包括proc和thread两个层级。 需要强调kmalloc的替代方案:当结构体超过128KB时需用vmalloc,但Binder设计规避了此情况。另外kzalloc在初始化时更常用,它本质是带GFP_ZERO标志的kmalloc,这点在引用[2]的释放函数kfree()中也能印证。 用户可能后续会关注内存泄漏排查,所以补充了proc->buffer列表管理机制(引用[1])。最后用线程结构体分配的代码片段强化结论,并准备三个延伸方向:内存分配失败处理、GFP标志影响、结构体大小优化空间。</think>是的,在Linux内核的Binder驱动实现中,`kmalloc` 是用于为每个进程的Binder通信关键数据结构(主要是 `struct binder_proc` 和 `struct binder_thread`)分配内存的主要机制。 以下是详细说明和依据: 1. **进程级数据结构 (`binder_proc`)**: * 当用户态进程首次打开 `/dev/binder` 设备文件时,内核会调用 `binder_open()` 函数(引用[5])。 * 在 `binder_open()` 内部,需要为**每个进程**创建一个 `struct binder_proc` 对象。这个结构体存储了该进程所有与 Binder 通信相关的状态信息(如线程列表、待处理事务列表、缓冲区链表等)。 * 该 `binder_proc` 结构体的内存正是通过 `kmalloc()` 分配的(通常使用 `kzalloc`,它是 `kmalloc` 的一个封装,会将分配的内存清零)。这符合引用[2]中描述的 `kmalloc` 用于分配物理上连续的内核内存的特性。 * 分配成功后,该 `binder_proc` 结构体会被初始化并关联到打开的文件描述符(`struct file`)的私有数据 (`private_data`) 上。 2. **线程级数据结构 (`binder_thread`)**: * 当用户态进程(或线程)首次通过 `ioctl()` 系统调用与 Binder 驱动交互时(例如发送 `BINDER_WRITE_READ` 命令),内核会调用 `binder_get_thread()` 函数(引用[4])。 * `binder_get_thread()` 的作用是查找或为**当前内核线程**(对应于用户态调用线程)创建一个 `struct binder_thread` 对象。这个结构体存储了该线程特定的 Binder 状态(如待处理事务、等待队列等)。 * 如果需要创建新的 `binder_thread` 结构体,其内存同样是通过 `kmalloc()`(或 `kzalloc()`)分配的(引用[4])。 * 新创建的 `binder_thread` 结构体会被添加到其所属进程的 `binder_proc` 结构体的线程列表中(`proc->threads` 或类似结构)。 **总结依据:** * **引用[2]:** 明确指出 `kmalloc()` 用于分配物理连续的内核内存,这正是内核数据结构(如 `binder_proc`, `binder_thread`)分配所需要的。 * **引用[4]:** 描述了 `binder_get_thread()` 函数负责为线程创建 `binder_thread` 结构体,其分配机制符合 `kmalloc` 的用途。 * **引用[5]:** 描述了 `binder_open()` 函数在进程首次打开 Binder 设备时被调用,这是创建 `binder_proc` 结构体的关键点,其分配机制同样符合 `kmalloc` 的用途。 * **设计需求:** `binder_proc` 和 `binder_thread` 是内核中频繁访问和操作的核心数据结构,需要高效的访问速度。`kmalloc` 分配的物理连续内存能提供良好的缓存局部性,比 `vmalloc` 分配的虚拟连续(物理可能不连续)内存访问更快,更适合这种关键数据结构。 **因此,你的理解是正确的:** 内核使用 `kmalloc`(或其清零封装 `kzalloc`)来为每个使用 Binder 的进程分配其专属的 `struct binder_proc` 内存,并为该进程内每个首次进行 Binder 调用的线程分配其专属的 `struct binder_thread` 内存。这些数据结构是管理每个进程 Binder 通信状态的核心。 ```c // 示例 (简化概念) static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; // 为当前进程分配 binder_proc 结构体 (通常用 kzalloc) proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (!proc) return -ENOMEM; // ... 初始化 proc 结构体 ... filp->private_data = proc; // 关联到文件 // ... } static struct binder_thread *binder_get_thread(struct binder_proc *proc) { struct binder_thread *thread = NULL; // ... 尝试查找现有线程结构体 ... if (thread == NULL) { // 为新线程分配 binder_thread 结构体 (通常用 kzalloc) thread = kzalloc(sizeof(*thread), GFP_KERNEL); if (thread == NULL) return NULL; // ... 初始化 thread 结构体并添加到 proc->threads 列表 ... } return thread; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值