在测试FastDDS的HelloWorldExample时发现,在同一台设备中运行订阅端和发布端的时候,通过tcpdump抓包,无法抓到两者之间业务数据的通信,只能抓取到PDP和EDP数据。
然后,在不同设备中分别运行订阅端和发布端然后用tcpdump抓包,就可以抓取到正常topic上的业务数据通信,因此怀疑是在同一个主机内的时候,发布端和订阅端是通过SharedMemory的方式进行通信的。
为了验证同一个主机内,FastDDS的发布端和订阅端是否通过SharedMemory通信的,因此通过gdb加在dds订阅端程序,在SubListener::on_data_available上添加断点,然后启动发布端程序,触发断点,打印调用堆栈。
hread 9 "DDSHelloWorldEx" hit Breakpoint 2, 0x0000555555587736 in HelloWorldSubscriber::SubListener::on_data_available(eprosima::fastdds::dds::DataReader*) ()
(gdb) bt
#0 0x0000555555587736 in HelloWorldSubscriber::SubListener::on_data_available(eprosima::fastdds::dds::DataReader*) ()
#1 0x00007ffff767160b in eprosima::fastdds::dds::DataReaderImpl::InnerDataReaderListener::on_data_available (this=0x5555556d7128, writer_guid=..., first_sequence=..., last_sequence=...,
should_notify_individual_changes=@0x7fffee7fad9e: false)
at /home/nio/code/new_code/starcruiser/starcruiser-la/lagvm/LINUX/android/vendor/nio/3rdparty/fydds/third-party/src/Fast-DDS-2.10.1/Fast-DDS/src/cpp/fastdds/subscriber/DataReaderImpl.cpp:903
......
#23 0x00007ffff7a920e4 in std::thread::_Invoker<std::tuple<void (eprosima::fastdds::rtps::SharedMemChannelResource::*)(eprosima::fastrtps::rtps::Locator_t), eprosima::fastdds::rtps::SharedMemChannelResource*, eprosima::fastrtps::rtps::Locator_t> >::operator() (this=0x555555654508) at /usr/include/c++/11/bits/std_thread.h:266
可以看到在同一台主机上的发布端和订阅端,订阅端的数据是通过SharedMemory的方式获取到的。
FastDDS中,每种传输类型的ChannelResource都是由该传输类型的TransportInterface来创建的,因此推断应该存在SharedMemoryTransportInterface类。查找代码后发现存在SharedMemTransportDescriptor这么一个TransportDescriptor,并且该TransportDescriptor会被注册给NetworkFactory,而NetworkFactory创建Sender/ReceiverResource的时候会在所以已经注册的TransportDescriptor上面创建具体的传输类型的ChannelResource。
因此,只要不向NetworkFactory注册SharedMemTransportDescriptor,就不存在SharedMem的传输类型的ChannelResource。
注册的动作发生在RTPSParticipantImpl的构造函数中,依赖SHM_TRANSPORT_BUILTIN宏来判断是否需要注册,关闭该宏既可,该宏的值在CMakeLists.txt中有定义默认值,可以将默认值改为OFF。