我正在编写一个CAN记录器程序。我记录数据的方式类似于调用candump
之类的candump
时candump any
-tool的处理方式:
https://github.com/linux-can/can-utils/blob/master/candump.ccandump any
使candump
绑定(bind)到任何设备,即addr.can_ifindex = 0;
,然后使用recvmsg
获取CAN帧,然后获取struct msghdr msg;
附加时间戳记上的时间戳,以将其写入日志文件或屏幕上。
我的问题是,内核是否确保以下assert
始终有效?
struct msghdr msg;
// init stuff
// ...
s[0] = _skt_1; // can0
s[1] = _skt_2; // can1
// configure and bind sockets
// ...
select(s[1]+1, &rdfs, NULL, NULL, NULL));
recvmsg(s[0], &msg, 0); // https://linux.die.net/man/2/recvmsg
timestamp_1 = getTimestamp(msg);
recvmsg(s[1], &msg, 0); // https://linux.die.net/man/2/recvmsg
timestamp_2 = getTimestamp(msg);
// Always valid?
assert(timestamp_1 < timestamp_2);
提示SocketCAN驱动程序中的源代码位置也将有所帮助。 最佳答案
简短的答案是肯定的,除非您的司机做的事情很奇怪。 CAN使用与其他网络设备相同的netif子系统。 SKB有几种获取时间戳的方法。
硬件时间戳:
如果您的驱动程序使用硬件时间戳,则时间戳基于硬件提供的内容。
软件时间戳记:
如果启用了netdev_tstamp_prequeue,则驱动程序将skb提交到netif_receive_skb后很快就会有一个时间戳记
https://elixir.bootlin.com/linux/v4.14.202/source/net/core/dev.c#L4554
如果未启用netdev_tstamp_prequeue,则在经过更多处理后仍会应用时间戳,但仍在同一NAPI接收线程中。
https://elixir.bootlin.com/linux/v4.14.202/source/net/core/dev.c#L4352
这是模糊部分:
有一些特殊的模式(RSP/RFP),这些模式允许内核使用SMP负载均衡skb处理。内核没有在napi接收线程中处理skb,而是将skb放入每个cpu队列中。现在,如果未启用netdev_tstamp_prequeue,则时间戳会在一段时间后脱离每个CPU队列时添加。但是,文档说接收顺序未修改,因此时间戳也应保持顺序。