Virtual time,多进程共享虚拟时间原型验证
周末抽空想了想数据回放的时间戳问题,想到了一个比较有意思的方案,就是使用虚拟时间。所以就尝试采用多进程共享虚拟时间的方式来劫持系统时间戳,尝试满足数据回放过程中的功能代码对系统时间戳需求。
- 一般而言,像ROS或者DDS的消息数据都是带有时间戳的,比如录制时间戳,消息内部header中保存的数据源时间戳或者数据对应的有效时刻的时间戳等等
- 对于实际生产环境中的功能逻辑代码,可能会依赖于系统时间戳来进行一些逻辑判断,比如超时判断,定时器;又或者对不同来源(不同topic、不同帧率)的时间戳的消息进行时间戳对齐或者插值等等,这些都是对时间戳的依赖。而如果软件没有对获取时间戳的接口进行封装,那么在采用类似于Pub/Sub的方式对数据回放的时候,就会出现问题,因为数据回放的时间戳是不可控的,可能会导致功能逻辑的错误。
- 对于单进程的数据回放程序,可以使用消息录制时的时间戳来作为虚拟的仿真系统时间戳,这样的话,原有的代码逻辑就可以直接使用这个时间戳来进行仿真
- 对于多进程节点,数据通过类似于DDS Pub/Sub的方式进行传输,那么就需要对时间戳进行额外的处理;对系统时间戳进行劫持,然后通过共享内存的方式来共享虚拟时间戳是一个看上去能走通的方案(当然,未必是最优的)
实现的思路非常简单,那就是可以根据消息对应的录制时间戳和消息内部的时间戳(其实一般前者应该就够了),来更新虚拟的时间戳,并将这个虚拟时间戳通过共享内存的方式共享给其他进程。这样的话,其他进程就可以通过读取共享内存的方式来获取虚拟时间戳。
该虚拟时间戳,可以通过劫持libc
中的gettimeofday
、clock_gettime
等函数来实现,这样的话,就可以在不修改原有代码的情况下,来实现对系统时间戳的劫持;这可以通过将动态库指定到LD_PRELOAD
的方式来实现。
具体原型代码实现可见 Virtual timestamp。该实现仅为虚拟时间戳多进程更新和共享的原型验证,实际应用中还需要考虑更多的问题,比如定时器回调的处理,进程异常退出后共享内存的释放等等。