binder pro驱动实现:服务端实现

该文描述了RPC服务在服务端的注册过程,使用红黑树进行高效查找和插入,同时结合哈希散列表存储,以便于管理和查找。当注册RPC服务时,首先插入红黑树,然后插入哈希表。删除和查找操作对应地从树和表中移除或搜索节点。此外,还涉及到了自旋锁对并发操作的保护。
摘要由CSDN通过智能技术生成

一、rpc服务的红黑树实现

bool register_rpc(struct rb_root *root, struct rpc_register *rpc)
{
  	struct rb_node **new = &(root->rb_node), *parent = NULL;

  	/* Figure out where to put new node */
  	while (*new) {
  		struct rpc_register *this = container_of(*new, struct rpc_register, rb_node_rpc);
  		uint rpc_id = this->rpc_id;

		parent = *new;
  		if (rpc->rpc_id < rpc_id)
  			new = &((*new)->rb_left);
  		else if (rpc->rpc_id > rpc_id)
  			new = &((*new)->rb_right);
  		else {
			printk("insert error rpc id %d, pid %d\n", rpc_id, rpc->pid);
  			return false;
		}
  	}

  	/* Add new node and rebalance tree. */
  	rb_link_node(&rpc->rb_node_rpc, parent, new);
  	rb_insert_color(&rpc->rb_node_rpc, root);

	return true;
}

struct rpc_register *rpc_search(struct rb_root *root, uint rpc_id)
{
  	struct rb_node *node = root->rb_node;

  	while (node) {
  		struct rpc_register *rpc_find = container_of(node, struct rpc_register, rb_node_rpc);


		if (rpc_id < rpc_find->rpc_id)
  			node = node->rb_left;
		else if (rpc_id > rpc_find->rpc_id)
  			node = node->rb_right;
		else
  			return rpc_find;
	}
	return NULL;
}

void delete_rpc(struct rb_root *rb_root, struct rpc_register *rpc) {
  	if (rpc) {
  		rb_erase(&rpc->rb_node_rpc, rb_root);
  		kfree(rpc);
  	}
}

void delete_rpc_by_id(struct rb_root *rb_root, uint rpc_id)
{
	struct rpc_register *rpc;
	rpc = rpc_search(rb_root, rpc_id);
	delete_rpc(rb_root, rpc);
}

二、将rpc注册到红黑树和hash散列表

2.1 rpc红黑树的操作

static long bind_rpc_operate(struct binder_dev *binder_devp, unsigned int cmd, unsigned long __arg) {
	uint rpc_id;
	uint ret;
	bool bool_ret;
	struct rpc_register *rpc_reg;
	struct rb_root *rpc_rb_root = &binder_devp->rpc_root;

	ret = copy_from_user(&rpc_id, (void __user *)__arg, sizeof(uint));
	if (ret != 0) {
		return -EINVAL;
	}

	switch (cmd) {
		case RB_TREE_INSERT_CMD: {
			rpc_reg = kmalloc(sizeof(struct rpc_register), GFP_KERNEL);
			if (!rpc_reg) {
				return -EINVAL;
			}
			memset(rpc_reg, 0, sizeof(struct rpc_register));
			rpc_reg->rpc_id = rpc_id;
			rpc_reg->pid = current->pid;
			bool_ret = register_rpc(rpc_rb_root,rpc_reg);
			if (!bool_ret) {
				kfree(rpc_reg);
				return -EINVAL; 
			}
			ret = insert_rpc_hlist(binder_devp->server_hash, rpc_reg, rpc_reg->pid);
			if (ret != BIND_RET_SUCCESS) {
                delete_rpc_by_id(rpc_rb_root,  rpc_id);
				kfree(rpc_reg);
				return -EINVAL;
			}
			break;
		}
		case RB_TREE_EREASE_CMD:
			delete_rpc_by_id(rpc_rb_root,  rpc_id);
			break;
		case RB_TREE_SEARCH_CMD:
			rpc_reg = rpc_search(rpc_rb_root, rpc_id);
			if (!rpc_reg) {
				printk("finder node error\n");
				return -EINVAL;
			}
			break;
		default:
			return BIND_INVLIED_ID;
	}

	return BIND_RET_SUCCESS;
}

2.2 rpc服务节点的相关操作

