基于共享内存的进程间交互式通信方法

文章介绍了内核如何申请并管理共享内存,用于进程间通信。内存被划分为每CPU块、节点位图块、数据位图块、业务节点块和数据块。管理结构体`bind_super`包含各种位图和节点的管理信息,以及自旋锁以保证并发安全。此外,文章还详细描述了每CPU结构体、业务节点描述符以及业务流程,包括客户端和服务器的数据结构组织和RPC注册的红黑树和哈希表组织方式。

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

         原理:内核申请一片内存,并且对其进行管理和分配,共享给其他进程,已达到进程间通信的目的。

一、共享内存的管理方法

        将共享内存进行格式化,按照一定字节对其,本案例用128字节对齐。并且将共享内存分为五大功能块,每CPU块、节点位图块、数据位图块、业务节点块、数据块。

每cpu块:进程于内核沟通的内存区域,每个cpu分配一块,减少锁的使用

节点位图块:映射业务节点内存区域,为节点数据是否被占用提供依据,方便节点的分配。

数据位图块:映射数据块,为数据块是否被占用提供依据,方便数据块的分配。

业务节点块:用来描述进程间通信的业务节点,包括进程通信的客户端、服务端、服务状态、输入输出数据等等。

数据块:用来存储业务的输入输出数据。

1.1 共享内存管理描述符

为了管理这部分内存,需要一个管理结构体,代码如下:

struct binder_buffer_info{
	void *buffer_address;
	uint buffer_size;
	uint block_num;
	uint pfn;
};

struct bind_super{
	struct binder_buffer_info *binder_buffer_info;
	spinlock_t lock_node_map;		/* 自旋锁,操作节点位图 */
	spinlock_t lock_data_map;		/* 自旋锁,操作数据位图 */

	uint cpu_num;			    //记录cpu数量
	void* per_cpu_start; 		//每cpu在共享内存中的起始位置
	uint per_cpu_size;			//记录单个每cpu占用的内存空间
	uint per_cpu_size_total;	//记录所有每cpu占用的内存空间
	int per_cpu_id;

	void* node_map_start;	//记录业务节点位图起点地址
	uint node_map_size;		//记录节点位图占用的空间大小
	int node_map_id;        //记录业务节点位图起点的块编号
	void* node_start;		//记录业务节点起点
	int node_id;            //记录业务节点起始块编号       
	uint node_num_total;	//记录业务节点总数量
	uint node_num_left;		//记录业务节点剩余数量
	uint per_node_size;		//记录每个业务节点大小
	uint node_size_total;	//记录业务节点总大小

	void* data_map_start;	//记录数据位图起点
	int data_map_id;        //记录数据位图起始块编号
	uint data_map_size;		//记录数据总块大小
	void* data_start;		//记录数据块起点地址
	int data_id;
	uint data_num_total;	//记录数据块总数据量
	uint data_num_left;		//记录数据块剩余数量
	uint data_size_total;	//记录数据块总大小
};

具体的图示描述如下:

1.2 每cpu结构体

每cpu用来组织用户态和内核态的通信,可以有效的减少锁的使用,提高进程效率,结构体如下:


struct client_server {
	uint rpc_id;		//需要调用的rpc id
	uint input_size;	//输入参数的长度
	uint output_size;	//输出参数的长度
};

struct bind_percpu{
	uint cpuid; 		//cpuid
	pid_t pid;			//当前使用进程的pid
	uint role;			//当前进程的角色  server、client
	uint server_start_id;// 当前进程为server时,第一个需要服务的node节点id
	uint client_server_max; //一个客户端可以同时申请服务的最大数量
	uint client_need_server_num;//当前进程为client,发起的服务数量
	struct client_server server_need_start[CLIENT_SERVER_MAX];	//客户端需求描述,具体描述如上
};

 1.3业务节点描述符

业务节点描述符如下:

struct rpc_node {
	char rpc_status;	//记录当前节点处理状态,客户端请求中、服务端处理中、服务端处理完、客户端已确认
	uint node_id;        //节点编号,释放节点内存是需要用到
	uint rpc_id;        //该节点处理的业务编号
	pid_t client_pid;	//客户端pid
	pid_t service_pid;	//服务端pid
	uint input_data;	//客户端输入数据
	uint input_data_size;//输入长度
	uint output_data;	//服务端返回值和数据
	uint output_data_size; //输出长度
	uint next_client_req;	//客户端的下一个请求
	uint next_service_req;	//服务端下一个需要处理的请求
};

二 业务流程

2.1 业务流程图

具体流程图如下:

三、业务的具体组织

3.1 组织结构体

业务通过一个总的结构体进行组织,具体结构体如下:

struct binder_dev {
	struct binder_buffer_info binder_buffer_info;      //共享内存简要信息
	struct bind_super binder_super;                    //共享内存描述符
	struct bind_percpu binder_percpu;                  //每cpu描述符
	struct rb_root rpc_root;                           //rpc红黑树根节点
	struct list_head  client_hash[BINDER_HASH_SIZE];   //客户端hash表
	struct list_head  server_hash[BINDER_HASH_SIZE];   //服务进程hash表
	wait_queue_head_t r_client_rq;                     //客户端等待队列头
	wait_queue_head_t r_server_rq;                     //服务端等待队列头
};

3.2 注册的rpc用红黑树和哈希表组织。

数据结构如下: 

struct server_item{
	struct list_head hash_list;    //进程的哈希节点
	struct list_head reg_list;     //注册rpc的哈希节点
	spinlock_t item_lock;          //同步自旋锁
	uint start_node_id;            //该服务进程需要处理的起始业务节点,业务会根据id组成一个单向链表
	uint process_node_id;          //当前正在处理的业务节点链表
	pid_t pid;                     //该节点所属的进程pid
};

struct rpc_register {
	struct rb_node rb_node_rpc;      //红黑树节点
	struct list_head reg_list;       //哈希表节点
	uint rpc_id;                     //rpc的id
	pid_t pid;                       //rpc所属的进程pid
};

3.3 服务端数据组织结构

服务进程数据结构示意图:

 3.4 客户端数据组织结构

结构体如下:

struct client_req_hash {
	struct list_head list_head;  //hash节点
	pid_t pid;                   //节点所属进程pid
	uint req_cnt;                //进程业务需求数量
	atomic_t req_done_num;       //改进程需求完成数量,当需求数量和已完成数量相等,唤醒该进程的等待队列
	uint start_req_node;         //该进程第一个需要处理的业务,业务单向链表第一个节点编号
};

客户端的进程结构示意图可以参考服务进程示意图。

四、总结

        通过对共享内存的管理,对服务进程和客户端进程的数据结构和流程的描述,大致讲解了该工具的实现,具体的代码实现下一章分析。

ps:该工具是原创,欢迎转载。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值