Linux 환경에서 CAN 통신을 구현하기 위한 방법은 여러가지가 있을 수 있겠지만,
가장 일반적으로 사용할 수 있는 방법은 Socket CAN 일 것이다.
Socket CAN 은 리눅스 커널에서 기본적으로 제공하는 CAN 통신 드라이버이기 때문에
별도의 드라이버 또는 API가 필요하지 않을 뿐더러,
대부분의 CAN 통신 장치들을 이 Socket CAN 방식으로 사용할 수 있기 때문이라고 생각한다.
이 Socket CAN을 일반 PC(노트북, 미니 PC, NUC등)에서 사용하기 위해서는 USB to CAN 등의 별도 장치가 필요하다.
예를 들면 Pcan usb, CANable 등이다.


이런 장치들은 각자 방법들은 조금씩 다르지만
결국 Socket CAN 인터페이스를 생성해주고(can0, can1 등등)
이 소켓 CAN 인터페이스가 생성되었다면
그 이후에 이 소켓을 이용해서 CAN 통신을 하는 코드적인 구현은 모두 동일하다.
그래서 만약에 내가 사용하는 장치가 PCAN usb 든, CANable이든 간에
Socket CAN 인터페이스를 생성할 수 있다는 것을 확인한 이후에는
생성된 인터페이스를 이용해서 통신하는 코드를 작성하는 단계만 남게 되는 것인데,
이 소켓 CAN 코드를 구현하면서 중간중간 작동을 테스트 해보려면,
소켓 CAN 인터페이스가 있어야 코드가 돌아가기 때문에, CAN 통신 장치를 가지고 있어야 한다.
그런데 코딩이라는 게,
정해진 근무 자리에서 할 수도 있지만, 집에서 할 수도 있고, 카페에 가서 할 수도 있는데
그럴 때마다 이 CAN 통신 장치를 들고 다니면서 CAN 통신 코드를 테스트 해보는 것은 꽤나 번거로운 일이 될 것이다.
또는 CAN 통신 장치는 1개인데, 여러명이서 함께 코드를 작성하고 있는 상황이라던지,
아니면 아예 CAN 통신 장치가 없는 상태에서 코드를 짜야 한다던지 할 때는 꽤나 애매한 상황이 되는 것이다.
그래서 CAN 통신 장치를 들고 다니지 않더라도 Socket CAN 통신 코드를 짤 수 있는 방법에 대해서 알아보고자 한다.
Linux에서는 Virtual CAN 이라는, 가상의 Socket CAN 인터페이스를 생성할 수 있다.
1. vcan0 라는 이름의 가상 CAN 인터페이스를 생성하기
sudo ip link add dev vcan0 type vcan
2. 가상 인터페이스 생성 확인하기.
2.1 ifconfig 명령으로 먼저 확인해보면
ifconfig
-> vcan0 인터페이스가 나타나지 않을 것이다.
2.2 ifconfig -a 명령을 쳐보면
ifconfig -a
-> vcan0 인터페이스를 확인할 수 있을 것이다.
이렇게 나오는 이유는 vcan0 인터페이스가 생성은 되었으나, 아직 활성화가 되지 않은 상태이기 때문이다.
2.3 다음 명령으로 vcan0 인터페이스를 활성화시켜주자.
sudo ifconfig vcan0 up
2.4 다시 ifconfig 명령으로 인터페이스가 나타나는지 확인해보자.
ifconfig
vcan0 인터페이스가 활성화되어서 나타난 것을 확인할 수 있을 것이다.
이 vcan0 인터페이스를 이용해 Socket CAN 통신을 주고 받는 코드를 테스트 해 볼 수 있을 것이다.
가상 Socket CAN 인터페이스가 정말 실제 인터페이스와 동일하게 작동되는지 확인해보자.
Socket CAN 통신을 이용해 간단하게 CAN 통신을 날리거나, 값을 확인할 수 있는 CAN utils 를 이용하면 간단히 확인할 수 있다.
CAN utils를 설치한 적이 없다면 먼저 설치부터 해주자.
1. CAN-utils 설치
sudo apt-get install can-utils
2. CAN send 명령으로 CAN 통신 보내보기.
vcan0 인터페이스를 통해서, ID는 999, 데이터는 DEADBEEF 로 구성된 CAN 패킷을 보내는 명령
(이때 DEADBEEF의 각 글자는 16진수 DE, AD, BE, EF 를 가지고 일종의 말장난 식의 데이터를 만들어놓은것)
cansend vcan0 999#DEADBEEF
-> 명령을 입력했을 때 아무 일도 일어나지 않는다면 정상 동작된 것이다. vcan0라는 인터페이스가 존재하기에 아무런 에러가 발생하지 않은 것이다.
3. CAN dump 명령으로 vcan0 인터페이스의 트래픽 확인해보기.
CAN dump 명령은 특정 인터페이스에서 보내거나, 수신하는 통신 트래픽을 나타내주는 명령이다.
즉 vcan0 인터페이스에서 CAN 통신을 보내는 것이나, 외부에서 보낸 CAN 통신이 vcan0로 들어오는 것을 확인할 수 있는 것이다.
새 터미널 창을 하나 열고, vcan0로 들어오고 나가는 트래픽을 확인하는 명령을 다음과 같이 실행해보자.
candump vcan0
그리고 다른 터미널에서 아까와 같이 cansend 명령을 보내보자.
그러면 다음과 같이 candump를 실행한 터미널에서, vcan0에서 send한 CAN 통신을 확인할 수 있다.

