我正在寫一個程序,不斷髮出「你好」到CAN總線和通過SocketCAN總線讀取數據。我希望這兩個步驟是獨立的。這意味着即使公交車上沒有數據,程序仍會發送「Hello」。但是通常的CAN讀取是不可能的,因爲這個函數會停止程序運行並等待數據。SocketCAN連續讀取和寫入
有沒有辦法如何使它非阻塞或等待數據只有幾毫秒?
我正在寫一個程序,不斷髮出「你好」到CAN總線和通過SocketCAN總線讀取數據。我希望這兩個步驟是獨立的。這意味着即使公交車上沒有數據,程序仍會發送「Hello」。但是通常的CAN讀取是不可能的,因爲這個函數會停止程序運行並等待數據。SocketCAN連續讀取和寫入
有沒有辦法如何使它非阻塞或等待數據只有幾毫秒?
您可以使用下面的星座(這是不完整的解決方案,而只是算法):
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瞭解更多信息,以及如何處理返回值。
另一種方式,我發現 - 線程。只需使線程中的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;
}
順便說一句,您可以使用'setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv))'其中'tv'是一個'timeval'來設置讀取超時時間,如果超時過期,'read'將會失敗並返回'EAGAIN',您也可以使用['CAN_RAW_FILTER'](https://www.kernel.org/ doc/Documentation/networking/can.txt)來減少處理開銷並僅過濾感興趣的幀。 –
謹慎使用此解決方案:
void *thread(int cansock) {
struct can_frame rxmsg;
while (1) {
read(cansock, &rxmsg, sizeof(rxmsg));
printf("message received\n");
}
}
,因爲如果閱讀()開始無阻擋返回一個錯誤,這是在現場和有沒有人看看printf()的結果,你將進入一個繁忙的循環。
這可能會損壞d作爲對另一個答案的評論更好;而不是本身的答案。我知道你還不能發表評論 - 請參閱[這篇文章](http://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i -do-instead/214174#214174)瞭解你可以在此期間做什麼的一些細節。 –
您不必使用'select'爲SocketCAN(雖然這不是一個問題,如果你這樣做的話);你也可以使用'setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv))',其中'tv'是接收超時的'timeval'。然後,如果超時到期,'read'將會失敗並返回'EAGAIN'。 –
@Jason C:我喜歡你的建議,但它並沒有爲我工作:我試圖如上,並與「setsockopt的(SKT,SOL_CAN_RAW,SO_RCVTIMEO,......」因爲這似乎更容易,但在這兩種情況下, 「讀」呼叫永遠阻塞,直到幀到達(無超時) – Jeremy
哎呀,我的錯......從「窩」在Linux手冊:「如果超時設置爲零(默認值),則操作永遠不會超時。「如果沒有幀要讀取,我正在使用超時0來希望立即返回。 – Jeremy