OpenHarmony Liteos_A内核之iperf3移植心得
一、iperf3工作原理
iperf3主要的功能是测试基于特定路径的带宽,在客户端和服务器端建立连接(三次握手)后,客户端发送一定大小的数据报并记下发送的时间,或者客户端在一定的时间内发送数据并记下发送的总数据。带宽的大小等于发送的总数据除以发送的总时间。对服务器端来说,在连接建立时间内,接收的总数据除以所花时间即为服务器端所测得的带宽。
iperf3测试UDP的性能时,客户端可以指定UDP数据流的速率。客户端发送数据时,将根据客户提供的速率计算数据报发送之间的时延,客户还可以指定发送数据报的大小。每个发送的数据报包含一个ID号,用来唯一地标识该报文。服务器端则根据该ID号来确定数据报丢失和乱序。当把UDP报文大小设置可以将整个报文放入IP层的包(packet)内时,那么UDP所测得的报文丢失数据即为IP层包的丢失数据。这提供了一个有效的测试包丢失情况的方法。数据报传输延迟抖动(Jitter)的测试由服务器端完成,客户发送的报文数据包含有发送时间戳,服务器端根据该时间信息和接收到报文的时间戳来计算传输延迟抖动。传输延迟抖动反映传输过程中是否平滑。由于它是一个相对值,所以并不需要客户端和服务器端时间同步。
由上介绍我们可以知道iperf3的功能增加了操作系统网络度量的能力,而携带Liteos_A内核的OpenAtom OpenHarmony(以下简称“OpenHarmony”)操作系统目前还不支持这个功能,特此尝试把iperf3移植到支持Liteos_A内核的OpenHarmony操作系统中,并作此文分享一些心得。
二、iperf3移植过程
iperf3可以运行在Linux和Windows平台下,其使用了标准的POSIX接口,因此将iperf3移植到Liteos_A上,目前Liteos_A支持用户态和内核态的命令,这个也造成了移植的很大困难,所以以下将2种添加命令的方式都记录下,供读者参考。
1. 确定库的类型
OpenHarmony有如下几种目标类型:
executable: 生成可执行文件,对于Liteos_A,在目录/bin下可以找到可执行文件
shared_library: 生成.dll或.so动态链接库、对于Liteos_A,在目录/lib或者 /usr/lib下可以找到动态库
static_library: 生成.lib或.a静态链接库
group: 生成依赖关系组
action: 运行脚本以生成文件
根据以上几种类型的描述可知,将iperf3移植成executable类型的组件最为合适。
2. 添加库到工程中
将源码下载到Linux下并解压,执行./configure,生成iperf_config.h,将iperf3的源码拷贝到OpenHarmony代码库中合适的位置,如下将iperf3添加到/third_party目录下。

需要注意的是非内核态的库不能添加到内核的目录下,不然编译和调试过程中相关的头文件可能找不到。在/vendor/厂商名/产品型号/config.json中的某一子系统下添加组件。

在 /build/lite/components/子系统名.json中添加组件,如下:

3. 编写配置BUILD.gn

移植的iperf3代码目录下需要提供一个gn文件,指明需要编译的代码。此文件可以通过import组件模板函数。一方面,很多引用到的头文件需要逐个添加到系统BUILD.GN中去,import组件模板函数可以省去很多麻烦;另一方面,头文件有多个,最终还很难确定是哪一个,使用系统配置好的组件模板函数,可以自动匹配。
4. 程序启动入口:将三方库添加到shell命令
1) 内核态的shell功能不符合POSIX标准,仅供调试使用,本文特记录下其添加命令的方法,此方法分为静态和动态两种方式,添加方式如下:
① 命令源代码包含如下头文件
#include "shell.h"
#include "shcmd.h"
② 静态注册命令方式
第一步:调用SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook),在源文件最后增加这个调用即可。
第二步:在链接选项中添加链接该新增命令项参数。
即在kernel/liteos_a/tools/build/mk/liteos_tables_ldflags.mk中增加相应选项,SHELLCMD_ENTRY的第一个参数前加-u。
此方法添加的shell,在代码编译阶段就已编译进去了,其实现原理是利用了编译器的section特性(也是代码模块化的重要手段),将所有shell命令相关功能都放在一段连续的地址空间,将SHELLCMD_ENTRY宏一层层展开,即可得到下面原型。
LOS_HAL_TABLE_BEGIN(g_shellcmd, shellcmd); //段的起始tag
LOS_HAL_TABLE_END(g_shellcmdEnd, shellcmd); //段的结束tag
SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook)
如下是编译后生成的map文件中shell段的部分,可以观察到已经通过此方法加入的shell命令。


③ 动态注册命令方式
此类方式是在代码运行阶段动态的注册,osCmdReg本身是一个函数,在命令初始化的源代码增加此函数调用。
UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
函数原型在/kernel/liteos_a/shell/full/src/base/shcmd.c 可以找到,基本原理是将动态注册的shell命令加入到动态shell命令链表空间。
2)用户态的shell不用手动添加
添加目标的方式为executable,将程序下载到目标板上,在/bin目录下找到可执行的文件,只要在串口助手中输入 ./bin/可执行文件名,内核即可动态加载可执行的文件(或者输入exec /bin/可执行文件名)。
三、iperf3使用方式介绍
使用iperf3测试时必须将一台主机设置为客户端,一台主机设置为服务器。在Linux环境或者Windows或者OpenHarmony shell交互窗口输入iperf3 -h可以获取iperf3的帮助信息。以下介绍几种常见的使用方式:
1. iperf3测试TCP
在默认的情况下,iperf3客户端与指定的监听5201端口的iperf3服务器建立一个TCP会话。
服务端:iperf3 -s
客户端:iperf3 -c 服务器IP (默认测试10秒),使用t来设置测试时间,单位是秒。
例如:iperf3 -c 192.168.99.74 -t 20
运行结果如下:


2. iperf3测试UDP
iperf3测试UDP性能时,客户端可以指定UDP数据流的速率。客户端发送数据时,将根据客户端提供的速率计算数据报发送之间的时延。
客户端还可以指定发送数据报的大小。每个发送的数据报包含一个ID号,用来唯一标识报文,服务器端根据该ID号来确定数据报丢失和乱序。
当把UDP报文大小设置可以将整个报文放入IP层的包(packet)内时,那么UDP所测得的报文丢失数据即为IP层包的丢失数据,这提供了一个有效的测试包丢失情况的方法。
数据报传输延迟抖动(Jitter)的测试由服务器端完成,客户发送的报文数据包含有发送时间戳,服务器端根据该时间信息和接收到报文的时间戳来计算传输延迟抖动。传输延迟抖动反映传输过程中是否平滑。由于它是一个相对值,所以并不需要客户端和服务器端时间同步。测试过程如下:
服务端:iperf3 -s -p 6868 (设定服务端监听6868端口)
Liteos_A shell客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M
测试结果:


- Jitter(延时变化):用iperf3 UDP测试来量度
- 数据报丢失:用iperf3 UDP测试来量度
- 带宽:通过TCP测试来量度
3. 反向带宽测试
服务端使用的命令不变,客户端需要加上参数-R,在帮助信息中,可以看到-R的信息是run in reverse mode (server sends, client receives)
服务端:iperf3 -s -p 6868
客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M -R
测试结果如下:

4. 同步双向带宽
测试
客户端加上命令参数 -bidir
服务端:iperf3 -s -p 6868
客户端:./bin/iperf3 -c 172.17.5.159 -p 6868 -u -b 100M -bidir
测试结果如下:


四、注意事项和遇到的问题及解决方法
1. Hi3516有三种下载程序的方式:串口、USB、网口转USB。推荐使用USB来下载程序,使用串口来调试程序。
2. DevEco Device Tool工具使用USB烧录Hi3516DV300镜像时失败,怎么解决?

解决措施:
出现这个问题,主要是因为开发者将Device Tool工具安装在系统盘符,在烧录大文件时会因为没有权限导致失败,可以根据以下操作解决:
● 在Windows平台找到安装目录,如图。鼠标右键,选中属性。
● 依次操作,步骤5将红框中两个选项都勾选上。

3. Hi3516如果携带操作系统是支持Linux内核的OpenHarmony,第一次下载时,需要格式化,下载完成后,系统启动到boot,就不会引导整个系统应用程序,这时需要点击如下菜单,然后重新拔插USB才能进入整个系统。

4. 在编写.gn文件时,如果三方组件为executable,那么第三方库代码中需要有唯一个入口main函数,最终生成一个可执行的命令。
5. iperf有大版本1,2,3,目前最新的是iperf3,不同的版本间命令参数不同,工作机制有所不同,所以在测试时,服务端和客户端要求使用相同的大版本。例如iperf3服务端不支持iperf的-u,-命令。
6. 在使用iperf3进行测试过程中,需要关闭防火墙,不然可能不能进行正常测试,可以提前使用ping测试一下网络是否已通。
7. 公司网络端的控制也会对测试造成影响,如果测试中发现发送和接收到的数据一直是0,则可能是网络控制端进行了控制,在拔掉外网络的情况,测试出来的结果就会很稳定。
8. Hi3516主板作为服务端,输入iperf3 -s,然后在PC机上启动客户端进行测试,发现根本不能进行正常测试,原因也是公司网络控制导致,解决办法是将要测试的两个网络接口,接到同一交换机下,然后拔掉外网的网线,可以进行正常测试;或者需要IT开发权限,当然如果不是在公司特定网络环境下,这个现象是不会出现的。
9. Hi3516需要设置网络才能进行测试,可以使用命令ifconfig来设置,例如:ifconfig eth0 172.17.5.253 netmask 255.255.254.0 gateway 172.17.4.1
10. MSS在OpenHarmony的底层LWIP不支持,在iperf_connect函数中调用getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len),会通过系统调用到达kernel层中的/kernel/liteos_a/compat/posix/src/socket.c, 最终走到底层LWIP的lwip_getsockopt_impl接口,在level IPPROTO_TCP下,对于分支TCP_MAXSEG,没有实现,解决办法是先屏蔽iperf3对此处的操作。同样在调用setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt))时,SO_SNDBUF分支在LWIP也未实现,先屏蔽此处,将发送缓冲区设置成和接收缓冲区同样的大小。
11. Liteos_A未实现延时删除,所以调用unlink时会出错,目前处理是先屏蔽此处。
12. Liteos_A对fprintf的实现也不如Linux,Windows好,所以对help命令输出到stdout上,长字串显示不出来,解决办法是使用fputs替换fprintf。
五、总结
本文从iperf3的工作原理、移植过程、使用方式、注意事项四个方面介绍了将iperf3移植到支持Liteos_A内核的OpenHarmony操作系统中的方法,希望本篇文章对开发者有所帮助。
关于OpenHarmony内核的内容,之前我还介绍了内核对象队列的算法、OpenHarmony LiteOS-M内核事件的运作机制,以及内核IPC机制数据结构,感兴趣的读者可以点击阅读:
《OpenHarmony——内核对象队列之算法详解(上)》、
《OpenHarmony——内核对象队列之算法详解(下)》、

OpenHarmony Liteos_A内核之iperf3移植心得的更多相关文章
- Linux内核3.0移植并基于Initramfs根文件系统启动
Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先, ...
- linux内核链表的移植与使用
一. Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...
- 小白自制Linux开发板 三. Linux内核与文件系统移植
上一篇完成了uboot的移植,但是想要愉快的在开发板上玩耍还需要移植Linux内核和文件系统. 1.Linux内核 事实上对于F1C100S/F1C200S,Linux官方源码已经对licheepi ...
- Linux内核,文件系统移植过程中出现的一些问题与解决办法
1.bootm地址和load address一样 此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行. ...
- Linux内核结构分析与移植
Linux内核主要的5个部分是:进程调度,内存管理,虚拟文件系统,网络接口,进程通信. 这5个部分之间的关系如下: (1)进程调度部分负责控制进程对CPU的访问. (2)内存管理允许多个进程安全地共享 ...
- ANSIC程序到KeilC51的移植心得
摘要:本文讲述了将ANSIC程序移植到KeilC51上应该注意的事项.文章讲述了存储类型.指针类型.重入函数.根据目标系统RAM的分布的段定位和仿真栈设置.函数指针.NULL指针问题.字节顺序.交叉汇 ...
- UCOS移植心得(
移植UCOS之前,你首先应该做好三件事: 1.弄懂UCOS,这是谁都知道的哦 ^_^ 2. 弄懂你想要移植到的硬件平台 3. 清楚你使用的编译器是如何处理函数的局部变量和怎么样处理函数间的参数传递 这 ...
- uboot 、内核、文件系统移植
1. 参考下面博客: http://blog.csdn.net/andylauren/article/details/51448353 2.查看u盘: $ sudo fdisk -l 3. 格式化u盘 ...
- android4.0.3源码之USB wifi移植心得
http://blog.csdn.net/eastmoon502136/article/details/7850157 http://forum.cubietech.com/forum.php?mod ...
- 鸿蒙内核源码分析(根文件系统) | 先挂到`/`上的文件系统 | 百篇博客分析OpenHarmony源码 | v66.01
百篇博客系列篇.本篇为: v66.xx 鸿蒙内核源码分析(根文件系统) | 先挂到/上的文件系统 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...
随机推荐
- pymysql基本语法,sql注入攻击,python操作pymysql,数据库导入导出及恢复数据---day38
1.pymysql基本语法 # ### python操作mysql import pymysql ''' # ### 1.基本语法 #(1) 创建连接 host user password datab ...
- JVM类的加载和加载器
JVM类的加载和类的加载器 一.类的加载过程 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来 ...
- Taurus.MVC WebMVC 入门开发教程4:数据列表绑定List<Model>
前言: 在本篇 Taurus.MVC WebMVC 入门开发教程的第四篇文章中, 我们将学习如何实现数据列表的绑定,通过使用 List<Model> 来展示多个数据项. 我们将继续使用 T ...
- EXE程序缺DLL怎么办
起因 工程师发给用户一个VS编译的windows应用程序,客户反应打不开,报缺少dll.可是dll明明就在当前目录啊,为什么还会报错呢? 那应该是该DLL依赖的其它DLL不存在导致的,用depends ...
- goland快键键防忘
环境: debian下的goland 2018实测: 鼠标button2 == 鼠标中键 光标移动: 跳转光标到刚才的位置: ctrl+win+alt+左/右 按词左右移动光标: ctrl + 左/右 ...
- 5. JVM虚拟机栈
1.概述 说到jvm 其中让人印象最深的就是栈和堆,也是 jvm中占用内存最大的两个地方. 从宏观上来看栈是运行时的单位,而堆是存储的单位 ,栈解决程序的运行问题,即程序如何执行,或者说如何处理数据. ...
- Android drawable与mipmap的区别(android资源文件放置位置)
1.Drawable Android 把可绘制的对象抽象为Drawable,不同的图形图像代表着不同的darwable类型, 通常我们在代码中不会直接接触drawable实现类的,是由android ...
- 记一次 .NET某设备监控自动化系统 CPU爆高分析
一:背景 1. 讲故事 先说一下题外话,一个监控别人系统运行状态的程序,结果自己出问题了,有时候想一想还是挺讽刺的,哈哈,开个玩笑,我们回到正题,前些天有位朋友找到我,说他们的系统会偶发性CPU爆高, ...
- springboot多数据源配置理解
今天研究项目的多数据源配置,产生了一点疑惑,有很多地方没有指定数据源,那么spring如何知道连接哪一个呢?让我们从头开始梳理吧. 首先是数据源配类 其中使用到了两个数据源,项目采用读写分离,一个主库 ...
- java项目-尚硅谷项目三员工调度系统
导入工具类和数据 创建TeamSchedule项目,com.atguigu.team. view,com.atguigu.team.service,com.atguigu.team.domain包 , ...
