FAQ MinieyeDDS
报错 ErrInvalidTopic
[<ThreadId(13)>2021/12/16 19:34:54](ERRO)libdds/src/ddsapi/shmapi.rs(518): ErrInvalidTopic("topicName")
这种错误是因为 topic 不对导致的。检查配置文件中 topic 的名字和程序中使用的 topic 名字是否一样,注意字母拼写。
报错 ErrBiggerSize
[<ThreadId(5)>2021/12/16 19:38:04](ERRO)libdds/src/ddsapi/shmapi.rs(276): ErrBiggerSize
这种情况的出现,是因为先创建了一个小的共享内存,然后又增大了配置文件里面共享内存的大小。 因为程序退出之后,并没有自动将之前小的那个共享内存删除,又想要再次创建一个更大的同名的共享内存, 所以报错。
解决方法:
重启设备。
报错 Address already in use
[<ThreadId(1)>2025/02/11 20:12:36](ERRO)src/ddsapi/shmapi.rs(314): ErrAnyHow(nn_bind failed
Caused by:
Address already in use)
这种情况的出现,是因为当前环境中已经存在了某个 topic,如果此时实例化该 topic,就会抛出该错误。
解决方式:
ls -al /dev/shm/
该指令可以看到当前环境中已经实例化的 topic,找到冲突的 topic 并且关闭对应的进程即可。
报错 Too big data
thread '<unnamed>' panicked at src/ads/shm_nn_queue/queue.rs:322:9:
Invalid parameter: Too big data. Input: 2412, Node Max Size: 2000.
如报错信息提示,是因为你写入的某条数据超过了 DDS 环上元素的大小,所以会抛出该错误。
解决方式:
修改 DDS 配置,并且重启设备,或者对您发出来的数据进行分包,确保每个包都小于等于 NodeMaxSize
如何删除共享内存?
现象:
程序退出了之后,共享内存还在,如何删除?
原因:
Posix 类型和 System V 类型的共享内存,生命周期是和操作系统一样的,和进程无关。 进程退出了,共享内存自然还存在着。
但是如果是在 Android 系统上。共享内存的生命周期是和进程一样的,进程退出了, 共享内存的生命周期就结束了。
解决方法:
方法1 [建议]
因为 Posix 类型和 System V 类型的共享内存生命周期和操作系统绑定,因此可以重启系统自动释放共享内存。
方法2 [不建议]
如果你熟悉共享内存的使用方法及其机制,可以调用 dds_common.h
中的 unlink
方法。
int rshm_unlink_posix(const char *key);
int rshm_unlink_multi_posix(const char *key, size_t num)
int rshm_unlink_svpic(const char *key);
int rshm_unlink_multi_svpic(const char *key, size_t num);
大部分时候,应该是使用 rshm_unlink_multi_posix 这个函数,第二个参数默认是 2。
方法3 [非常危险]
如果你确定已经没有线程在使用 DDS,可以移除操作系统挂载的所有共享内存
该方法非常危险,禁止🚫在生产环境中使用
rm -rf /dev/shm/dds:shm:*
调用 unlink 之后,为什么共享内存仍然可以访问?
现象:
程序 A、程序 B、程序 C 同时连接着共享内存 M。这个时候,程序 A 调用 unlink
方法把共享内存 M 删除了,但是程序 B 和程序 C 却仍然可以访问共享内存 M。
原因:
这是因为 unlink
方法只是将共享内存的引用计数减一,只有引用计数减为 0 了, 共享内存才会真正被删除。但是调用 unlink
之后,其他程序便不能再连接到 该共享内存上了。这也是为什么这个函数的名字叫 unlink
而不是 remove
的原因。
如果程序 Crash 了,对共享内存是否有影响?
如果共享内存内部使用了,锁、信号量之类的同步原语, 程序 Crash 了会造成状态被破坏,暂时不知道如何解决。
生产者生产的前几个数据会漏掉
现象:
消费者先启动,然后再启动生产者,会漏掉生产者最开始生产的几个数据。
原因:
因为消费者先启动之后,无法连接到生产者,会每隔一秒尝试一次重连。 在重连的间隔中生产者启动了,生产的数据就没法通知到消费者。
但是一般情况下,这些数据都还是在共享内存中的,只是消费者收不到 nanomsg 的通知了。
解决方法:
使用 DDS Reader 的主动 Read 接口,从共享内存中读取相应的数据
/*
@brief: Read data from topic, array[index].
@param: index[in]: index of array [0 ~ node_num).
@param: buf[out]: Buffer used to store received data.
@param: len[in|out]: Input is length of buf, Output is data length.
@param: id[out]: (optional) unique id.
@return On success: 0
On error: error code is returned.
*/
int Read(size_t index, void *buf, size_t *len, size_t *id = nullptr);
并行实例化多个 Ctx 为什么会崩溃
现象:
并行启动 N 个线程,每个线程启动时都初始化自己的独立的 DDS Ctx
原因:
DDS 的 Ctx 是线程不安全的,禁止并行初始化 Ctx,可能导致偶发性的崩溃问题
解决方法
- 方法一:使用锁控制,禁止多个 Ctx 在同一时刻初始化
- 方法二:使用单个 Ctx,将 Ctx 指针传入到每个线程