binder内核缓冲区管理

这篇博客详细探讨了Android系统中Binder内核缓冲区的分配过程,特别是在`binder_alloc_buf`函数中的实现。文章指出,在分配过程中,如何找到最佳适配的缓冲区,以及如何处理异步交易的空间需求。同时,它提出了一个问题:当缓冲区大小经过裁剪并与页面对齐时,是否可能导致新缓冲区部分没有分配物理内存的情况。这引发对于内核缓冲区管理有效性的讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
size_t data_size, size_t offsets_size, int is_async)
{
struct rb_node *n = proc->free_buffers.rb_node;
struct binder_buffer *buffer;
size_t buffer_size;
struct rb_node *best_fit = NULL;
void *has_page_addr;
void *end_page_addr;
size_t size;

if (proc->vma == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n",
       proc->pid);
return NULL;
}

size = ALIGN(data_size, sizeof(void *)) +
ALIGN(offsets_size, sizeof(void *));

if (size < data_size || size < offsets_size) {
binder_user_error("binder: %d: got transaction with invalid "
"size %zd-%zd\n", proc->pid, data_size, offsets_size);
return NULL;
}

if (is_async &&
    proc->free_async_space < size + sizeof(struct binder_buffer)) {
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd f"
       "ailed, no async space left\n", proc->pid, size);
return NULL;
}

while (n) {
buffer = rb_entry(n, struct binder_buffer, rb_node);
BUG_ON(!buffer->free);
buffer_size = binder_buffer_size(proc, buffer);

if (size < buffer_size) {
best_fit = n;
n = n->rb_left;
} else if (size > buffer_size)
n = n->rb_right;
else {
best_fit = n;
break;
}
}
if (best_fit == NULL) {
printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
       "no address space\n", proc->pid, size);
return NULL;
}
if (n == NULL) {
buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
buffer_size = binder_buffer_size(proc, buffer);
}
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got buff"
       "er %p size %zd\n", proc->pid, size, buffer, buffer_size);

    /*
    #define PAGE_SHIFT   12
    #define PAGE_SIZE   (1UL << PAGE_SHIFT)
    #define PAGE_MASK   (~(PAGE_SIZE-1))
    */
    
has_page_addr =
(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
if (n == NULL) {
if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
buffer_size = size; /* no room for other buffers */
else
buffer_size = size + sizeof(struct binder_buffer);
}
end_page_addr =
(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
if (end_page_addr > has_page_addr)
end_page_addr = has_page_addr;
if (binder_update_page_range(proc, 1,
    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
return NULL;

rb_erase(best_fit, &proc->free_buffers);
buffer->free = 0;
binder_insert_allocated_buffer(proc, buffer);
if (buffer_size != size) {
struct binder_buffer *new_buffer = (void *)buffer->data + size;
list_add(&new_buffer->entry, &buffer->entry);
new_buffer->free = 1;
binder_insert_free_buffer(proc, new_buffer);
}
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got "
       "%p\n", proc->pid, size, buffer);
buffer->data_size = data_size;
buffer->offsets_size = offsets_size;
buffer->async_transaction = is_async;
if (is_async) {
proc->free_async_space -= size + sizeof(struct binder_buffer);
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC_ASYNC)
printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd "
       "async free %zd\n", proc->pid, size,
       proc->free_async_space);
}

return buffer;
}

[size=16px]在分配内核缓冲区里面用,裁剪后新的内核缓冲区部分或者全部是不是有可能位于无效物理内存呢?
       假设裁剪后的buffer->data + buffer_size恰好对齐到页面边界,则此时内核缓冲区的结束地址也等于end_page_addr,那么此时binder_update_page_range(proc, 1, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL)分配物理内存时,裁剪后新的内核缓冲区结构体不就没有分配物理内存么?
[/size]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值