我正在编写一个程序,它不断地向 CAN 总线发送“Hello”并通过 SocketCAN 从总线读取数据。我希望这两个步骤是独立的。这意味着即使总线上没有数据,程序仍然会发送“Hello”。但是用通常的 CAN 读取是不可能的,因为这个函数会停止程序运行并等待数据。
有没有办法让它非阻塞或只等待几毫秒的数据?
我正在编写一个程序,它不断地向 CAN 总线发送“Hello”并通过 SocketCAN 从总线读取数据。我希望这两个步骤是独立的。这意味着即使总线上没有数据,程序仍然会发送“Hello”。但是用通常的 CAN 读取是不可能的,因为这个函数会停止程序运行并等待数据。
有没有办法让它非阻塞或只等待几毫秒的数据?
我发现的另一种方式 - 线程。只需使 CAN 读取工作在线程中,它不会停止主循环。对于 Linux 系统,它看起来像这样:
#include <pthread.h>
void *thread(int cansock) {
struct can_frame rxmsg;
while (1) {
read(cansock, &rxmsg, sizeof(rxmsg));
printf("message received\n");
}
}
int main(){
// initialize CAN socket and message to send
pthread_t pth;
pthread_create(&pth, NULL, thread, cansock);
while(1){
write(cansock, &txmsg, sizeof(txmsg));
printf("message sent\n");
}
return 0;
}
您可以使用以下星座(这不是完整的解决方案,而只是算法):
while(1) {
FD_ZERO(&rdfs);
FD_SET(s, &rdfs);
tv.tv_sec = 0;
tv.tv_usec = 10000; // microseconds
rc = select(s + 1, &rdfs, NULL, NULL, &tv);
// rc == 0 - timeout
if (!rc) {
// write your CAN frame
}
if (FD_ISSET(s, &rdfs)) {
// read CAN frames
}
}
有关更多信息以及如何处理返回值,请参见man select 。
小心这个解决方案:
void *thread(int cansock) {
struct can_frame rxmsg;
while (1) {
read(cansock, &rxmsg, sizeof(rxmsg));
printf("message received\n");
}
}
因为如果 read() 开始返回一个没有阻塞的错误,并且这是在现场并且没有人查看 printf() 的结果,那么你将进入一个繁忙的循环。
我通过在初始化时添加以下代码来解决它
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
setsockopt(skt_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
read
并在另一个线程中添加循环。