Android 用java程序模拟binder buffer的分配释放以及buffer的向前和向后合并

用Java代码模拟以下代码,以便理解

/* 处理缓冲区分割:如果找到的缓冲区比需要的大 */
	if (buffer_size != size) {
		/* 找到 oversized 缓冲区,需要进行分割 */
		buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
		buffer_size = binder_alloc_buffer_size(alloc, buffer);

		/* 确保条件正确:不应该有精确匹配,且缓冲区确实大于需求 */
		WARN_ON(n || buffer_size == size);
		
		/* 设置新缓冲区的起始地址(原缓冲区地址 + 需求大小) */
		new_buffer->user_data = buffer->user_data + size;
		/* 将新缓冲区添加到链表中 */
		list_add(&new_buffer->entry, &buffer->entry);
		new_buffer->free = 1;  // 标记为空闲
		/* 将剩余部分插入空闲树 */
		binder_insert_free_buffer(alloc, new_buffer);
		new_buffer = NULL;  // 防止后续重复释放
	}

Java代码如下:
DemoTwoListDebug.java

import java.util.*;

public class DemoTwoListDebug {

    /* -------------------- 结点 -------------------- */
    private static final class Node {
        long addr, size;
        Node prev, next;
        Node(long a, long s) { addr = a; size = s; }
        String range() { return String.format("[%08X,%08X)", addr, addr + size); }
    }

    /* -------------------- 两条链表 -------------------- */
    private final Node allocHead = new Node(-1, -1);
    private final Node freeHead  = new Node(-1, -1);
    { allocHead.next = allocHead.prev = allocHead; }
    { freeHead.next  = freeHead.prev  = freeHead; }

    private final long totalSize;

    public DemoTwoListDebug(long totalSize) {
        this.totalSize = totalSize;
        insertFree(new Node(0, totalSize));
        debug("初始");
    }

    /* ==================== 分配 ==================== */
    public synchronized long alloc(long req) {
        if (req <= 0) return -1;
        Node best = null, cur = freeHead.next;
        while (cur != freeHead) {
            if (cur.size >= req && (best == null || cur.size < best.size))
                best = cur;
            cur = cur.next;
        }
        if (best == null) {
            debug("alloc failed");
            return -1;
        }
        /* 摘空闲 */
        removeFree(best);
        debug(String.format("best-fit 选中 %s", best.range()));

        /* 切分 */
        long rem = best.size - req;
        if (rem > 0) {
            Node split = new Node(best.addr + req, rem);
            insertFree(split);
            debug(String.format("切分剩余 %s", split.range()));
        }

        /* 插已分配 */
        Node allocNode = new Node(best.addr, req);
        insertAlloc(allocNode);
        debug("after alloc");
        return allocNode.addr;
    }

    /* ==================== 释放 ==================== */
    public synchronized void free(long addr) {
        Node tgt = allocHead.next;
        while (tgt != allocHead && tgt.addr != addr) tgt = tgt.next;
        if (tgt == allocHead) throw new IllegalArgumentException("bad addr");
        removeAlloc(tgt);
        debug(String.format("free %s", tgt.range()));

        /* 先插空闲(保持有序)再合并 */
        insertFree(tgt);
        coalesce(tgt);
        debug("after free");
    }

    /* ==================== 合并 ==================== */
    private void coalesce(Node mid) {
        Node prev = mid.prev, next = mid.next;
        if (prev != freeHead && prev.addr + prev.size == mid.addr) {
            debug(String.format("向前合并 %s + %s", prev.range(), mid.range()));
            prev.size += mid.size;
            removeFree(mid);
            mid = prev;
        }
        if (next != freeHead && mid.addr + mid.size == next.addr) {
            debug(String.format("向后合并 %s + %s", mid.range(), next.range()));
            mid.size += next.size;
            removeFree(next);
        }
    }

    /* ==================== 链表工具 ==================== */
    private void insertFree(Node n) {
        Node cur = freeHead.next;
        while (cur != freeHead && cur.addr < n.addr) cur = cur.next;
        Node pre = cur.prev;
        pre.next = n; n.prev = pre;
        n.next = cur; cur.prev = n;
    }
    private void removeFree(Node n)  { n.prev.next = n.next; n.next.prev = n.prev; }
    private void insertAlloc(Node n) { /* 头插即可 */ n.next = allocHead.next; n.prev = allocHead;
                                       allocHead.next.prev = n; allocHead.next = n; }
    private void removeAlloc(Node n) { n.prev.next = n.next; n.next.prev = n.prev; }

