套接字如何获取发送失败状态? [英] How socketcan get send failure status?

查看:142
本文介绍了套接字如何获取发送失败状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As we all know, in the CAN bus communication protocol, sender know whether the data was successfully sent. I send socketcan data as follows.

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

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

However, even if the CAN communication cable is disconnected, the return value of ret is still 16(=sizeof (struct can_frame)).I queried the information and found that the problem was due to the tx_queue of the network stack used by socketcan. When write is called multiple times, the buffer is full and the return value of ret is -1. But this is not the behavior I expect, I hope that every frame of data sent will immediately get the status of success or failure. By

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

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

I want to cancel the tx_queue, but it does not work. What I want to ask is, is there a way to cancel the tx_queue of socketcan, or to get the status of the each sending frame about controller through the API (such as libsocketcan). Thanks.

推荐答案

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

You cannot use write() itself to discover whether a CAN frame was successfully put on the bus, because all it does is write the frame to the in-kernel socket buffer. The kernel then moves the frame to the transmit queue of the SocketCAN network interface, followed by the driver moving it to the transmit buffer of the CAN controller, which finally puts the frame on the bus. What you want is a direct write which bypasses all those buffers, but that's not possible with SocketCAN, even if you set the transmit queue length to 0.

但是,还有另一种获取确认的方法.如果启用 CAN_RAW_RECV_OWN_MSGS 套接字选项(请参见

However, there is another way to get confirmation. If you enable the CAN_RAW_RECV_OWN_MSGS socket option (see section 4.1.4 and 4.1.7 in the SocketCAN documentation), you will receive frames that were successfully sent. You'll need to use recvmsg() so you get the message flags. msg_flags will have the MSG_CONFIRM bit set for a frames that was successfully sent by the same socket on which it is received. You won't be informed of failures, but you can detect them by using a timeout for the confirmation.

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

It's not an ideal solution because it mixes the read and write logic in your application. One way to avoid this would be to use two sockets. One for writing and reading MSG_CONFIRM frames, the other for reading all other frames. You could then create a (blocking) write function that does a write() followed by multiple calls to recvmsg() with an appropriate timeout.

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

Finally, it is useful to enable error frames (through the CAN_RAW_ERR_FILTER socket option). If you send a frame on a socket with a disconnected cable, this will typically result in a bus off state, which will be reported in an error frame.

这篇关于套接字如何获取发送失败状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