在做一个ZYNQ项目时,需要实现嵌入式Linux与Windows电脑直连。可能会有盆友会遇到类似的需求,所以整理分享一下。
问题描述
基于ZYNQ芯片设计的一块嵌入式板子,板上运行Linux需要将大量的数据通过网口传输给电脑。这里借用黑金AX7010开发板示例,事实上也是这样做实验的。最开始系统是这样工作的:
板子连以及电脑网口都连接在路由器的LAN口,路由器自动给电脑与板子分配IP地址,板子与电脑在同一个子网里。从而实现了数据通信。这样用是能用,就是设备总是需要带一个路由器,这样很不方便。有没有办法直连呢?就像下面这样:
这样就需要配置板子与电脑的IP地址在同一个网段内,有没有什么办法能够自动分配IP地址给板子以及电脑呢?经过一些搜索,发现了这么一个非常棒的开源组件Avahi。下面就来分享一下Avahi。
何为Avahi?
https://www.avahi.org/
Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite. This enables you to plug your laptop or computer into a network and instantly be able to view other people who you can chat with, find printers to print to or find files being shared. Compatible technology is found in Apple MacOS X (branded "Bonjour" and sometimes "Zeroconf").
Avahi is primarily targetted at Linux systems and ships by default in most distributions. It is not ported to Windows at this stage, but will run on many other BSD-like systems. The primary API is D-Bus and is required for usage of most of Avahi, however services can be published using an XML service definition placed in /etc/avahi/services.
翻译一下:
Avahi 是一个通过 mDNS/DNS-SD 协议实现在局域网发现服务的系统。从而使您能够将笔记本电脑或计算机连接到网络,并立即能够查看可以与之会话的其他机器、查找局域网打印机或查找正在共享的文件。在 Apple MacOS X中存在与之兼容的技术(品牌为 “Bonjour”,也称为“Zeroconf” 零配置)。
Avahi 主要针对 Linux 系统,并在大多数发行版中默认提供。目前还不支持Windows,但可以在许多其他类似 BSD 的系统上运行。主要 API 基于D-Bus实现,并可以在/etc/avahi/services 中的 XML 文件中定义发布服务。
那么什么是mDNS/DNS-SD呢?什么又是零配置呢?
mDNS协议
mDNS是multicast DNS的缩写,也即是多播DNS协议。
什么是DNS呢?简单打个比方就是相当于电话簿,比如要给某人打电话,往往很难记住某个人的电话号码,因此需要去电话簿查这个人的号码,然后再拨过去。计算机间通信IP需要知道目标机的IP地址,也是常常使用主机名或者某个站点的域名进行访问,但是就通信协议而言则是需要对应机器的IP地址。因为DNS系统就被设计出来了。
DNS(Domain Name Server) 是指域名系统,是用于管理域名与IP间对应关系的软件系统。那么问题来了,mDNS与常规的DNS又有何差异呢?
和DNS一样,mDNS也是将域名解析为IP地址,不同的是mDNS在局域网级别运行,这与全局级别运行的常规DNS不同。它与零配置(Zeroconf)网络中的DNS-SD(DNS-Service Discovery)协议结合使用。零配置网络不需要手动操作。此外,零配置网络不依赖DNS服务器和DHCP服务器进行操作。
DNS-SD协议
DNS-SD又是个什么东西呢?用来做什么的呢?DNS-SD允许客户端获取服务实例及其服务类型的命名列表,并使用标准DNS查询消息将这些服务解析为主机名。mDNS协议在RFC6762中定义,DNS-SD协议在RFC6763中定义。mDNS有多种实现版本,比如Bonjor,Avahi,Windows等。
怎么使能Avahi
对于ZYNQ系统使用petalinux-tools编译构建Linux内核以及根文件系统,使用起来非常方便。
- 首先在已经建立的petalinux工程运行根文件系统配置命令:
petalinux-config -c rootfs
这样得到如下的配置界面:
2.选择 Filesystem Packages进入:
3.选择network进入下一级配置界面:
4.进入avahi配置界面进入:
如上图这样配置,保存退出,就完成avahi配置了。
5.编译部署
petalinux-build
再运行如下命令,生成部署镜像文件:
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga xxxx.bit --u-boot --force
xxxx.bit是PL的FPGA所需要的bit文件。
6.运行测试
将BOOT.BIN以及image.ub文件拷贝进SD卡,将板子与电脑网口用网线直连,然后系统上电运行,可见到如下类似的内核打印信息:
INIT: Entering runlevel: 5
Configuring network interfaces... IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
udhcpc: started, v1.29.2
run-parts: /etc/udhcpc.d/00avahi-autoipd: exit status 1
udhcpc: sending discover
random: app: uninitialized urandom read (4 bytes read)
Server is listening...
udhcpc: sending discover
macb e000b000.ethernet eth0: link up (1000/Full)
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
udhcpc: sending discover
random: avahi-autoipd: uninitialized urandom read (4 bytes read)
"169.254.3.140"
broadcastDatagram
udhcpc: no lease, forking to background
done.
random: dbus-uuidgen: uninitialized urandom read (12 bytes read)
random: dbus-uuidgen: uninitialized urandom read (8 bytes read)
Starting system message bus: dbus.
Starting internet superserver: inetd.
Starting syslogd/klogd: done
* Starting Avahi mDNS/DNS-SD Daemon: avahi-daemon
...done.
* Starting Avahi Unicast DNS Configuration Daemon: avahi-dnsconfd
...done.
检查板子的IP地址:
root@idaq:~# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0A:35:00:1E:53
inet6 addr: fe80::20a:35ff:fe00:1e53/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:39 errors:0 dropped:0 overruns:0 frame:0
TX packets:63 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4132 (4.0 KiB) TX bytes:8953 (8.7 KiB)
Interrupt:27 Base address:0xb000
eth0:avahi Link encap:Ethernet HWaddr 00:0A:35:00:1E:53
inet addr:169.254.3.140 Bcast:169.254.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
Interrupt:27 Base address:0xb000
再检查电脑的IP地址:
从而开发板IP地址为169.254.3.140,电脑的IP为169.254.50.229,子网掩码都是255.255.0.0,所以电脑与开发板处于同一个子网中。剩下做应用就是利用socket进行TCP/UDP通信了。
这里对avahi的几个配置项做个简要的介绍:
- avahi-dbg:使能这个选项就将avahi相关的调试符号编译进去了。
- libavahi-glib:将avahi引擎编译成glib库接口以支持GTK+/GNOME
- libavahi-client:编译avahi client库
- libavahi-core:编译avahi引擎编译成库,将完整的 mDNS/DNS-SD栈嵌入到应用软件中的 API。这仅适用于嵌入式设备的开发人员。
- avahi-dev:多播/单播 DNS-SD框架
- avahi-dnsconfd:mDNS/DNS-SD配置守护进程的单播DNS服务器。avahi-dnsconfd 连接到正在运行的avahi-daemon,并为本地 LAN 根据脚本 /etc/avahi/dnsconfd.action发送单播DNS服务。如此mDNS 就以类似DHCP的方式配置单播 DNS 服务。
- avahi-autoipd:avahi-autoipd 实现了 IPv4LL,即“IPv4 链路本地地址的动态配置协议”(IETF RFC3927),是一种无需中央服务器即可从链路本地 169.254.0.0/16 范围自动配置 IP 地址的协议。主要用于缺少DHCP服务器的ad-hoc网络。avahi-autoipd可以用作独立的地址分配器或用作DHCP客户端的插件,如果找不到DHCP服务器,它可以用作后备解决方案。
- avahi-utils:该配置项将使能多个实用程序,可以使用这些命令行与Avahi守护程序交互,包括发布、浏览和发现服务。
- libavahi-common:该配置项使能Avahi 通用库。
- avahi-daemon:Avahi mDNS/DNS-SD守护进程实现了Zeroconf 架构。该守护进程使用mDNS/DNS-SD注册本地 IP 地址和静态服务,并为本地程序提供两个进程间通信的API,以利用 avahi-daemon维护的 mDNS 记录缓存。
- avahi-daemon 在系统启动时解释其配置文件 /etc/avahi/avahi-daemon.conf 并从 /etc/avahi/services/*.service 读取 XML ,这些信息可能被定义为静态 DNS-SD服务。如果在 avahi-daemon.conf 中启用 publish-resolv-conf-dns-servers,文件 /etc/resolv.conf 也将被读取。
- libavahi-gobject:使能Avahi的GObject 接口库。
总结一下
如果你使用buildroot进行系统构建,Buildroot也已经内置了Avahi的支持,配置也基本类似。当然你也可以直接下载源码进行交叉编译,不过个人不建议这样使用。
总之,利用Avahi可以方便实现零配置网络,实现嵌入式Linux与电脑直连,自动分配IP地址给电脑只是一个比较简单实用的应用,利用其库还可以开发出更为复杂的应用。