    /* ==================== 调试打印 ==================== */
    private void debug(String phase) {
        System.out.printf("========== %s ==========%n", phase);
        System.out.println("freeList (addr升序):");
        Node cur = freeHead.next;
        while (cur != freeHead) {
            System.out.printf("  %s%n", cur.range());
            cur = cur.next;
        }
        System.out.println("allocatedList:");
        cur = allocHead.next;
        while (cur != allocHead) {
            System.out.printf("  %s%n", cur.range());
            cur = cur.next;
        }
        System.out.println();
    }

    /* ==================== 交互 ==================== */
    public static void main(String[] args) {
        DemoTwoListDebug alloc = new DemoTwoListDebug(1024);
        Scanner in = new Scanner(System.in);
        System.out.println("Commands:  alloc <size>  |  free <addr>  |  exit");
        while (true) {
            System.out.print("> ");
            String line = in.nextLine().trim();
            if (line.equalsIgnoreCase("exit")) break;
            String[] tok = line.split("\\s+");
            if (tok.length != 2) { System.out.println("bad cmd"); continue; }
            try {
                if (tok[0].equals("alloc")) {
                    long sz = Long.parseLong(tok[1]);
                    long a = alloc.alloc(sz);
                    if (a == -1) System.out.println("alloc failed");
                } else if (tok[0].equals("free")) {
                    long a = Long.parseLong(tok[1], 16);
                    alloc.free(a);
                } else {
                    System.out.println("unknown cmd");
                }
            } catch (Exception e) {
                System.out.println("error: " + e.getMessage());
            }
        }
    }
}

调试结果如下:

javac DemoTwoListDebug.java && java DemoTwoListDebug
========== 初始 ==========
freeList (addr升序):
  [00000000,00000400)
allocatedList:

Commands:  alloc <size>  |  free <addr>  |  exit
> alloc 100
========== best-fit 选中 [00000000,00000400) ==========
freeList (addr升序):
allocatedList:

========== 切分剩余 [00000064,00000400) ==========
freeList (addr升序):
  [00000064,00000400)
allocatedList:

========== after alloc ==========
freeList (addr升序):
  [00000064,00000400)
allocatedList:
  [00000000,00000064)

> alloc 300
========== best-fit 选中 [00000064,00000400) ==========
freeList (addr升序):
allocatedList:
  [00000000,00000064)

========== 切分剩余 [00000190,00000400) ==========
freeList (addr升序):
  [00000190,00000400)
allocatedList:
  [00000000,00000064)

========== after alloc ==========
freeList (addr升序):
  [00000190,00000400)
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

> alloc 10
========== best-fit 选中 [00000190,00000400) ==========
freeList (addr升序):
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

========== 切分剩余 [0000019A,00000400) ==========
freeList (addr升序):
  [0000019A,00000400)
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

========== after alloc ==========
freeList (addr升序):
  [0000019A,00000400)
allocatedList:
  [00000190,0000019A)
  [00000064,00000190)
  [00000000,00000064)

> free 190
========== free [00000190,0000019A) ==========
freeList (addr升序):
  [0000019A,00000400)
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

========== 向后合并 [00000190,0000019A) + [0000019A,00000400) ==========
freeList (addr升序):
  [00000190,0000019A)
  [0000019A,00000400)
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

========== after free ==========
freeList (addr升序):
  [00000190,00000400)
allocatedList:
  [00000064,00000190)
  [00000000,00000064)

> free 0
========== free [00000000,00000064) ==========
freeList (addr升序):
  [00000190,00000400)
allocatedList:
  [00000064,00000190)

========== after free ==========
freeList (addr升序):
  [00000000,00000064)
  [00000190,00000400)
allocatedList:
  [00000064,00000190)

> free 64
========== free [00000064,00000190) ==========
freeList (addr升序):
  [00000000,00000064)
  [00000190,00000400)
allocatedList:

========== 向前合并 [00000000,00000064) + [00000064,00000190) ==========
freeList (addr升序):
  [00000000,00000064)
  [00000064,00000190)
  [00000190,00000400)
allocatedList:

========== 向后合并 [00000000,00000190) + [00000190,00000400) ==========
freeList (addr升序):
  [00000000,00000190)
  [00000190,00000400)
allocatedList:

========== after free ==========
freeList (addr升序):
  [00000000,00000400)
allocatedList:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值