4. Binder进程上下文管理
任务目标
在Binder IPC框架中,每个客户端进程与服务端进程都需要独立的上下文记录,用于保存进程标识、调度优先级以及当前Binder通信状态。本案例实现一个轻量级的binder_proc_ctx结构体及其管理接口,支持上下文的创建、查询、更新与销毁,并模拟多进程并发访问时的状态切换。
核心实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define MAX_CTX 64
#define CTX_ACTIVE 0
#define CTX_BLOCKED 1
#define CTX_DEAD 2
typedef struct {
int pid;
int priority; /* 0-99,数值越小优先级越高 */
int state; /* CTX_ACTIVE / CTX_BLOCKED / CTX_DEAD */
char process_name[32];
} binder_proc_ctx;
static binder_proc_ctx ctx_table[MAX_CTX];
static int ctx_count = 0;
static pthread_mutex_t ctx_lock = PTHREAD_MUTEX_INITIALIZER;
/* 创建或更新进程上下文 */
int binder_ctx_register(int pid, const char *name, int priority) {
if (!name || priority < 0 || priority > 99) return -1;
pthread_mutex_lock(&ctx_lock);
for (int i = 0; i < ctx_count; i++) {
if (ctx_table[i].pid == pid) {
ctx_table[i].priority = priority;
ctx_table[i].state = CTX_ACTIVE;
snprintf(ctx_table[i].process_name, sizeof(ctx_table[i].process_name), "%s", name);
pthread_mutex_unlock(&ctx_lock);
return 0; /* 已存在,更新 */
}
}
if (ctx_count >= MAX_CTX) {
pthread_mutex_unlock(&ctx_lock);
return -2; /* 表满 */
}
ctx_table[ctx_count].pid = pid;
ctx_table[ctx_count].priority = priority;
ctx_table[ctx_count].state = CTX_ACTIVE;
snprintf(ctx_table[ctx_count].process_name, sizeof(ctx_table[ctx_count].process_name), "%s", name);
ctx_count++;
pthread_mutex_unlock(&ctx_lock);
return 1; /* 新建 */
}
/* 查询进程上下文,返回指针;未找到返回NULL */
binder_proc_ctx *binder_ctx_lookup(int pid) {
pthread_mutex_lock(&ctx_lock);
for (int i = 0; i < ctx_count; i++) {
if (ctx_table[i].pid == pid) {
pthread_mutex_unlock(&ctx_lock);
return &ctx_table[i];
}
}
pthread_mutex_unlock(&ctx_lock);
return NULL;
}
/* 更新进程状态 */
int binder_ctx_set_state(int pid, int new_state) {
if (new_state != CTX_ACTIVE && new_state != CTX_BLOCKED && new_state != CTX_DEAD)
return -1;
binder_proc_ctx *ctx = binder_ctx_lookup(pid);
if (!ctx) return -2;
ctx->state = new_state;
return 0;
}
/* 移除进程上下文 */
int binder_ctx_unregister(int pid) {
pthread_mutex_lock(&ctx_lock);
for (int i = 0; i < ctx_count; i++) {
if (ctx_table[i].pid == pid) {
ctx_table[i] = ctx_table[ctx_count - 1];
ctx_count--;
pthread_mutex_unlock(&ctx_lock);
return 0;
}
}
pthread_mutex_unlock(&ctx_lock);
return -1;
}
/* 打印当前所有上下文(调试用) */
void binder_ctx_dump(void) {
pthread_mutex_lock(&ctx_lock);
printf("=== Binder进程上下文表 (共%d个) ===\n", ctx_count);
for (int i = 0; i < ctx_count; i++) {
const char *state_str = ctx_table[i].state == CTX_ACTIVE ? "ACTIVE" :
ctx_table[i].state == CTX_BLOCKED ? "BLOCKED" : "DEAD";
printf(" [%d] pid=%d name=%s prio=%d state=%s\n",
i, ctx_table[i].pid, ctx_table[i].process_name,
ctx_table[i].priority, state_str);
}
pthread_mutex_unlock(&ctx_lock);
}
/* 模拟两个进程并发注册与状态切换 */
void *worker_thread(void *arg) {
int pid = *(int *)arg;
char name[16];
snprintf(name, sizeof(name), "proc_%d", pid);
binder_ctx_register(pid, name, pid % 50);
binder_ctx_set_state(pid, CTX_BLOCKED);
usleep(100);
binder_ctx_set_state(pid, CTX_ACTIVE);
return NULL;
}
int main(void) {
pthread_t t1, t2;
int pid1 = 1001, pid2 = 1002;
/* 注册两个进程 */
binder_ctx_register(pid1, "system_server", 20);
binder_ctx_register(pid2, "surfaceflinger", 35);
/* 查询并验证 */
binder_proc_ctx *ctx = binder_ctx_lookup(pid1);
if (ctx) {
printf("查询pid=%d: name=%s priority=%d state=%d\n",
ctx->pid, ctx->process_name, ctx->priority, ctx->state);
}
/* 并发状态切换 */
pthread_create(&t1, NULL, worker_thread, &pid1);
pthread_create(&t2, NULL, worker_thread, &pid2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
/* 更新优先级 */
binder_ctx_set_state(pid1, CTX_BLOCKED);
binder_ctx_register(pid1, "system_server", 10); /* 提升优先级 */
binder_ctx_dump();
/* 注销 */
binder_ctx_unregister(pid2);
printf("注销pid=%d后,剩余上下文数: %d\n", pid2, ctx_count);
return 0;
}
编译与运行
gcc -o binder_ctx binder_ctx.c -lpthread
./binder_ctx
验证方法
程序输出应包含以下关键信息,满足即判定通过:
- 查询
pid=1001时返回name=system_server priority=20 state=0(state=0表示ACTIVE); - 并发线程执行后,两个进程均完成
BLOCKED→ACTIVE状态切换,最终dump表中无BLOCKED状态; - 重新注册
pid=1001后优先级从20变为10,且上下文数量不增加(更新而非重复创建); - 注销
pid=1002后,dump表只剩pid=1001一项,输出剩余上下文数为1。
关键说明
- 上下文表使用全局数组+互斥锁保护,模拟内核中
binder_proc的哈希表管理; - 优先级范围0-99与Linux实时优先级语义一致,数值越小优先级越高;
- 状态机仅包含
ACTIVE/BLOCKED/DEAD三种,对应Binder线程在等待事务、处理事务或已退出时的核心状态; - 实际内核中每个进程的
binder_proc还包含线程树、待处理事务链表等,本案例聚焦上下文管理核心逻辑。