首页 文章 精选 留言 我的

精选列表

搜索[AI漏洞挖掘],共10000篇文章
优秀的个人博客,低调大师

挖掘全志Tina Linux下SPI主从通信验证模块的秘密

主控: D1H 板卡: 两块哪吒开发板(以下简称为主机, 从机) 操作系统: Tina Linux 2.0 验证D1H芯片SPI主从机通信. 硬件接线 主机SPI 从机SPI 19 SPI1_MOSI SPI1_MOSI 19 21 SPI1_MISO SPI1_MISO 21 23 SPI1_SCK SPI1_SCK 23 24 SPI1_CE SPI1_CE 24 SPI概述 SPI接口是一种高速的, 全双工, 同步的通信总线. 适配D1H芯片的Tina Linux的BSP-SDK(以下简称SDK)中已包含相关驱动文件: spi-sunxi.c. 它提供的了仅内核态下主从机的简易通信验证实验, 这或许是考虑到SPI通信速率比较高的特性. 验证操作 SPI主机配置 MENUCONFIG 在SDK执行完环境变量加载后, 执行: /mnt/tina-d1-h$ make kernel_menuconfig ●开启Device Drivers->SPI support ●进入SPI support, 按图示开启: 设备树 修改: ./device/config/chips/d1-h/configs/nezha/board.dts 需要根据手册和原理图确认好针脚功能: SPI从机配置 MENUCONFIG (同SPI主机配置一致) 设备树 仅spi_slave_mode设为0, 其余项同SPI主机配置一致. spi_slave_mode = <0>; SPI主机收发信息 按上述配置, 重新编译SDK, 打包, 烧录, 启动设备会出现: root@TinaLinux# ls -l /dev/spidev1.0 crw------- 1 root root 153, 0 Jan 1 08:00 /dev/spidev1.0 然后将可执行的SPI测试程序(./lichee/linux-5.4/tools/spi/spidev_test)挪到设备上(adb push等)并赋予可执行权限: # 主机以10MHz发送(即MOSI)发送16进制数据: 0x01 0x02 0x03 0x04 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x01\x02\x03\x04" # 主机以10MHz发送(即MOSI)发送ASCII字符串数据: "allwinner" ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "allwinner" spi mode: 0x0 bits per word: 8 max speed: 10000000 Hz (10000 KHz) TX | 61 6C 6C 77 69 6E 6E 65 72 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ |allwinner| 注意SPI是同步通信接口, 所以在发送的同时也会接收同样长度字节的数据. 下文将用到SPI主从通信的一种常见做法: 主机先发指令头, 然后再发指令体以获取从机应答. SPI从机收发信息 spi-sunxi.c中对SPI从机模(SLAVE_MODE)采取了简单的收发验证处理, 具体是创建一个内核线程执行int sunxi_spi_slave_task(void *data), 该函数又被设备中断所控制(当收到SPI数据时). SPI从机接收到数据的主要流程: sunxi_spi_slave_task() -> sunxi_spi_slave_handle_head(), 然后: 若指令头是写操作(0x01), 则执行:sunxi_spi_slave_cpu_rx_config(), 该函数仅是输出写入内容. 若指令投是读操作(0x03), 则执行:sunxi_spi_slave_cpu_tx_config(), 该函数仅是将收到的指令体的值+0x80, 然后发送(MISO)给主机. 对于从机, spi-sunxi.c能验证SPI通信, 但没有可供用户层直接使用的方法. 用户层可验证的SPI从机收发方案 功能设计 从机安排一块32byte的内存缓存空间(简称"缓存空间")供主机通过指令进行读操作和写操作, 且从机能在用户层对该内存空间访问. 主要改动 spi.c: 增加static struct class_attribute ye_spi_buf_attrs[], 以创建/sys/class/spi_slave目录下的spi_buf文件, 并提供实现了读/写缓存空间的方法. spi-sunxi.c: 使用ye_spi_slave_set_txdata()方法替换sunxi_spi_slave_set_txdata(), 以实现读操作. 修改sunxi_spi_slave_cpu_rx_config()方法, 以实现写操作. 改动详情请查看:d1h_spi_driver.diff 使用方法 写操作: 操作:0x01(写) 地址:0x00 0x00 0x00 指令体长度:0x09 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x01\x00\x00\x00\x09" && \ ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "allwinner" 读操作: 操作:0x03(读) 地址:0x00 0x00 0x00 指令体长度:0x09 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x03\x00\x00\x00\x09" && \ ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x00\x00\x00\x00\x00\x00\x00\x00\x00" 从机读取缓存空间: cat /sys/class/spi_slave/spi_buf 从机写入缓存空间: echo "Hello world" > /sys/class/spi_slave/spi_buf

优秀的个人博客,低调大师

Java技术专题-JVM研究系列(9)JVM深入研究挖掘课题

JVM执行引擎的效率提升 JVM是如何在保证可移植性的前提下提供高执行效率的? Java跨平台性 Java程序最为常见的执行方式,是预先编译为一种名为 Java 字节码的中间代码格式。这种代码格式无法直接运行在 CPU 之上,而是需要借助 JVM 来执行。换句话说,只要某个平台提供了合乎JVM 规范的实现,它便能执行这份Java 字节码。这也就是我们经常说的“一次编写,到处运行”。 Java执行方式 主流的 OpenJDK/OracleJDK 中所提供的 JVM 叫做HotSpot。它同时采用了解释执行和即时编译。 解释执行就好比同声传译,JVM一边理解输入的字节码一边解释字节码生成机器码向CPU发出指令序列; 即时编译则是“磨刀不误砍柴工”,JVM 会在运行过程中将 热点代码编译成为可直接执行二进制代码。 这种混合执行模式是建立在程序符合二八定律的假设上,即百分之二十的代码占据了百分之八十的计算资源。对于不常用代码,我们无需耗费时间将其编译成二进制代码,而是采取解释执行的方式运行;另一方面,对于仅占据小部分的热点代码,JVM 则会花费时间将其编译为二进制代码,以达到理想的运行效率。 Java异常捕获 编译生成的Java字节码中,每个方法都附带一个异常表。异常表中的每一行均定义了一条异常执行路径,其中包括规定捕获范围的起始字节码索引、终止(不包含)字节码索引,异常处理代码的起始字节码索引,以及所捕获的异常类型。 当程序触发异常时,JVM会从上至下遍历异常表中的所有条目。当触发异常的字节码的索引值在某行异常表条目的捕获范围内,JVM 会判断所抛出的异常和该条目想要捕获的异常是否匹配。如果匹配,JVM 会将控制流转移至该条目所指向的异常处理代码。 上述异常捕获机制还被用于 finally 从句的实现。通常,Java程序的编译器javac会复制多份 finally 代码块,放置于生成的 Java 字节码之中,然后通过生成多行异常表条目,来实现完整的 finally 逻辑。 Java反射调用 默认情况下,反射调用首先会被委派给native方法来进行。可想而知,其运行效率低下。当某个反射调用的调用次数达到 15 之后,JDK 代码断定该调用属于热点调用。 继而,JDK 将动态生成直接调用目标方法的字节码,并将反射调用的委派对象由原本的 native 方法实现切换至该动态生成的实现。这种方式的运行效率相对于 native 方法来说要高很多。 之所以 JDK 不从一开始便采用动态生成字节码的方式,主要是因为生成过程需要耗费一定的时间。对于那些整个生命周期中仅执行数次的反射调用,动态生成字节码将得不偿失。 然而,即便是直接调用目标方法的动态实现,其峰值性能也无法跟真正的直接调用相媲美。这背后涉及到即时编译中的虚方法内联。 JVM垃圾回收 目前 JVM 的主流垃圾回收器采取的都是可达性分析算法。 该算法的实质是将一系列被称为GC Roots的对象作为初始的存活对象合集,然后从该合集出发探索所有能够被该集合引用到的对象,并标记为存活对象。当标记阶段结束之后,未被标记到的对象便是可以清除的。 传统的垃圾回收算法在标记、清除过程中需要中止其他应用线程,即所谓的 Stop-The-World。新型的垃圾回收算法,如 CMS、G1 以及 ZGC,尽可能地实现并发标记、清除,从而让Stop-The-World 的时间长度可控。 垃圾回收的另一基础思想则是分代回收。JVM 会将新生成的对象划为新生代,而将在多次垃圾回收中存活下来的对象划为老年代。JVM 会为不同的分代设置不同的回收算法,从而达到新生代多收集、快收集,老年代少收集、全收集的目标。 Java内存模型 现代计算机多为对称多处理器的体系架构。每个处理器均有独立的寄存器组和缓存(这在 Java 内存模型中被抽象为工作内存);多个处理器可同时执行同一进程中的不同线程。 不同线程可能访问同一变量或对象。如果任由编译器或处理器对这些访问进行优化,则很可能出现在单线程执行思维下无法想象的问题。因此,Java语言规范引入了Java内存模型,通过定义多项规则对编译器和处理器进行限制。 这些规则所体现的最为重要的属性便是可见性,即对某一变量的访问能否被同一线程的其他操作,或者不同线程所观测到。 Java内存模型引入了多种 happens-before 关系,以实现上述可见性。以volatile字段为例,对其的写操作 happens before这之后的读操作,也就是说,我们总能读到volatile字段的最新值。 JVM对象锁 重量级锁是最为基础、最为低效的对象锁实现。JVM会阻塞加锁失败的线程,并且在目标锁被释放的时候,唤醒这些线程。我们用等红灯作类比。Java线程进入阻塞状态相当于熄火停车,再次点火启动必然耗费时间。JVM 会在进入阻塞状态之前进行自旋,也就是怠速停车。如果目标锁能够在短时间内被释放出来,该线程便能够不进入阻塞状态,直接获取该锁。 重量级锁针对的是多个线程同时竞争同一把锁的场景。在现实中,多个线程可能在不同时间段持有同一把锁。为了应对这种没有锁竞争的情况,JVM 采用了轻量级锁机制。在加锁时,JVM 将在锁对象处做标记,指向当前线程的栈上;在解锁时,上述标记会被清除。如果某线程在请求锁时,发现该锁为轻量级锁,并且指向另一线程所对应的栈,那么它会将该锁膨胀为重量级锁。 偏向锁所应对的场景则更为乐观:至始至终只有一个线程请求某把锁。JVM 采取的做法是在第一次加锁时为锁对象做标记,使其指向当前线程的地址;在解锁时则不做任何操作。如果下一次请求该锁的仍是同一线程,便直接跳过标记过程;否则,JVM 会将该锁膨胀为轻量级锁。

优秀的个人博客,低调大师

Hadoop MapReduce编程 API入门系列之挖掘气象数据版本2(十)

这篇博文,包括了,实际生产开发非常重要的,单元测试和调试代码。这里不多赘述,直接送上代码。 MRUnit 框架 MRUnit是Cloudera公司专为Hadoop MapReduce写的单元测试框架,API非常简洁实用。MRUnit针对不同测试对象使用不同的Driver: MapDriver:针对单独的Map测试 ReduceDriver:针对单独的Reduce测试 MapReduceDriver:将map和reduce串起来测试 PipelineMapReduceDriver:将多个MapReduce对串志来测试 记得,将这个jar包,放到工程项目里。我这里是在工程项目的根目录下的lib下。 代码版本2 编写TemperatureMapperTest.java的代码。 编译,出现以下,则说明无误。 在test()方法中,withInput的key/value参数分别为偏移量和一行气象数据,其类型要与TemperatureMapper的输入类型一致即为LongWritable和Text。 withOutput的key/value参数分别是我们期望输出的new Text("03103")和new IntWritable(200),我们要达到的测试效果就是我们的期望输出结果与 TemperatureMapper 的实际输出结果一致。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 Mapper 测试成功了。 创建TemperatureReduceTest.java,来对Reduce进行测试。 在test()方法中,withInput的key/value参数分别为new Text(key)和List类型的集合values。withOutput 的key/value参数分别是我们所期望输出的new Text(key)和new IntWritable(150),我们要达到的测试效果就是我们的期望输出结果与TemperatureReducer实际输出结果一致。 编写TemperatureReduceTest.java的代码。 编译,出现以下,则说明无误。 Reducer 端的单元测试,鼠标放在 TemperatureReduceTest 类上右击,选择 Run As ——> JUnit test,运行结果如下所示。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 Reducer 测试成功了。 MapReduce 单元测试 把 Mapper 和 Reducer 集成起来的测试案例代码如下。 创建TemperatureTest.java,来进行测试。 在 test() 方法中,withInput添加了两行测试数据line和line2,withOutput 的key/value参数分别为我们期望的输出结果new Text("03103")和new IntWritable(150)。我们要达到的测试效果就是我们期望的输出结果与Temperature实际的输出结果一致。 编写TemperatureTest.java的代码。 编译,出现以下,则说明无误。 Reducer 端的单元测试,鼠标放在 TemperatureTest.java类上右击,选择 Run As ——> JUnit test,运行结果如下所示。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 MapReduce 测试成功了。 Temperature.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import org.apache.hadoop.io.IntWritable; 6 import org.apache.hadoop.io.LongWritable; 7 import org.apache.hadoop.io.Text; 8 import org.apache.hadoop.mapreduce.Mapper; 9 import org.apache.hadoop.mapreduce.lib.input.FileSplit; 10 import org.apache.hadoop.conf.Configuration; 11 import org.apache.hadoop.conf.Configured; 12 import org.apache.hadoop.fs.FileSystem; 13 import org.apache.hadoop.fs.Path; 14 import org.apache.hadoop.io.IntWritable; 15 import org.apache.hadoop.io.Text; 16 import org.apache.hadoop.mapreduce.Job; 17 import org.apache.hadoop.mapreduce.Mapper; 18 import org.apache.hadoop.mapreduce.Reducer; 19 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 20 import org.apache.hadoop.mapreduce.lib.input.FileSplit; 21 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 22 import org.apache.hadoop.util.Tool; 23 import org.apache.hadoop.util.ToolRunner; 24 25 26 /* 27 Hadoop内置的数据类型: 28 BooleanWritable:标准布尔型数值 29 ByteWritable:单字节数值 30 DoubleWritable:双字节数值 31 FloatWritable:浮点数 32 IntWritable:整型数 33 LongWritable:长整型数 34 Text:使用UTF8格式存储的文本 35 NullWritable:当<key, value>中的key或value为空时使用 36 */ 37 38 39 /** 40 * 统计美国每个气象站30年来的平均气温 41 * 1、编写map()函数 42 * 2、编写reduce()函数 43 * 3、编写run()执行方法,负责运行MapReduce作业 44 * 4、在main()方法中运行程序 45 * 46 * @author zhouls 47 * 48 */ 49 //继承Configured类,实现Tool接口 50 public class Temperature extends Configured implements Tool{ 51 public static class TemperatureMapper extends Mapper<LongWritable, Text, Text, IntWritable>{ 52 //输入的key,输入的value,输出的key,输出的value 53 //输入的LongWritable键是某一行起始位置相对于文件起始位置的偏移量,不过我们不需要这个信息,所以将其忽略。 54 55 // 在这种情况下,我们将气象站id按 Text 对象进行读/写(因为我们把气象站id当作键),将气温值封装在 IntWritale 类型中。只有气温数据不缺失,这些数据才会被写入输出记录中。 56 57 58 // map 函数的功能仅限于提取气象站和气温信息 59 60 /** 61 * @function Mapper 解析气象站数据 62 * @input key=偏移量 value=气象站数据 63 * @output key=weatherStationId value=temperature 64 */ 65 public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{ 66 //map()函数还提供了context实例,用于键值对的输出 或者说 map() 方法还提供了 Context 实例用于输出内容的写入 67 68 // 就本示例来说,输入键是一个长整数偏移量,输入值是一行文本,输出键是气象站id,输出值是气温(整数)。 69 // 同时context作为了map和reduce执行中各个函数的一个桥梁,这个设计和Java web中的session对象、application对象很相似 70 71 72 //第一步,我们将每行气象站数据转换为每行的String类型 73 String line = value.toString(); //每行气象数据 74 // values是1980 12 01 00 78 -17 10237 180 21 1 0 0 75 // line是"1980 12 01 00 78 -17 10237 180 21 1 0 0" 76 77 78 //第二步:提取气温值 79 int temperature = Integer.parseInt(line.substring(14, 19).trim());//每小时气温值 80 //需要转换为整形,截取第14位到19位,从第0位开始,trim()的功能是去掉首尾空格。 81 //substring()方法截取我们业务需要的值 82 83 // substring(start, stop)其内容是从 start 处到 stop-1 处的所有字符,其长度为 stop 减 start。 84 85 // 如Hello world! 若是substring(3,7) 则是lo w 86 87 // Integer.parseInt() 返回的是一个int的值。在这里, 给temperature 88 89 // new Integer.valueof()返回的是Integer的对象。 90 // Integer.parseInt() 返回的是一个int的值。 91 // new Integer.valueof().intValue();返回的也是一个int的值。 92 93 94 95 96 97 // 1980 12 01 00 78 -17 10237 180 21 1 0 0 98 //78是气温值 99 100 // temperature是78 101 102 // 30yr_03103.dat 103 // 30yr_03812.dat 104 // 30yr_03813.dat 105 // 30yr_03816.dat 106 // 30yr_03820.dat 107 // 30yr_03822.dat 108 // 30yr_03856.dat 109 // 30yr_03860.dat 110 // 30yr_03870.dat 111 // 30yr_03872.dat 112 113 114 // (0,1985 07 31 02 200 94 10137 220 26 1 0 -9999) 115 // (62,1985 07 31 03 172 94 10142 240 0 0 0 -9999) 116 // (124,1985 07 31 04 156 83 10148 260 10 0 0 -9999) 117 // (186,1985 07 31 05 133 78 -9999 250 0 -9999 0 -9999) 118 // (248,1985 07 31 06 122 72 -9999 90 0 -9999 0 0) 119 // (310,1985 07 31 07 117 67 -9999 60 0 -9999 0 -9999) 120 // (371,1985 07 31 08 111 61 -9999 90 0 -9999 0 -9999) 121 // (434,1985 07 31 09 111 61 -9999 60 5 -9999 0 -9999) 122 // (497,1985 07 31 10 106 67 -9999 80 0 -9999 0 -9999) 123 // (560,1985 07 31 11 100 56 -9999 50 5 -9999 0 -9999) 124 125 // (03103,[200,172,156,133,122,117,111,111,106,100]) 126 127 // 根据自己业务需要 , map 函数的功能仅限于提取气象站和气温信息 128 129 130 // 1998 #year 131 // 03 #month 132 // 09 #day 133 // 17 #hour 134 // 11 #temperature 感兴趣 135 // -100 #dew 136 // 10237 #pressure 137 // 60 #wind_direction 138 // 72 #wind_speed 139 // 0 #sky_condition 140 // 0 #rain_1h 141 // -9999 #rain_6h 142 143 144 if (temperature != -9999){//过滤无效数据 145 //第三步:提取气象站编号 146 //获取输入分片 147 FileSplit fileSplit = (FileSplit) context.getInputSplit();//提取问加你输入分片,并转换类型 148 // 即由InputSplit -> FileSplit 149 150 // context.getInputSplit() 151 // (FileSplit) context.getInputSplit()这是强制转换 152 // fileSplit的值是file:/D:/Code/MyEclipseJavaCode/myMapReduce/data/temperature/30yr_03870.dat:0+16357956 153 // 即,读的是30yr_03870.dat这个文件 154 155 156 //然后通过文件名称提取气象站编号 157 String weatherStationId = fileSplit.getPath().getName().substring(5, 10);//通过文件名称提取气象站id 158 //首先通过文件分片fileSplit来获取文件路径,然后再获取文件名字,然后截取第5位到第10位就可以得到气象站 编号 159 // fileSplit.getPath() 160 // fileSplit.getPath().getName() 161 162 // 30yr_03870.dat 我们只需获取03870就是气象站编号 163 164 // fileSplit.getPath().getName().substring(5, 10) //从0开始,即第5个开始截取,到第10个为止,第10个没有拿到,所以为03870 165 // weatherStationId是03870 166 167 168 169 context.write(new Text(weatherStationId), new IntWritable(temperature));//写入weatherStationId是k2,temperature是v2 170 // context.write(weatherStationId,temperature);等价 ,但是若是直接这样写会出错,因为, weatherStationId是String类型,注意与Text类型还是有区别的! 171 //气象站编号,气温值 172 } 173 } 174 } 175 176 177 178 public static class TemperatureReducer extends Reducer< Text, IntWritable, Text, IntWritable>{ 179 private IntWritable result = new IntWritable();//存取结果 180 //因为气温是IntWritable类型 181 public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{ 182 // Iterable<IntWritable> values是iterable(迭代器)变量 183 184 185 // Iterable<IntWritable> values和IntWritable values这样有什么区别? 186 // 前者是iterable(迭代器)变量,后者是intwriteable(int的封装)变量 187 188 189 // Iterable<IntWritable> values 190 // 迭代器,valuses是 iterable(迭代器)变量,类型是IntWritable 191 192 193 //reduce输出的key,key的集合,context的实例 194 //第一步:统计相同气象站的所有气温 195 int sum = 0; 196 int count = 0; 197 for (IntWritable val : values) //星型for循环来循环同一个气象站的所有气温值,即将values的值一一传给IntWritable val 198 // IntWritable val是IntWritable(int的封装)变量 199 200 {//对所有气温值累加 201 sum += val.get();//去val里拿一个值,就sum下 202 203 // val.get()去拿值 204 205 count++; 206 } 207 result.set(sum / count);//设为v3 208 // result.set(sum / count)去设置,将sum / count的值,设给result 209 // sum是21299119 count是258616 = 82.3580869 210 211 212 context.write(key,result);//写入key是k3,result是v3 213 } 214 } 215 216 217 218 public int run(String[] args) throws Exception{ 219 // TODO Auto-generated method stub 220 //第一步:读取配置文件 221 Configuration conf = new Configuration();//程序里,只需写这么一句话,就会加载到hadoop的配置文件了 222 //Configuration类代表作业的配置,该类会加载mapred-site.xml、hdfs-site.xml、core-site.xml等配置文件。 223 224 // new Configuration() 225 226 //第二步:输出路径存在就先删除 227 Path mypath = new Path(args[1]);//定义输出路径的Path对象,mypath 228 229 230 // new Path(args[1])将args[1]的值,给mypath 231 232 FileSystem hdfs = mypath.getFileSystem(conf);//程序里,只需写这么一句话,就可以获取到文件系统了。 233 //FileSystem里面包括很多系统,不局限于hdfs,是因为,程序读到conf,哦,原来是hadoop集群啊。这时,才认知到是hdfs 234 235 if (hdfs.isDirectory(mypath))//如果输出路径存在 236 { 237 hdfs.delete(mypath, true);//则就删除 238 } 239 //第三步:构建job对象 240 Job job = new Job(conf, "temperature");//新建一个任务,job名字是tempreature 241 242 // new Job(conf, "temperature")有这么个构造方法 243 244 job.setJarByClass(Temperature.class);// 设置主类 245 //通过job对象来设置主类Temperature.class 246 247 //第四步:指定数据的输入路径和输出路径 248 FileInputFormat.addInputPath(job, new Path(args[0]));// 输入路径,args[0] 249 FileOutputFormat.setOutputPath(job, new Path(args[1]));// 输出路径,args[1] 250 251 //第五步:指定Mapper和Reducer 252 job.setMapperClass(TemperatureMapper.class);// Mapper 253 job.setReducerClass(TemperatureReducer.class);// Reducer 254 255 //第六步:设置map函数和reducer函数的输出类型 256 job.setOutputKeyClass(Text.class); 257 job.setOutputValueClass(IntWritable.class); 258 259 //第七步:提交作业 260 return job.waitForCompletion(true)?0:1;//提交任务 261 } 262 263 264 /** 265 * @function main 方法 266 * @param args 267 * @throws Exception 268 */ 269 public static void main(String[] args) throws Exception { 270 //第一步 271 // String[] args0 = 272 // { 273 // "hdfs://djt002:9000/inputData/temperature/", 274 // "hdfs://djt002:9000/outData/temperature/" 275 // }; 276 277 String[] args0 = {"./data/temperature/","./out/temperature/"}; 278 279 // args0是输入路径和输出路径的属组 280 281 //第二步 282 int ec = ToolRunner.run(new Configuration(), new Temperature(), args0); 283 284 // ToolRunner.run(new Configuration(), new Temperature(), args0)有这么一个构造方法 285 286 //第一个参数是读取配置文件,第二个参数是主类Temperature,第三个参数是输入路径和输出路径的属组 287 System.exit(ec); 288 } 289 290 } 291 TemperatureMapperTest.java 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 6 import org.apache.hadoop.io.IntWritable; 7 import org.apache.hadoop.io.LongWritable; 8 import org.apache.hadoop.io.Text; 9 import org.apache.hadoop.mapreduce.Mapper; 10 import org.apache.hadoop.mrunit.mapreduce.MapDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Mapper 端的单元测试,这里用MRUnit框架,需要使用mrunit-hadoop.jar 16 */ 17 @SuppressWarnings("all")//告诉编译器忽略指定的警告,不用在编译完成后出现警告信息 18 public class TemperatureMapperTest{ 19 private Mapper mapper;//定义一个Mapper对象,是mapper 20 private MapDriver driver;//定义一个MapDriver对象,是driver,因为是要MapDriver去做! 21 22 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 23 public void init(){//初始化方法init 24 mapper = new Temperature.TemperatureMapper();//实例化一个Temperature中的TemperatureMapper对象 25 driver = new MapDriver(mapper);//实例化MapDriver对象 26 } 27 28 29 @Test//@Test是测试方法提示符,一般与@Before组合使用 30 public void test() throws IOException{ 31 //因为测试的是Map 32 //输入一行测试数据 33 String line = "1985 07 31 02 200 94 10137 220 26 1 0 -9999"; 34 driver.withInput(new LongWritable(), new Text(line))//withInput方法是第一行输入 跟TemperatureMapper输入类型一致 35 .withOutput(new Text("03103"), new IntWritable(200))//withOutput方法是输出 跟TemperatureMapper输出类型一致 36 .runTest();//runTest方法是调用运行方法 37 } 38 } TemperatureReduceTest.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import java.util.ArrayList; 6 import java.util.List; 7 import org.apache.hadoop.io.IntWritable; 8 import org.apache.hadoop.io.Text; 9 import org.apache.hadoop.mapreduce.Reducer; 10 import org.apache.hadoop.mrunit.mapreduce.ReduceDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Reducer 单元测试,这里用MRUnit框架,需要使用mrunit-hadoop.jar 16 */ 17 @SuppressWarnings("all")//告诉编译器忽略指定的警告,不用在编译完成后出现警告信息 18 public class TemperatureReduceTest{ 19 private Reducer reducer;//定义一个Reducer对象,是 reducer 20 private ReduceDriver driver;//定义一个ReduceDriver对象,是driver,因为是要ReduceDriver去做! 21 22 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 23 public void init(){//初始化方法init 24 reducer = new Temperature.TemperatureReducer();//实例化一个Temperature中的TemperatureReducer对象 25 driver = new ReduceDriver(reducer);//实例化ReduceDriver对象 26 } 27 28 @Test//@Test是测试方法提示符,一般与@Before搭配使用 29 public void test() throws IOException{//为了模拟在reduer端单元测试,所以需如下 30 String key = "03103";//声明一个key值 31 List values = new ArrayList(); 32 values.add(new IntWritable(200));//添加第一个value值 33 values.add(new IntWritable(100));//添加第二个value值 34 driver.withInput(new Text(key), values)//withInput方法是第一行输入 跟TemperatureReducer输入类型一致 35 .withOutput(new Text(key), new IntWritable(150))//withOutput方法是输出 跟TemperatureReducer输出类型一致 36 .runTest();//runTest方法是调用运行方法 37 } 38 } TemperatureTest.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import org.apache.hadoop.io.IntWritable; 6 import org.apache.hadoop.io.LongWritable; 7 import org.apache.hadoop.io.Text; 8 import org.apache.hadoop.mapreduce.Mapper; 9 import org.apache.hadoop.mapreduce.Reducer; 10 import org.apache.hadoop.mrunit.mapreduce.MapReduceDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Mapper 和 Reducer 集成起来测试,这里用MRUnit框架 16 */ 17 @SuppressWarnings("all") 18 public class TemperatureTest { 19 private Mapper mapper;//定义一个Mapper对象 20 private Reducer reducer;//定义一个Reducer对象 21 private MapReduceDriver driver;//定义一个MapReduceDriver对象是driver,因为是对map和reducer联合起来测试,所以需要MapReduceDriver去做! 22 23 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 24 public void init(){ //初始化方法init 25 mapper = new Temperature.TemperatureMapper();//实例化一个Temperature中的TemperatureMapper对象 26 reducer = new Temperature.TemperatureReducer();//实例化一个Temperature中的TemperatureReducer对象 27 driver = new MapReduceDriver(mapper, reducer);//实例化MapReduceDriver对象 28 } 29 30 @Test//@Test是测试方法提示符 31 public void test() throws RuntimeException, IOException{ 32 //输入两行行测试数据 33 String line = "1985 07 31 02 200 94 10137 220 26 1 0 -9999"; 34 String line2 = "1985 07 31 11 100 56 -9999 50 5 -9999 0 -9999"; 35 driver.withInput(new LongWritable(), new Text(line))//withInput方法是第一行输入 跟TemperatureMapper输入类型一致 36 .withInput(new LongWritable(), new Text(line2))//第二行输入 37 .withOutput(new Text("03103"), new IntWritable(150))//withOutput方法是输出 跟TemperatureReducer输出类型一致 38 .runTest();//runTest方法是调用运行方法 39 } 40 } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6164003.html,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册