이로써, 가상 인터페이스인 vcan0를 실제 Socket CAN 인터페이스처럼 동일하게 사용할 수 있다는 것을 확인하였다.
그런데 위와 같이 vcan0 인터페이스를 하나 만들어주면, 해당 인터페이스로 CAN 통신을 보내는 코드는 테스트 해 볼 수 있지만,
CAN 통신을 받는 코드는 테스트 해 볼 수 없을 것이다. 실제 Socket CAN 인터페이스라면 제 2의 외부 CAN 장치에서 CAN 통신을 수신하겠지만, vcan0 인터페이스는 가상이다 보니, 외부에서 해당 인터페이스로 보내주는 것이 없는 것이다.
그렇기 때문에, 가상 Socket CAN으로 통신을 보내는 것 뿐만 아니라 받는 것도 테스트 하기 위해서,
가상 CAN 인터페이스를 2개를 생성해 주면, 두 인터페이스가 서로 통신을 주고 받게 해서 테스트 할 수 있지 않을까?
앞서 vcan0 인터페이스를 생성했으니, vcan1 인터페이스를 추가로 생성해주자.
1. vcan1 인터페이스 생성.
sudo ip link add dev vcan1 type vcan
2. vcan1 인터페이스 활성화
sudo ifconfig vcan1 up
3. vcan1 인터페이스 생성 확인
ifconfig
-> 앞서 생성했던 vcan0 뿐만 아니라, vcan1 이 새롭게 생성 된 것을 확인할 수 있다.
이로써, 두개의 가상 Socket CAN 인터페이스 vcan0와 vcan1을 생성해주었다.
그럼 vcan0 인터페이스에서 뭔가를 보내면, vcan1로 데이터가 들어올까? 그렇지 않을 것이다.
왜냐하면 앞서 한 것은 가상의 CAN 장치 2개를 그저 존재하게 해 준 것에 불과하기 때문이다.
마치 CANable(USB to CAN 장치) 2개가 그냥 따로 따로 있는 것과 다를바 없다.
실제 CAN 장치들도 꼬인 2선으로 연결해 주어야 하는 것처럼, 가상의 인터페이스들도 서로 연결해주는 작업이 필요하다.
다음 명령으로 vcan0와 vcan1을 서로 연결해주자.
sudo modprobe can-gw
sudo cangw -A -s vcan0 -d vcan1 -e
sudo cangw -A -s vcan1 -d vcan0 -e
두번째 줄 명령은 vcan0 -> vcan1로 향하는 연결을 의미하고, 세번째 줄 명령은 vcan1 -> vcan0 연결을 의미한다.
따라서 쌍방 연결이 구성된것이다.
이제 vcan0에서 뭔가 보내면, 연결된 vcan1로 데이터가 들어올 것이다.
실제로 그렇게 될지 한번 확인해보자.
터미널을 3개 열어주고, 그중 2개는 vcan0의 candump와 vcan1의 candump를 다음과 깉이 실행해놓자.

그리고 나머지 한 터미널에서 다음 명령으로 vcan0 인터페이스에서 통신을 전송해보자.
cansend vcan0 999#DEADBEEF
다음 사진과 같은 결과를 확인할 수 있다.
왼쪽 터미널에서 vcan0 인터페이스를 통해 데이터를 보냈고,
가운데 터미널에서는 vcan0의 트래픽(보낸 트래픽)
오른쪽 터미널에서는 vcan1의 트래픽(받은 트래픽)이 나타난다.

즉 vcan0로 CAN 통신을 보냈을 때, vcan1에서 수신이 되는 것을 확인하였다.
이것으로 가상의 Socket CAN 테스트 환경을 구성 완료하였다.
이 가상의 인터페이스를 사용해서, 실제 CAN 통신 장치가 없는 상황에서도 CAN 통신 코드 개발을 할 수 있을 것이다.
참고 링크:
https://www.beyondlogic.org/example-c-socketcan-code/
Example C SocketCAN Code – Beyondlogic
Writing user space C code to talk to CAN devices via the Linux SocketCAN interface is relatively simple and efficient. SocketCAN uses the Berkeley socket API and hence is very similar to communicating with other network socket devices. Below is a simple gu
www.beyondlogic.org
https://stackoverflow.com/questions/54296852/how-to-connect-two-vcan-ports-in-linux
How to connect two VCAN ports in Linux?
I have set up two vcan devices and I want to treat them as if they were connected together. I want to be able to use can-utils candump to listen on one line, and send can messages from the other. H...
stackoverflow.com