GNU Radio buffer介绍

ccll2026-07-23 14:47:51
3 浏览 0 评论

1、 GNU Radio buffer分配

1.1 buffer使用简述

GNU Radio数据buffer的管理机制是零拷贝循环缓存,这样能够保证来自源

的数据流高效在各个模块之间传输。具体的buffer分配方式如下图所示:

1 buffer的使用方式

页管理存储方式,一开始就分配好,buffer的长度是每页的大小的倍数,同时,每个循环缓存映射成两部分,实际使用的只是其中的一半。Buffersize由用户决定(最大、最小缓存大小设定)。

1.2 buffer创建方式

针对不同的操作系统,GNU Radio提供不同配置方式。由vmcircbuf classes类型控制实现buffer使用。

●   MS Windows系统,采用Create File Mapping方式

●  OSX系统,采用Memory-mapped Temp File方式

●  Linux/POSIX系统,提供了System V Shared MemoryMemory-mapped Shared Memory两种方式

   具体每种方式的建立步骤这里不再赘述,后面根据代码再简单介绍。

2、 GNURadio buffer的创建流程

GNU Rradio Flowgraph 运行时,每个模块的输出端口都绑定一个循环缓冲区(buffer),通过一个写指针 w_ptr 输出数据,它的下游模块通过一个读指针r_ptr 读取数据。

对于每个blockbuffer如何进行分配,在block运行的设置连接函数setup_connections()里就对它进行了具体的描述,主要是对buffersize以及地址进行设定,具体流程如下图所示:

2 buffer分配流程

3、 代码分析

每个Block通过detail()可以得倒block_detail实例对象指针,而且block的输

出端口都绑定一个循环缓冲区(buffer),其分配起始于下面的代码:

   上面这部分代码是buffer分配的具体实现,主要是对输出端口对应的缓冲区size大小及输出数据类型做判断,确保buffer分配的有效,然后通过make_buffer实现buffer的分配以及设定循环缓冲区的首地址。

Buffer的分配最终是调用VM circular buffer类实现缓存分配并返回基址。

前面提到过,针对不同的操作系统提供了不同的内存分配接口,系统默认的buffer分配配置文件路径是$HOME/.gnuradio/prefs/vmcircbuf_default_factory。通过读取文件获取到(如默认 gr::vmcircbuf_sysv_shm_factory),如果没有默认配置或者配置的不正确,则直接获取工厂列表中的第一个。

同样,根据获取到的factory,然后通过对应的make进行buffer分配。

具体的代码实现参考以下的.h和对应的cc文件(vmcircbuf_createfilemapping.h

vmcircbuf_sysv_shm.hvmcircbuf_mmap_shm_open.hvmcircbuf_mmap_tmpfile.h

1、MS Windows系统的实现

Windows系统采用createfilemapping 方式实现内存的分配及映射,具体代

码的实现逻辑如下:

①  size大小是page size的整数倍,通过CreateFileMapping获取文件页的句柄;

②  通过VirtualAlloc分配2*size大小的内存并返回指针first_tmp

③  通过MapViewOfFileEx分别将文件页映射到分配的虚拟内存的前后两部分,指针分别对应为first_tmpfirst_tmp+size

④  返回内存地址指针(保证分配的内存大小是2*size)。

具体的实现代码见vmcircbuf_createfilemapping::vmcircbuf_createfilemapping

::vmcircbuf_createfilemapping(int size): gr::vmcircbuf(size)函数,

2、OSX系统的实现

苹果系统,查看vmcircbuf_mmap_tmpfile::vmcircbuf_mmap_tmpfile (int size)

: gr::vmcircbuf (size)函数具体描述,这里不再详细介绍。

3、LINUX系统的Mermory-mapped Shared Memory实现

查看vmcircbuf_mmap_shm_open::vmcircbuf_mmap_shm_open(int size)

: gr::vmcircbuf(size)函数具体描述,通过shm_open分配内存,这里不再详细介绍。

4、GNU radio默认的buffer分配采用LINUX系统的另外一种实现方式,

System V Shared Memory共享内存方式,主要由shmgetshmatshmatshmctl四个函数组成实现。代码的逻辑基本上如下描述:

①  获取page size,传入的size大小是page size的整数倍;

②  通过shmget分别创建shmid_guardpage size大小)、shmid1size

小)、shmid22*size大小)共享内存对象;

③  通过shmat将各共享内存区对象映射到调用进程的地址空间,将shmid1

分别映射到shmid2前半部分和后半部分,并且保证shmid2的两部分内存映射到同样的虚拟空间,同时映射shmid_guard到首地址,且为只读模式;

④  返回内存地址指针(保证分配的内存大小是2*size)。

具体的实现代码见文件vmcircbuf_sysv_shm.cc文件的vmcircbuf_sysv_shm::vmcircbuf_sysv_shm(int size): gr::vmcircbuf(size)函数。

到此为止,buffer的分配完成,后面通过block建立block之间的连接,对应每个buffer绑定reader,在block的运行中,通过维护r_ptrw_ptr即可实现buffer的循环使用。

4、 LOG跟踪

       flat_flowgraph.cc文件中,将#define FLAT_FLOWGRAPH_DEBUG 0修改为#define FLAT_FLOWGRAPH_DEBUG 1,即打开日志的使能开关,就可以看到各block buffer分配的简单信息,如果需要详细了解分配的各步骤信息,可以在代码中增加打印信息。

全部回复 (0)

0 / 1000
请遵守社区规范
暂无评论,快来抢沙发吧~
c

cll

社区创作者

帖子信息

所属板块GNU Radio
发布时间2026-07-23 14:47:51
3浏览
0点赞
0评论