一、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散列表,注册完毕后,等待客户端的服务请求。