.png)
저는 현재 일부 센서/모터 제어 기능을 실행하는 임베디드 Linux 시스템이 있는 프로젝트를 진행하고 있으며 사용자가 시스템을 제어할 수 있는 GUI 응용 프로그램을 만들고 있습니다. 미래에는 단일 시스템에서 두 응용 프로그램을 모두 실행할 수 있지만 당분간은 이를 기존 시스템에 대한 업그레이드로 설치할 수 있기를 원하며 기존 컨트롤러 보드에는 GUI를 다음과 같이 실행할 수 있는 기능이 없습니다. 설계되었으므로 별도의 SBC에서 실행될 것입니다(현재 우리는오드로이드 C4Android 9 실행 중)
우리는 두 시스템 간의 통신 API를 연구했으며 고정 IP 주소를 사용하여 두 시스템 간에 직접 이더넷 연결을 실행하여 초기 테스트를 수행해 왔습니다. 그러나 배포 요구 사항과 Android의 제한으로 인해 다른 방법을 알아내야 합니다. 실제 제품 배포를 위한 연결 방법입니다. 고객이 WiFi 또는 이더넷을 통해 GUI 시스템에서 인터넷에 연결할 수 있어야 하므로 ODroid의 온보드 이더넷 포트는 해당 목적으로 사용할 수 없으며, 게다가 Android 커널에는 몇 가지 내부 동작이 있습니다. 이는 주어진 시간에 단일 네트워크 연결만 활성화되도록 허용합니다.
Android 네트워크 우선순위 규칙의 예외는 USB 네트워크 인터페이스입니다. Linux 컨트롤러 시스템과 Android 장치 자체에는 원격 호스트에 대한 네트워크 인터페이스로 표시되는 기능이 있습니다. 컨트롤러 시스템에는 사용 가능한 USB 가젯 포트가 있고 g_ether
시스템 이미지에서 커널 모듈을 활성화했습니다. GUI 시스템에는 USB OTG 포트가 있으며 Android 시스템 설정에서 USB 테더링을 활성화할 수 있습니다.
저는 이들 시스템 중 하나와 해당 인터페이스를 사용하여 Windows 개발 시스템 간에 통신할 수 있었지만 지금까지 두 솔루션 중 다른 솔루션과 통신하는 방법을 찾지 못했습니다.
원격 인터페이스로서의 Linux 시스템(g_ether 드라이버가 포함된 USB 가젯)
- Linux 시스템에 g_ether 커널 모듈을 로드하면
usb0
인터페이스가 생성됩니다.
# modprobe g_ether
# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.42.128.107 netmask 255.255.255.0 broadcast 10.42.128.255
inet6 fe80::206:cff:fe01:1027 prefixlen 64 scopeid 0x20<link>
ether 00:06:0c:01:10:27 txqueuelen 1000 (Ethernet)
RX packets 500 bytes 54062 (52.7 KiB)
RX errors 0 dropped 46 overruns 0 frame 0
TX packets 0 bytes 24423 (23.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 96 (96.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- Linux 시스템의 가젯 포트에서 Android 시스템의 호스트 포트로 USB 케이블을 연결하면 즉시 Android에 인터페이스가 생성되고 Linux에 인터페이스
usb0
에 대한 IP 주소가 생성됩니다 .usb0
기계적 인조 인간:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Driver cdc_subset
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
리눅스:
# ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.119.94 netmask 255.255.0.0 broadcast 169.254.255.255
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 96 (96.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- Android 시스템에서 인터페이스를 불러오면 IP 주소가 할당되지 않으므로 Linux 시스템에서 자체 할당하는 169.254/16 공간을 사용하여 수동으로 할당해야 합니다.
odroidc4:/ # ifconfig usb0 up
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Driver cdc_subset
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:117 errors:4 dropped:75 overruns:0 frame:4
TX packets:27 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5080 TX bytes:4897
odroidc4:/ # ip addr add 169.254.1.1/16 broadcast 169.254.255.255 dev usb0
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Driver cdc_subset
inet addr:169.254.1.1 Bcast:169.254.255.255 Mask:255.255.0.0
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:117 errors:4 dropped:75 overruns:0 frame:4
TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5080 TX bytes:8528
이 시점에서 두 가지 문제가 있습니다. 첫 번째는 다른 장치에서 두 장치를 ping해도 응답이 없다는 것입니다. Android 측에서 패킷 수를 보면 Linux 측에서 핑을 수신하고 있지만 응답하지 않는 것처럼 보입니다. 이는 라우팅 테이블이 예상대로 작동하지 않는 두 번째 문제로 인해 발생할 수 있습니다. 안드로이드 측에서. Android 시스템에 활성 인터넷 연결이 있는 동안 이 작업이 필요하다는 점을 감안할 때 동시에 이더넷이 연결되어 있으며 라우팅을 볼 때 다음과 같이 표시됩니다.
odroidc4:/ # ip route list
169.254.0.0/16 dev usb0 proto kernel scope link src 169.254.1.1
10.42.128.0/24 dev eth0 proto kernel scope link src 10.42.128.166
odroidc4:/ # ip route get 169.254.119.94
169.254.119.94 via 10.42.128.2 dev eth0 table eth0 src 10.42.128.166 uid 0
cache
odroidc4:/ # ip route show table 0
default via 10.42.128.2 dev eth0 table eth0 proto static
...
원격 인터페이스로서의 Android 시스템(OTG 포트를 통한 USB 테더링)
이 시나리오를 사용하면 단방향 통신이 가능해지기 때문에 조금 더 가까워진 것 같습니다.
- Linux 이미지에 필요한 드라이버를 추가한 후 Android OTG 포트의 케이블을 Linux 호스트 포트에 연결하면 시스템에서 USB 장치를 인식하는 모습이 표시됩니다
dmesg
.
[ 235.710937] usb 1-2.3: new full-speed USB device number 7 using at91_ohci
[ 235.862304] rndis_host 1-2.3:1.0 usb0: register 'rndis_host' at usb-at91-2.3, RNDIS device, 32:1d:e8:fc:dd:8
- 인터페이스
usb0
가 즉시 생성되고 Linux 측에 IP 주소가 할당됩니다.
# ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.249.80 netmask 255.255.0.0 broadcast 169.254.255.255
inet6 fe80::e341:f9b1:b676:99b7 prefixlen 64 scopeid 0x20<link>
ether 32:1d:e8:fc:dd:80 txqueuelen 1000 (Ethernet)
RX packets 69 bytes 13572 (13.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 73 bytes 18251 (17.8 KiB)
TX errors 8 dropped 0 overruns 0 carrier 0 collisions 0
- 설정에서 USB 테더링이 활성화된 Android 측에서는 usb0 인터페이스가 나타나지만 시작됩니다. 이를 불러와도 IP 주소가 제공되지 않으므로 수동으로 할당했지만 첫 번째 시나리오와 마찬가지로 라우팅 테이블이 예상대로 작동하지 않는 것 같습니다.
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
odroidc4:/ # ifconfig usb0 up
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
inet6 addr: fe80::dc75:5cff:fe41:2ae6/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1090 TX bytes:2751
odroidc4:/ # ip addr add 169.254.1.1/16 broadcast 169.254.255.255 dev usb0
odroidc4:/ # ip route
10.42.128.0/24 dev eth0 proto kernel scope link src 10.42.128.166
169.254.0.0/16 dev usb0 proto kernel scope link src 169.254.1.1
odroidc4:/ # ip route get 169.254.249.80
169.254.249.80 via 10.42.128.2 dev eth0 table eth0 src 10.42.128.166 uid 0
cache
- 그러나 이 시나리오에서는 인터페이스를 수동으로 지정하여 Android 측에서 성공적인 통신을 얻을 수 있습니다.
odroidc4:/ # ping -c 5 -I usb0 169.254.249.80
PING 169.254.249.80 (169.254.249.80) from 169.254.1.1 usb0: 56(84) bytes of data.
64 bytes from 169.254.249.80: icmp_seq=1 ttl=64 time=1.56 ms
64 bytes from 169.254.249.80: icmp_seq=2 ttl=64 time=1.89 ms
64 bytes from 169.254.249.80: icmp_seq=3 ttl=64 time=1.71 ms
64 bytes from 169.254.249.80: icmp_seq=4 ttl=64 time=1.75 ms
64 bytes from 169.254.249.80: icmp_seq=5 ttl=64 time=1.85 ms
--- 169.254.249.80 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
2|odroidc4:/ # ping6 -c5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 data bytes
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=1 ttl=64 time=0.202 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=1.91 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=2 ttl=64 time=0.196 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=1.80 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=3 ttl=64 time=0.199 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=1.37 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=4 ttl=64 time=0.199 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=1.85 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=5 ttl=64 time=0.205 ms
--- ff02::1%usb0 ping statistics ---
5 packets transmitted, 5 received, +4 duplicates, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 0.196/0.883/1.914/0.776 ms
- 여전히 Linux 측에서 발생하는 트래픽을 작동시킬 수 없습니다. 아마도 Android 쪽의 라우팅 문제로 인해 반환 트래픽이 올바르게 라우팅되지 않기 때문일 것입니다.
# ping -c 5 -I usb0 169.254.1.1
PING 169.254.1.1 (169.254.1.1) from 169.254.249.80 usb0: 56(84) bytes of data.
--- 169.254.1.1 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4295ms
# ping6 -c 5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 data bytes
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=0.522 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=0.302 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=0.376 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=0.383 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=5 ttl=64 time=0.385 ms
--- ff02::1%usb0 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4009ms
rtt min/avg/max/mdev = 0.302/0.393/0.522/0.074 ms
두 시나리오 모두에서 문제의 근본 원인은 Android 측의 라우팅 테이블이 USB 인터페이스를 통해 트래픽을 올바르게 라우팅하지 않고 Linux 측에서는 자동으로 IP 주소를 할당하는 반면 Android 측에서는 IP 주소를 할당하지 않는 것 같습니다. Linux 가젯 인터페이스/Android 호스트를 사용하면 이러한 문제를 어느 정도 이해할 수 있지만 Android OTG 포트 테더링/Linux 호스트를 사용하면 Android 시스템이 테더링 연결을 제어하므로 올바르게 라우팅될 것으로 기대합니다.
답변1
안녕하세요 @rdowell 님,
이 문제를 해결하려면 Android 장치에 기본 경로 테이블을 추가해야 합니다.
ip rule add from all lookup main pref 1