/* 集中处理server item需要用锁的业务,方便自旋锁的管理 */
void server_item_lock(struct server_item *server_item,struct rpc_register *rpc_reg, struct rpc_node *rpc_node, uint action) {
    unsigned long flags;

    spin_lock_irqsave(&server_item->item_lock, flags);	/* 上锁 */    
    switch (action) {
        case RPC_LIST_ADD:
            list_add(&rpc_reg->reg_list, &server_item->reg_list);
            break;
        case NODE_LIST_INSERT:
            if (server_item->start_node_id == BIND_INVLIED_ID) {
                server_item->start_node_id = rpc_node->node_id;
            } else {
                rpc_node->next_service_req = server_item->start_node_id;
                server_item->start_node_id = rpc_node->node_id;
            }
            break;
        case RPC_LIST_DEL:
            list_del(&rpc_reg->reg_list); 
            break;
        case RPC_SERVER_GET:
            server_item->process_node_id = server_item->start_node_id;
            server_item->start_node_id = BIND_INVLIED_ID;
            break;
        default:
            printk("server action can not find:%d \n", action);
            break;
    }
    spin_unlock_irqrestore(&server_item->item_lock, flags);
}

/* 开始执行客户端的请求 */
void start_server_rpc(struct server_item *server_item)
{
    server_item_lock(server_item, NULL, NULL, RPC_SERVER_GET);
}

/* 在客户端的rpc请求插入到待处理的链表 */
void insert_node_list(struct server_item *server_item, struct rpc_node *rpc_node)
{
    server_item_lock(server_item, NULL, rpc_node, NODE_LIST_INSERT);
}

/* 在hash散列表中删除注册的rpc节点 */
void rpc_node_del(struct list_head *server_hash, struct rpc_register *rpc_reg, struct rb_root *rpc_root)
{
    struct server_item *server_item;

    delete_rpc_by_id(rpc_root, rpc_reg->rpc_id);
    server_item = find_server_item(server_hash, rpc_reg->rpc_id);
    if (server_item != NULL) {
        server_item_lock(server_item, rpc_reg, NULL, RPC_LIST_DEL);
    }
}

/* 将客户端的请求插入到服务端的hash散列表 */
uint req_to_server(struct list_head *server_head, struct rpc_node *rpc_node)
{
    pid_t pid;
    struct server_item *server_item;

    pid = rpc_node->service_pid;
    server_item = find_server_item(server_head, pid);
    if (server_item == NULL) {
        printk("can not find server item pid:%d \n", pid);
        return BIND_RET_ERROR;
    }
    insert_node_list(server_item, rpc_node);

    return BIND_RET_SUCCESS;
}

/* 更具pid查找server item */
struct server_item *get_server_item(struct list_head  *server_head, pid_t sever_pid)
{
    struct server_item *server_item;

    list_for_each_entry(server_item, server_head, hash_list)  {
        if (server_item->pid == sever_pid) {
            return server_item;
        }
    } 

    return NULL;
}

/* 查找服务端注册的rpc节点 */
struct rpc_register *get_rpc_reg(struct server_item *server_item, uint rpc_id)
{
    struct rpc_register *rpc_reg;
    list_for_each_entry(rpc_reg, &server_item->reg_list, reg_list) {
        if (rpc_reg->rpc_id == rpc_id) {
            return rpc_reg;
        }
    }

    return NULL;
}

/* 从hash散列表中查找server item */
struct server_item *find_server_item(struct list_head *server_hash, pid_t sever_pid)
{
    struct server_item *server_item;
    struct list_head *head;

    head = &server_hash[sever_pid % BINDER_HASH_SIZE];
    server_item = get_server_item(head, sever_pid);

    return server_item;
}

2.3 将rpc节点插入哈希表


uint insert_rpc_hlist(struct list_head *server_heads, struct rpc_register *rpc_reg, pid_t pid)
{
	struct server_item *server_item;
	bool server_item_exist;

	struct list_head *server_head= &server_heads[pid % BINDER_HASH_SIZE];
	server_item_exist = false;
	list_for_each_entry(server_item, server_head, hash_list) {
		if (server_item->pid == pid) {
			server_item_exist = true;
			break;
		}
	}

	if (!server_item_exist) {
		server_item = kmalloc(sizeof(struct server_item), GFP_KERNEL);
		if (server_item == NULL) {
			printk("out of memory \n");
			return BIND_RET_ERROR;
		}
		server_item->pid = pid;
		spin_lock_init(&server_item->item_lock);
		INIT_LIST_HEAD(&server_item->reg_list);
		server_item->start_node_id = BIND_INVLIED_ID;
		list_add(&server_item->hash_list, server_head);
	}

    server_item_lock(server_item,rpc_reg, NULL, RPC_LIST_ADD);

	return BIND_RET_SUCCESS;
}

总结:服务端注册rpc,注册形式为红黑树和hash散列表,注册完毕后,等待客户端的服务请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值