Skip to content

FAQ MinieyeDDS

报错 ErrInvalidTopic

sh
[<ThreadId(13)>2021/12/16 19:34:54](ERRO)libdds/src/ddsapi/shmapi.rs(518): ErrInvalidTopic("topicName")

这种错误是因为 topic 不对导致的。检查配置文件中 topic 的名字和程序中使用的 topic 名字是否一样,注意字母拼写。

报错 ErrBiggerSize

sh
[<ThreadId(5)>2021/12/16 19:38:04](ERRO)libdds/src/ddsapi/shmapi.rs(276): ErrBiggerSize

这种情况的出现,是因为先创建了一个小的共享内存,然后又增大了配置文件里面共享内存的大小。 因为程序退出之后,并没有自动将之前小的那个共享内存删除,又想要再次创建一个更大的同名的共享内存, 所以报错。

解决方法:

重启设备。

报错 Address already in use

sh
[<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,就会抛出该错误。

解决方式:

sh
ls -al /dev/shm/

该指令可以看到当前环境中已经实例化的 topic,找到冲突的 topic 并且关闭对应的进程即可。

报错 Too big data

sh
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 方法。

cpp
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,可以移除操作系统挂载的所有共享内存

该方法非常危险,禁止🚫在生产环境中使用

sh
rm -rf /dev/shm/dds:shm:*

现象:

程序 A、程序 B、程序 C 同时连接着共享内存 M。这个时候,程序 A 调用 unlink 方法把共享内存 M 删除了,但是程序 B 和程序 C 却仍然可以访问共享内存 M。

原因:

这是因为 unlink 方法只是将共享内存的引用计数减一,只有引用计数减为 0 了, 共享内存才会真正被删除。但是调用 unlink 之后,其他程序便不能再连接到 该共享内存上了。这也是为什么这个函数的名字叫 unlink 而不是 remove 的原因。

如果程序 Crash 了,对共享内存是否有影响?

如果共享内存内部使用了,锁、信号量之类的同步原语, 程序 Crash 了会造成状态被破坏,暂时不知道如何解决。

生产者生产的前几个数据会漏掉

现象:

消费者先启动,然后再启动生产者,会漏掉生产者最开始生产的几个数据。

原因:

因为消费者先启动之后,无法连接到生产者,会每隔一秒尝试一次重连。 在重连的间隔中生产者启动了,生产的数据就没法通知到消费者。

但是一般情况下,这些数据都还是在共享内存中的,只是消费者收不到 nanomsg 的通知了。

解决方法:

使用 DDS Reader 的主动 Read 接口,从共享内存中读取相应的数据

cpp
/*
    @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 指针传入到每个线程

智能汽车赋能者