【问题标题】:How socketcan get send failure status?套接字如何获得发送失败状态?
【发布时间】:2020-03-18 09:48:58
【问题描述】:

众所周知,在CAN总线通信协议中,发送方知道数据是否发送成功。我发送socketcan数据如下。

ret = write (socket, frame, sizeof (struct can_frame));

但是,即使CAN通讯线断开,ret的返回值仍然是16(=sizeof(struct can_frame))。查询资料,发现问题是由于使用的网络栈的tx_queue通过 socketcan。多次调用write时,缓冲区已满,ret的返回值为-1。 但这不是我所期望的行为,我希望发送的每一帧数据都会立即获得成功或失败的状态。 由

echo 0> / sys / class / net / can0 / tx_queue_len

我想取消 tx_queue,但它不起作用。 我想问的是,有没有办法取消socketcan的tx_queue,或者通过API(如libsocketcan)获取关于控制器的每个发送帧的状态。 谢谢。

【问题讨论】:

  • “电缆已断开”是什么意思?总线上是否有接收节点?如果没有接收节点,则无法进行 CAN 通信。总线依赖于至少一个其他节点来确认每个发送的帧。
  • @Lundin "cable is disconnected" 表示总线上没有其他节点。当然,socketcan 会发送帧失败。我期望的行为是获取数据帧发送失败的状态,但我不知道如何获取状态。

标签: linux-device-driver embedded-linux can-bus zynq socketcan


【解决方案1】:

您不能使用write() 本身来发现 CAN 帧是否已成功放在总线上,因为它所做的只是将帧写入内核套接字缓冲区。然后内核将帧移动到 SocketCAN 网络接口的传输队列,然后驱动程序将其移动到 CAN 控制器的传输缓冲区,最终将帧放到总线上。您想要的是绕过所有这些缓冲区的直接写入,但使用 SocketCAN 是不可能的,即使您将传输队列长度设置为 0。

但是,还有另一种方法可以得到确认。如果启用CAN_RAW_RECV_OWN_MSGS 套接字选项(参见SocketCAN documentation 中的4.1.4 和4.1.7 节),您将收到已成功发送的帧。您需要使用 recvmsg() 以便获得消息标志。 msg_flags 将设置MSG_CONFIRM 位,用于由接收它的同一个套接字成功发送的帧。您不会被告知失败,但您可以通过使用超时进行确认来检测它们。

这不是一个理想的解决方案,因为它在您的应用程序中混合了读写逻辑。避免这种情况的一种方法是使用两个套接字。一个用于写入和读取MSG_CONFIRM 帧,另一个用于读取所有其他帧。然后,您可以创建一个(阻塞)写入函数,该函数执行 write(),然后以适当的超时时间多次调用 recvmsg()

最后,启用错误帧很有用(通过CAN_RAW_ERR_FILTER 套接字选项)。如果您在电缆断开的情况下在套接字上发送帧,这通常会导致总线关闭状态,这将在错误帧中报告。

【讨论】:

    猜你喜欢
    • 2012-09-14
    • 1970-01-01
    • 2022-11-01
    • 2013-12-21
    • 2014-04-15
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多