繁体   English   中英

Linux recvmsg 的 SocketCAN 行为

[英]Linux SocketCAN behaviour of recvmsg

我正在编写一个 CAN 记录器程序。 我记录数据的方式与调用candump类的candump candump any时 candump 工具的方式类似: https://github.com/linux-can/can-utils/blob/master/candump.c

candump any使candump绑定到任何设备,即addr.can_ifindex = 0; 然后它使用recvmsg获取 CAN 帧,然后获取struct msghdr msg; 附加时间戳将其写入日志文件或屏幕上。

我的问题是,kernel 是否确保以下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 ) 允许 kernel 使用 SMP 对 skb 处理进行负载平衡。 kernel 不是在 napi 接收线程中处理 skb,而是将 skb 放入每个 cpu 队列中。 现在,如果netdev_tstamp_prequeue未启用,则时间戳会在一段时间后从 per cpu 队列中退出时添加。 但是,文档说接收顺序没有修改,因此时间戳也应该保持顺序。

我想在@user14508498 的答案中添加一些内容。

我终于做了一些测量。 如果我将中断固定到不同的 CPU(例如 CAN0 到 CPU0 和 CAN1 到 CPU1), candump确实会以非时间顺序接收一些 CAN 帧,即上述断言在这种特定情况下并不总是正确的。 至少在我的系统上的数量级约为 1-2 微秒。 当两个中断都固定在同一个处理器上时,我无法观察到相同的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM