已阅读5页,还剩70页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1 1 3 2 4 5 嵌入式Linux交叉编译环境的建立 Linux开发环境的建立 6 7 嵌入式Linux应用程序设计 Linux开发步骤 Linux开发环境的选择 交叉编译过程 GNU工具的使用及开发流程 Linux常用命令 2 开发环境的建立 在进行项目开发前 首先要做的就是搭建一套基于Linux操作系统的应用开发环境 一般由目标板和宿主机所构成 目标板用于运行操作系统和系统应用软件 而目标板所用到的操作系统的内核编译 应用程序的开发和调试则需要通过宿主机来完成 开发环境对硬件没有特殊的要求 但是为了双方之间建立连接关系 关键的几种接口电路如串口 以太网接口和USB接口是必不可少的 用于开发和调试目标板上所用到的操作系统 应用程序等所有软件 这种在宿主机上开发程序 在目标板上运行程序的方式 通常就叫做交叉开发 3 开发环境的建立 4 目标板 Target 可以是嵌入式应用软件的实际运行环境 当然也可以是替代实际环境的仿真系统 如软件模拟器 宿主机 Host 通过串口 网络连接或调试接口 如JTAG仿真器 与目标机通信 宿主机的软硬件资源比较丰富 其操作系统主要有Windows和Linux两种 其上用于开发程序的那套软件工具 通常叫做开发工具链 开发环境的建立 5 嵌入式Linux的组成 最基本的嵌入式Linux系统需要3个基本元素 系统引导程序 用于完成机器加电后的系统定位引导 Linux系统内核 为嵌入式应用提供一个软件环境 为应用程序完成基本的底层资源管理工作 初始化过程 完成基本的初始化 为使这个最小嵌入式系统具有一定的实用性 还需加上硬件的驱动程序及 个或几个应用进程以提供必要的应用功能支持 如果应用比较复杂 可能还需要添加一个可以在ROM或RAM中使用的文件系统 TCP IP网络协议栈等 在PDA领域 还需要加上 个GUl支持 6 Linux开发步骤 Linux操作系统作为一种多任务 稳定可靠 内核可裁剪的系统 是开发嵌入式软硬件产品的优秀软件平台 嵌入式Linux是一种开放源码 软实时 多任务的嵌入式操作系统 通常它是在标准Linux的基础上针对嵌入式系统进行裁剪和优化后形成的 裁剪和优化后的Linux体积更小 性能更加稳定 而且源代码本身是免费的 这将大大减少开发商的成本 更具市场竞争力具体进行Linux开发的步骤如下 BOOTLOADER开发 Linux开发环境建立 Linux内核移植 应用程序开发 7 嵌入式Linux的开发环境 个人用Linux开发嵌入式应用程序 可以在自己的PC机上安装一套Linux操作系统 使用Linux中的XWindows打开若干个窗口进行编译 下载和调试等 当多名工程师共同来开发一个系统时 可以用1台PC机运行Linux作为服务器 每个开发工程师都通过局域网用Telnet登录到这台服务器上 被开发的目标板也挂在网上 然后在服务器的Linux环境下用GNUgcc编译成生目标代码 再用FTP传回到自己的PC机上 最后通过串口或网络下载到目标机上即可完成整个嵌入式系统的开发 8 交叉编译环境的建立 所谓交叉编译 就是在一个平台上生成可以在另一个平台上执行的代码 采用交叉编译的主要原因在于 多数嵌入式目标机不能提供足够的资源供编译过程使用 因而只好将编译工作转移到高性能的宿主机中进行 交叉编译环境是一个由编译器 连接器和解释器组成的综合开发环境 交叉编译工具主要包括针对目标系统的编译器gcc 目标系统的二进制工具binutils 目标系统的标准c库glibc和目标系统的Linux内核头文件 9 GNU交叉编译 Linux采用GNU交叉编译器 GNU的交叉编译器 包括以下组件 1 gcc交叉编译器 即在宿主机上开发编译目标上可运行的二进制文件 2 binutils辅助工具 包括objdump objcopy等 3 gdb调试器 对于ARM可以采用如下两个版本的编译器 arm elf arm linux 10 arm elf 交叉编译器 arm elf gcc arm elf ld arm elf as arm elf objdump arm elf objcopy arm elf gdb 11 arm linux 交叉编译器 arm linux gcc arm linux ld arm linux as arm linux objdump arm linux objcopy arm linux gdb 12 选择Linux开发环境 Windows环境 Cygwin Windows环境 VMWare虚拟机 安装RedHat9 0 Linux环境 推荐RedHat9 0 单机模式 一台计算机 双机模式 两台计算机 Windows Linux 13 在linux环境下进行Linux开发 必须采用支持GDB的调试器 如ADT1000A 才能进行调试 否则只能通过BOOTLOADER进行简单的程序烧写运行等 调试信息的打印可以通过串口完成 使用linux下的minicom超级终端程序 类似于Windows上的超级终端工具 接收并显示目标板传送的打印信息 Linux程序的编辑 编译和调试都是在Linux环境下进行的 Linux串口驱动完成后 可以通过内核打印函数printk向串口打印信息 这是Linux内核调试过程中最有效的手段 14 在Windows Cygwin环境下进行Linux开发 Linux内核配置和编译等在Cygwin环境下运行 程序编辑和调试都在Windows环境下进行 必须采用支持Windows下进行linux调试的调试器 如ADT1000A 才能进行调试 否则只能通过BOOTLOADER进行简单的程序烧写运行等 调试信息的打印可以通过串口完成 使用Windows上的超级终端工具接收并显示目标板传送的打印信息 Cygwin是运行于Windows中的一个应用程序 它可以使得Linux环境下的应用程序可以在Cygwin环境下进行编译 即可以在Windows进行编译 15 在Windows VMWare虚拟机环境下进行Linux开发 如果需要使用只支持Windows环境下调试的调试器 可以通过在VMWare中安装linux虚拟机 在该虚拟机中进行编辑 编译Linux 然后通过网络 ftp nfs ssh 等手段传送到Windows中 进行调试 这样编译和调试可以分别在linux和windows环境下但是是在一台电脑中完成 它的缺点是系统要求较高 运行速度慢 也可以在两台电脑中分别安装linux和windows 分别实现编译和调试 VMWare是运行于Windows中的一个应用程序 是一个虚拟机 可以在其上安装多个操作系统 相当于在Windows上安装一个虚拟的操作系统 16 17 交叉编译过程 在Linux交叉编译环境下 整个编译过程大体上可以分为以下几个步骤 编译binutils运行configure文件 并使用 prefix PREFIX参数指定安装路径 使用 target arm linux参数指定目标机类型 然后执行makeinstall 配置Linux内核头文件执行makemrproper进行清理工作 然后执行makeconfigARCH arm 或makemenuconfig xconfigARCH arm 进行配置 一定要在命令行中使用ARCH arm指定CPU架构 因为默认架构为主机的CPU架构 18 交叉编译过程 第一次编译gcc这一步执行makeinstall 生成一个最简单的gcc 由于编译整个gcc需要目标机的glibc库 而它在刚开始时还不存在 因此需要首先生成一个最简单的gcc 它只需要具备编译目标机glibc库的能力即可 交叉编译glibc这一步通过执行configure和makeinstall来对glibc库进行交叉编译 configure的运行参数如下 CC arm linux gcc configure prefix PREFIX arm linux host arm linux enable add ons 19 交叉编译过程 第二编译gcc首先运行configure 参数设置为 prefix PREFIX target arm linux enable languages c c 接着运行makeinstall 这样整个交叉编译环境就生成了 建立一个交叉编译工具链是一个相当复杂的过程 为了节省时间 可以直接从网上下载一些已编译好的交叉编译工具链 如arm linux toolchains tgz 20 Linux开发工具的使用 运行于Linux操作系统下的自由软件GNUgcc编译器 不仅可以编译Linux操作系统下运行的应用程序 还可以编译Linux内核本身 甚至可以交叉编译运行于其他CPU上的程序 因此 在进行嵌入式系统应用程序开发时GNUgcc得到了广泛的应用 GNU开发工具的主要缺点是采用命令行方式 用户掌握和使用起来比较困难 不如基于Windows系统的开发工具易用 可一旦掌握了其用法就可以非常方便地进行项目开发 GNU的操作系统和开发工具都是免费的 只要遵循GPL协议 任何人都可以随意获取并使用 21 Linux开发工具GNU的使用 GNU提供的编译工具包括汇编器as C编译器gcc C 编译器g 链接器ld和二进制转换工具objcopy等 其中基于ARM平台的工具分别为 arm linux as arm linux gcc arm linux g arm linux ld和arm linux objcopy Linux下的GNU调试工具主要有gdb gdbserver和kgdb 其中gdb和gdbserver可完成对目标板上Linux应用程序的远程调试 22 GNU工具的开发流程 在Linux操作系统下使用GNU工具开发程序的流程主要有以下几个步骤 编写C C 语言或汇编语言源程序 用gcc或g 生成目标文件 编写链接脚本文件 用链接器生成最终目标文件 elf格式 用二进制转换工具生成可下载的二进制代码 23 gcc编译器的使用 最初gcc的意思是GNUCCompiler 即只作为C程序语言的编译器 现在 经过多年的发展 gcc已经变成了GNUCompilerCollection 即GNU编译器家族的意思 除支持C语言以外 还支持Ada语言 C 语言 Java语言等多种语言 gcc是GNU组织提供的免费C编译器 大多数Linux版本都默认安装了这种编译器 24 gcc编译器的用法 Gcc的使用格式为 gcc option file 其中option是以 开始的各种选项 file是要编译的文件名 在使用gcc进行编译时 必须要给出必要的选项和文件名 Gcc的整个编译过程分为预处理 编译 汇编和链接四个过程 25 gcc编译器的用法 gcc编译器的常用选项有 o 表示要求编译器生成指定文件名的可执行文件 c 表示只要求编译器进行编译 而不要进行链接 生成以源文件的文件名命名但把其后缀由 c或 cc变成 o的目标文件 g 要求编译器在编译的时候提供以后对程序进行调试的信息 E 表示编译器对源文件只进行预处理就停止 而不做编译 汇编和链接 S 表示编译器只进行编译 而不做汇编和链接 O 是编译器对程序提供的编译优化选项 以提高执行效率 Wall 指定产生全部的警告信息 26 gcc编译器的用法 例 给出以下Hello源程序voidmain printf Hellotheworld n 要编译这个程序 只需输入以下命令即可完成 gcc ohellohello c其中gcc表示用gcc来编译源程序 o选项表示要求编译器生成可执行文件的文件名 hello c是要编译的源程序文件 27 Makefile文件和Make命令 Linux内核的配置系统由以下三个部分组成 Makefile 用于定义Linux内核的编译规则 配置文件 config in 给用户提供配置选择的功能 配置工具 包括配置命令解释器和配置用户界面等 其中 Makefile文件描述了目标文件之间的依赖关系 以及指定编译过程中使用的工具 即根据配置的情况 构造出需要编译的源文件列表 然后分别编译 并把目标代码链接到一起 最终形成Linux内核的二进制文件 Makefile带来的好处就是自动化编译 批处理 在需要编译时只需要一个Make命令即可自动完成 极大的提高了软件开发的效率 28 Makefile文件和Make命令 在Linux内核中 与Makefile直接相关的文件有 Makefile 顶层Makefile 是整个内核配置 编译的总体控制文件 Config 内核配置文件 包含由用户选择的配置选项 用来存放内核配置后的结果 Arch Makefile 位于各CPU体系目录下的Makefile 各子目录下的Makefile 负责所在子目录下源代码的管理 Rules make 规则文件 被所有的Makefile使用 顶层Makefile有两个主要任务 一是产生vmlinux文件 二是产生内核模块 module 29 Makefile文件和Make命令 Makefile中的变量顶层Makefile定义并向环境中输出了很多变量 为各个子目录下的Makefile传递一些信息 具体常用变量如下 版本信息 用来定义当前内核的版本 CPU体系结构 用于定义目标CPU的体系结构 路径信息 用于定义内核等源代码所在的目录 内核组成信息 包括头文件 内核文件等 编译信息 用于定义交叉编译的环境 配置变量config 用来说明用户配置的结果 30 Makefile文件和Make命令 Rules make变量Rules make定义了所有Makefile共用的编译规则 Linux把所有共用的编译规则统一放置到Rules make中 并在各自的Makefile中通过语句 includeRules make 包含Rules make 这样可避免多个Makefile中重复这些规则 子目录Makefile用来控制本级目录下源代码的编译规则 MakeMake是一个解释Makefile中指令的命令工具 Make命令执行时 需要一个Makefile文件 以告诉make命令怎么去编译和链接程序 31 配置文件 除了Makefile的编写 另外一个重要的工作就是把新功能加入到Linux的配置选项中 并提供此项功能的说明 让用户有机会选择此项功能 这些工作需要在config in文件中用配置语言编写配置脚本来实现 在Linux内核中 配置命令有多种方式 Makeconfig 配置命令 scripts configure 解释脚本 Makeoldconfigscripts configureMakemenuconfigscripts menuconfigMakexconfigscripts tkparse以字符界面配置Makeconfig为例 其配置过程为顶层Makefile调用scripts configure按照arch arm config in来进行配置 命令执行完后产生配置文件 config 其中保存着有关配置信息 32 配置文件 配置语言顶层菜单mainmenu name prompt prompt 用于指定本CONFIG语言文件顶层的名字 其中 prompt 是一串提示符 询问语句Bool prompt symbol hex prompt symbol word int prompt symbol word string prompt symbol word tristate prompt symbol 询问语句首先显示一串提示符 prompt 等待用户输入 并把输入的结果赋给 symbol 所代表的配置变量 33 配置文件 定义语句define bool symbol word 定义语句显式的给配置变量 symbol 赋值 word 依赖语句dep bool prompt symbol dep 依赖语句与询问语句一样 也是定义新的变量 不同的是 symbol 的取值将依赖于配置变量列表 dep 选择语句choice prompt work word 选择语句主要用于给出一串选择列表 以供用户选择 If语句菜单块Source语句 34 启动加载程序bootloader SRAM SDRAM等存储设备属于易失性的存储器 掉电以后其中的内容会全部丢失 所以必须把操作系统的内核镜像存放在Flash等不易失性的存储介质上 而操作系统在运行时 需要动态的创建一些如数据段 堆栈 页表 针对使用虚拟地址的操作系统 等内容 所以需要在RAM中运行操作系统 因此 这就需要一个引导程序把操作系统的内核镜像从Flash存储器拷贝到RAM中 然后再从RAM中执行操作系统的内核 Bootloader就是可以完成这样一种功能的程序 35 启动加载程序bootloader 从本质上来讲 bootloader不属于操作系统内核 它采用汇编语言编写 因此针对不同的CPU体系结构 这一部分代码不具有可移植性 在移植操作系统时 这部分代码必须加以改写 具体来讲 bootloader在系统启动时主要完成以下几项工作 将操作系统内核从Flash拷贝到SDRAM中 如果是压缩格式的内核 还要将之解压缩 改写系统的memorymap 原先flash起始地址映射为0地址 这时需要将RAM的起始地址映射为0 设置堆栈指针并将bss段清零 将来执行C语言程序和调用子函数时要用到 改变pc值 使得CPU开始执行真正的操作系统内核 36 运行操作系统内核 bootloader程序执行完上述的各项工作后 通过一条跳转指令 转而执行init目录下C语言源文件main c中的函数start kernel 因为在此之前bootloader已经创建好一个初始化环境 C函数可以开始执行了 37 Linux操作系统移植 在交叉编译环境和BootLoader建立后 下面的工作就是对操作系统的移植 对于系统移植 Linux系统实际上是由两个比较独立的部分组成 即内核部分和系统部分 具体过程如下 系统启动时 加载程序 BootLoader 首先将Linux的部分内核调入内存 并将控制权交给内存中Linux内核的第一行代码 加载程序的工作就算完成了 然后Linux内核再将剩余的部分全部加载到内存 初始化所有的设备 在内存中建立好所需的数据结构 这部分工作属于内核部分 内核加载设备并启动init守护进程 init守护进程再根据配置文件加载文件系统 配置网络 服务进程等 这部分工作属于系统部分 即内核部分的工作是初始化并控制大部分硬件设备 为内存管理 进程管理等工作作好准备 而系统部分的工作是加载必需的设备 配置各种环境以便用户可以使用整个系统 38 Linux内核移植 Linux内核的移植可以分为板级移植和片级移植 对于Linux发行版本中已经支持的CPU通常只需要针对板级硬件进行适当的修改即可 这种移植叫做板级移植 而对于Linux发行版本中没有支持的CPU则需要添加相应CPU的内核移植 这种移植叫做片级移植 片级移植相对板级移植来说要复杂许多 本系统采用的Linux发行版本中已经包含S3C2410XARM920T处理器的移植包 因此 只需要在其上进行Linux板级移植的基本过程和方法 39 Linux内核的目录结构 40 Linux内核的arch目录 与架构和平台相关的源代码都放在arch目录下 对于ARM的Linux 包含于arch目录下的arm子目录中 41 Linux内核的arch目录 当使用压缩核心时 boot目录下包含压缩和解压核心的源代码和Makefile文件 kernel目录的entry armv S中为未压缩内核的起始执行文件 内核从其第一条指令处执行 vmlinux lds文件为核心的连接脚本文件 压缩核心解压后必须解压缩到该文件指定的地址 42 Linux内核移植 配置内核 编译内核 下载 运行 调试内核 43 配置Linux内核 makeconfig makemenuconfig makexconfig 44 makeconfig 45 makemenuconfig 46 makexconfig 47 Linux常用配置选项 系统及其存储器配置 网络支持 显示器支持 触摸屏支持 48 系统及其存储器配置 在 SystemType 菜单中中进行配置 选择系统类型处理器型号 选择处理器其它特性 USB支持等 49 网络支持 在 Networkingoptions 以及 Networkdevicesupport 中进行配置 选择支持TCP IP协议 50 网络支持 在 Networkdevicesupport 配置中 添加选项 Networkdevicesupport 并在 Ethernet 10or100Mbit 中选择 OtherISAcards 如下图所示选择NE2000 NE1000support 采用RTL8019网卡芯片 为NE2000兼容网卡芯片 因此 选择该网卡 51 显示器支持 在 Characterdevices 以及 Consoledrivers 中进行配置 在 Characterdevices 配置中 添加选项 Virtualterminal 配置 如下图所示 Virtualterminal支持 52 显示器支持 在 Consoledrivers 中添加 SupportFramebufferdevices 配置 采用256色STN显示器 因此必须选择8bpp支持 53 触摸屏支持 在 Characterdevices 的 SupportS3C2410TouchScreen 子菜单中进行配置 选择s3c2410触摸屏支持 54 编译Linux内核 建立依赖关系 makedep 编译内核 make编译内核makezImage编译压缩核心 zImage 编译生成地Linux映像文件zImage通常保存在arch arm boot 目录下 创建内核模块 编译Linux内核大体上需要三个步骤 即建立内核依赖关系 创建内核镜像和创建内核模块 55 下载 运行和调试内核 通过调试器下载内核并运行 通过BOOTLOADER下载内核到SDRAM中运行 通过BOOTLOADER将内核烧写到FLASH中 然后运行Linux 56 Linux调试手段 在Linux开发中 由于可能没有标准键盘和显示器支持 因此 通常通过串口将显示信息发送到主机 由主机端超级终端工具接收 以完成显示功能 同时在超级终端中可以输入数据 然后由Linux接收 以完成标准键盘功能 调试过程中也可以通过串口将调试信息打印到超级终端 这是Linux最有效和最简单的方法 57 Linux内核移植主要过程1 对于板级移植 内核移植主要包括如下几个部分 内核配置 包括板级包配置 如S3C44B0X MBA44 体系结构相关代码修改 根据板级包的配置 修改相应的体系结构相关代码 包括 压缩核心启动代码 linux arch arm boot 内核启动代码 linux arch arm kernel 板级相关代码 linux arch arm mach s3c2410 连接脚本核心连接脚本 linux arch arm vmlinux lds压缩核心连接脚本 linux arch arm boot compressed linux lds 58 Linux内核移植主要过程2 加载文件系统ramdisk 编写驱动程序驱动程序目录 linux drivers 网卡驱动程序 linux drivers net ne cLCD驱动程序 linux drivers video s3c2410fb c触摸屏驱动程序 linux drivers char s3c2410 ts c 59 Linux启动过程1 核心打印信息 内核命令行 存储器 60 Linux启动过程2 IIC总线初始化 FrameBuffer显示初始化 61 Linux启动过程3 Linux控制台 62 Linux内核移植的若干问题 源程序阅读问题1 Linux内核源代码非常多 且结构复杂 Linux内核有接近10000个文件 4000000行代码 因此 阅读Linux时必须借助一些工具 Sourceinsight Ultraedit等 Linux内核使用GNUC 它在ANSIC基础上进行了一些扩充 因此在许多编程习惯上与ANSIC不同 大量使用宏定义 且许多宏定义非常复杂 这也在一定程度上增加了难度 63 Linux内核移植的若干问题 源程序阅读问题2 Linux中并不是所有代码都编译进去 对于一个体系结构 只有很少部分的代码参与编译 因此 必须掌握Linux发布中各目录的意义才能进一步清楚是否参与编译 还可以通过查看 o文件的方式查看当前参与编译的是哪个文件 通常xxx c文件生成的目标文件为xxx o 只有生成了 o的文件才参与编译 注意 这适合于大部分情况 但是不是绝对的 Linux中大量使用条件编译 阅读代码时需要弄清楚 到底哪部分代码参与编译 ifdefxxx elif endif 64 Linux内核移植的若干问题 GNUC结构体初始化 结构体声明 ANSIC结构体初始化 必须按顺序 GNUC结构体初始化 无需按顺序 65 Linux应用程序设计 编写程序 编写Makefile文件 编译 运行 66 编写应用程序 在编写应用程序之前 应首先建立一个工作目录 如 tmp 选用文本编辑器Vi编写源程序代码hello c如下 includeintmain void printf Hellotheworld n return0 若在宿主机中编译并运行hello程序 则使用如下命令gcc ohellohello c若编译在目标机上运行的hello程序 则使用如下命令arm linux gcc ohellohello c 67 编写Makefile文件 生成的执行文件和链接过程中的目标文件 68 Linux应用程序的运行 应用程序运行可以采用如下两种方式 在Linux内核启动起来 并且有办法从主机获取文件时 可以在Linux控制台直接从主机获取编译后的应用程序 可以通过ftp等方式传输 也可以在编译应用程序后将该应用程序拷贝到ramdisk中 然后重新制作ramdisk 并更新ramdisk文件系统 此时新的程序将在文件系统中 69 Linux应用程序的运行 重新编译内核时 通常将应用程序添加到Linux文件系统的bin目录 该目录有全局路径 且该文件应该具有执行属性 可以通过如下命令修改 chmod777leddemo在新内核启动后 直接在命令行输入文件名即可运行 当直接在Linux控制台中从主机上获取应用程序时 必须保存到可写的位置 且通过如下命令执行该程序 leddemo 70 配置Linux应用程序启动后自动运行 如果需要在系统启动以后自动运行helloworld程序 需要编辑ramdisk中的启动脚本文件 该文件为root rd etc init d rcS使用vi编辑器编辑 在该文
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 机床滚珠丝杠副课程设计
- 新教材高中物理 第4章 本章优化总结教案 鲁科版必修第一册
- 九年级道德与法治下册 第一单元 我们共同的世界 第一课 同住地球村 第1框 开放互动的世界教案 新人教版
- 机器人齿轮课程设计
- 机器人有哪些课程设计
- 机器人假期特色课程设计
- 本科工作分配方案
- 2024至2030年直脚起毛针布项目投资价值分析报告
- 木栏杆基座修复施工方案
- 期货投资技术课程设计
- 肺结节诊治中国专家共识(2024年版)解读
- 单脚起跳、双脚落地
- 毛竹脚手架施工方案
- HXN5型机车常见故障处理指导书
- 水泵技术规格书精编版
- 中南大学学位证书样本扫描件WORD
- 头颈部体格检查评分标准(共3页)
- 多重中介模型及其应用
- 可分离变量的微分方程(8)课件
- 苏教版小学一年级数学上册期末试卷
- 火灾报警系统技术规范书
评论
0/150
提交评论