目录
启动两个进程(进程间socket通信的发送端和接收端)分别进行初始化,通过统一的本地文件进行进程间socket通信。
服务端(接收端)执行socket->bind->listen->accept四步。
客户端(发送端)执行socket->connect两步。
若只开了服务端,则一直accept等待客户端连接,若只开了客户端,则connect不上重复connect直至超时。
通过memfd_create创建内存共享文件句柄,两端需要同时拥有这个文件句柄才能进行内存共享,因此在第一步中client connect成功之后则创建句柄,通过sendmsg发送给server,server accept成功之后则recvfrom等待接收这个文件句柄。
两端均拿到文件句柄之后,同时开启mmap,进行内存地址的共享,两个进程共同拿到一个函数指针,指向同一块内存地址。下面再进行指针偏移的操作进行数据的共享传输。
通过读写指针的更新在同一块内存地址上进行数据的共享,一边放数据更新写指针,一边读数据更新读指针。读之前根据读写指针判断是否可读,写之前根据读写指针判断是否可写。
客户端和服务端共享一块地址时会给这块地址分配一个大小,此处比如100M,也即1024*1024*100 字节(Byte),随后再设置一个单块数据的大小限制,如2M,单块数据表示每次入的大小必须小于2M。整个共享内存100M的头部会有一个结构体常驻在此,长期共享读写指针之类的数据,在它的后面才是每一包数据的读写,读写的依据都是头部实时更新的读写指针位置数据。

除了头部数据(我们算sizeof(SShareHead))之外,剩余的内存写进程从第一个2M开始放,读进程从第一个2M开始读。
速度:
1、若写的比读的快,那么写指针会一直往后,直到耗尽了100M,此时会从第一个2M开始继续覆盖,极端情况下如果读指针还停留在第一个2M的位置,那么就不可写了,若读指针在一半的位置,那么写指针会去追逐它直到追上,那么就会停止写入,读进程读一次,写进程才有空余写一次,速度就完全由慢一些的读进程决定了。
2、若读的比较快,那么根据读写指针的计算,会判断不可读,直到有写入数据,速度完全由写进程决定。
最终有一种环形追逐的感觉,所以我们称之为环形buf,其实实质上是一块内存重复读写。
- /*更新写指针*/
- //初始化的时候dwRingLen = 100M - sizeof(SShareHead)) - 2M //总长度去掉头部,去掉一包数据
-
- if (dwWidx + dwWriteLen >= dwRingLen)
- {
- //如果写指针 + 当前要写的数据已经到达最后一个数据块(最后一个2M)的位置,则写指针清零,从零开始写
- dwWidx = 0;
- }
- else
- {
- //否则写指针正常往后加
- dwWidx += dwWriteLen;
- }
- if (dwRidx + dwReadLen >= dwRingLen)
- dwRidx = 0;
- else
- dwRidx += dwReadLen;
- //dwLen是此次想要写入的长度
- bool checkWritable(u32 dwLen)
- {
- //u32代表unsigned int
- //初始化的时候dwRingLen = 100M - sizeof(SShareHead)) - 2M
- //总长度去掉头部,去掉一包数据,见数据框图
- u32 dwSpace = dwRingLen - (dwWidx - dwRidx + dwRingLen) % dwRingLen;
- if (dwWidx > dwRidx && dwRidx > 0)
- {
- dwSpace += dwTailLen;
- }
- return (dwSpace > dwLen);
- }
- dwLen = (dwWidx - dwRidx + dwRingLen) % dwRingLen;
- //有数据直接返回,TProcessShareDataHead是自定义的私有数据头
- if (dwLen >= sizeof(TProcessShareDataHead))
- {
- //m_pDataAddr是数据框图的红色箭头指向处
- pHead = (TProcessShareDataHead *)(m_pDataAddr + mdwRidx);
- return true;
- }
- //校验拖尾数据是否可读,极端情况读指针在最后,写指针在最前面
- //读指针=dwRingLen-1,写指针=0;实际上读指针还能再读最后一包数据
- if (dwRidx > dwWidx)
- {
- //m_pDataAddr是数据框图的红色箭头指向处
- pHead = (TProcessShareDataHead *)(m_pDataAddr + dwRidx);
- return true;
- }
- return false;