基于Cortex-A8 Android&Linux系统与应用开发

Size: px
Start display at page:

Download "基于Cortex-A8 Android&Linux系统与应用开发"

Transcription

1

2 安 全 提 示 非 常 感 谢 您 选 购 联 创 中 控 ( 北 京 ) 科 技 有 限 公 司 的 产 品, 在 首 先 打 开 包 装 箱 后 请 依 据 产 品 清 单 检 查 配 件, 若 发 现 产 品 主 配 件 有 损 坏 或 缺 失, 请 尽 快 与 您 的 经 销 商 或 技 术 支 持 联 络 产 品 使 用 前, 务 必 先 阅 读 本 手 册 实 验 平 台 须 使 用 配 套 的 电 源 适 配 器 接 触 实 验 平 台 主 板 前, 应 将 手 先 置 于 接 地 金 属 上 一 会 儿, 以 释 放 身 体 静 电 为 避 免 人 体 被 点 击 或 产 品 被 损 坏, 在 每 次 对 实 验 平 台 主 板 扩 展 模 块 进 行 插 拔 或 者 重 新 配 置 时, 须 先 关 闭 交 流 电 源 或 者 将 配 套 的 电 源 适 配 器 拔 除 当 您 需 连 接 或 拔 除 设 备 前, 须 确 定 所 有 的 电 源 线 事 先 已 被 拔 除 设 备 严 禁 在 高 温 高 压 强 磁 场 等 恶 劣 环 境 下 工 作 设 备 在 使 用 过 程 中 出 现 异 常 情 况, 请 及 时 找 专 业 人 员 处 理 文 档 约 定 文 档 格 式 约 定 如 下 : 1) 文 中 涉 及 到 终 端 信 息 时 : 超 级 终 端 提 示 符 为 # : checking mode for fastboot... Hit any key to stop autoboot: 0 x210 # nand scrub 电 脑 ubuntu 系 统 的 终 端 提 示 符 为 $ : $ sudo apt-get install subversion $ sudo apt-get install libapache2-svn 用 户 输 入 用 粗 体 表 示, 终 端 打 印 输 入 使 用 默 认 字 体 ; 2) 注 释 说 明 使 用 #, 且 为 粗 体 : Really scrub this NAND flash? <y/n> # 此 处 提 示 从 PC 输 入 y - 2 -

3 目 录 第 一 章 Android 应 用 开 发 环 境 ADT 的 安 装 与 配 置 创 建 第 一 个 应 用 程 序 导 入 Android 应 用 项 目 第 二 章 程 序 设 计 基 础 Android 程 序 框 架 Android Java 基 础 程 序 生 命 周 期 程 序 调 试 第 三 章 用 户 界 面 开 发 用 户 界 面 基 础 界 面 布 局 界 面 控 件 菜 单 界 面 事 件 第 四 章 组 件 间 通 信 Intent 对 象 及 其 属 性 系 统 标 准 ActivityAction 应 用 Intent 过 滤 器 广 播 信 息 第 五 章 数 据 存 储 与 访 问 简 单 存 储 文 件 存 储 数 据 库 存 储 数 据 共 享

4 第 六 章 多 媒 体 开 发 在 窗 体 布 局 上 -VideoView 音 频 及 视 频 播 放 -MediaPlayer 音 / 视 频 的 录 制 Camera 照 相 第 七 章 定 位 与 地 图 位 置 服 务 Google 地 图 应 用 第 八 章 Android 中 的 图 形 图 像 在 Android 中 访 问 图 片 Android 中 的 动 画 动 态 图 形 绘 制 图 形 特 效 第 九 章 Android 网 络 编 程 Apache 接 口 HTTP 通 信 Socket 通 信 第 十 章 Linux 操 作 系 统 基 础 ZEmberOS 操 作 系 统 安 装 ZEmberOS 基 本 使 用 Linux 常 用 操 作 命 令 Vi 编 辑 器 的 使 用 GCC 编 译 器 Makefile 第 十 一 章 Android&Linux 系 统 移 植 构 建 交 叉 编 译 环 境 编 译 脚 本 分 析 uboot 启 动 代 码 解 析

5 11.4 Linux 系 统 内 核 解 析 Android 系 统 解 析 构 建 基 本 文 件 系 统 NFS 网 络 文 件 系 统 第 十 二 章 linux 应 用 程 序 开 发 Helloworld 入 门 文 件 操 作 实 验 进 程 控 制 实 验 线 程 控 制 实 验 计 时 器 实 验 TCP 实 验 Webserver 实 验 UDP 实 验 网 络 服 务 器 Boa 实 验 Madplay 实 验 SQLite 数 据 库 移 植 实 验 第 十 三 章 linux 驱 动 程 序 开 发 Linux 简 单 字 符 驱 动 GPIO 驱 动 设 计 -LED 实 验 按 键 驱 动 设 计 实 验 串 口 通 信 实 验 LCD 显 示 实 验 触 摸 屏 采 集 实 验 SD 卡 存 储 实 验 以 太 网 实 验 WIFI 实 验 蓝 牙 实 验 摄 像 头 驱 动 实 验 GPS 实 验

6 13.13 GSM 显 示 实 验 第 十 四 章 嵌 入 式 GUI 设 计 实 验 主 机 编 译 Qt 移 植 Qt4.8 到 硬 件 平 台 Qt Creator 开 发 应 用 程 序 Qt Creator 开 发 Led 控 制 实 验 第 十 五 章 Android Ndk 开 发 Ndk 开 发 基 础 搭 建 Ndk 编 译 环 境 Ndk 开 发 LED 实 例 Ndk 开 发 串 口 实 例 第 十 六 章 Android 硬 件 接 口 按 键 / 键 盘 移 植 存 储 设 备 移 植 -SD 卡 WIFI 设 备 移 植 GPS 设 备 移 植 蓝 牙 设 备 移 植 摄 像 头 设 备 移 植 电 话 ril 层 移 植

7 第 一 章 Android 应 用 开 发 环 境 本 章 节 主 要 介 绍 如 何 快 速 进 行 Android 应 用 程 序 的 开 发, 包 括 Android Developer Tools 的 安 装 与 配 置,Android 应 用 工 程 的 创 建,Android 应 用 程 序 的 运 行 等 1.1 ADT 的 安 装 与 配 置 实 验 目 的 了 解 Android 应 用 编 程 所 需 要 的 工 具 ; 掌 握 Android 应 用 环 境 的 安 装 与 配 置 ; 掌 握 Android 模 拟 器 的 建 立 及 运 行 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 Android 应 用 是 基 于 JAVA 语 言 开 发, 主 要 是 采 用 Eclipses IDE 进 行 程 序 的 开 发,Google 提 供 了 完 整 的 基 于 Eclipses IDE 的 应 用 开 发 环 境, 主 要 涉 及 的 软 件 包 括 : JDK 1.6:JAVA 开 发 包, 包 括 了 Java 运 行 环 境 Java 工 具 和 Java 基 础 类 库 ; Eclipse-SDK: 一 款 流 行 的 开 放 源 代 码 的 基 于 Java 的 可 扩 展 实 验 平 台 ; Android-sdk:Android 应 用 开 发 工 具 包, 是 Android 特 定 的 软 件 包 软 件 框 架 硬 件 平 台 操 作 系 统 等 建 立 应 用 软 件 的 开 发 工 具 的 集 合 ; ADT 插 件 :Google 开 发 的 基 于 Eclipse IDE 的 Android 软 件 开 发 插 件 目 前 可 以 直 接 在 Android 官 网 直 接 下 载 集 成 所 有 必 须 工 具 的 软 件 合 集 包 :adt- bundle-windows, 实 验 平 台 出 厂 光 盘 内 路 径 :DISK-S210xA80\04- 常 用 工 具 \Android\adt-bundle-windows.zip - 7 -

8 安 装 完 Android 开 发 环 境 后, 可 以 通 过 SDK 内 提 供 的 模 拟 器 创 建 Android 模 拟 器 AVD,AVD 可 以 运 行 大 部 分 的 Android 应 用 程 序, 在 功 能 要 求 不 高 及 不 考 虑 运 行 效 率 的 情 况 下, 可 以 进 行 Android 应 用 程 序 的 开 发 图 Android 模 拟 器 实 验 步 骤 ADT 环 境 的 安 装 与 配 置 : 下 面 将 介 绍 ADT 环 境 的 安 装 及 配 置 : 1) 安 装 JAVA SDK(DISK-S210xA80\04- 常 用 工 具 \Android\jdk-6u33-windows-i586.exe); 2) 安 装 Android 开 发 工 具, 解 压 缩 adt-bundle-windows.zip 到 任 意 目 录 即 可, 比 如 D 盘 ; 3) 设 置 调 试 工 具 环 境 变 量 : 右 键 单 击 计 算 机 -> 属 性 -> 高 级 系 统 设 置 -> 环 境 变 量, 编 辑 系 统 变 量 中 的 path 变 量 ( 根 据 程 序 adt-bundle-windows 的 位 置 来 设 置 ), 在 后 面 添 加 : ;D:\adt-bundle-windows\sdk\tools;D:\adt-bundle-windows\sdk\platform-tools; 4) 检 测 ADB 环 境 设 置 正 确 与 否, 在 cmd( 开 始 -> 所 有 程 序 -> 附 件 -> 命 令 提 示 符 ) 终 端 输 入 以 下 命 令, 查 看 信 息 : C:\Users\lusi> adb version Android Debug Bridge version 这 样, 整 个 Android 应 用 开 发 环 境 就 安 装 配 置 好 了, 可 以 运 行 Eclipse 工 具 (D:\adt-bundlewindows\eclipse-x86\eclipse.exe) 进 行 应 用 开 发 了 - 8 -

9 图 启 动 eclipse Android 模 拟 器 AVD 的 创 建 : 下 面 将 介 绍 ADT 环 境 的 安 装 及 配 置 : 1) 运 行 Eclipse IDE, 依 次 点 击 菜 单 栏 的 Windows-> AVD Manager, 出 现 以 下 界 面 : 图 启 动 AVD Manager 2) 进 入 到 Device Definitions 选 项 卡, 可 以 看 到 各 种 Android 设 备 的 模 拟 器 定 义, 同 时 可 以 点 击 右 侧 按 钮 New Devices 创 建 自 定 义 的 模 拟 器 配 置 : 图 AVD 列 表 - 9 -

10 按 照 下 图 进 行 设 置 然 后 点 击 Create Device 即 添 加 了 自 定 义 的 模 拟 器 s210xa80 配 置 : Name: s210xa80 Size: normal Screen Size: 8 Screen Ratio: long Resolution: 1024 x 768 Density: hdpi Sensors: 全 选 Buttons: Hardware Cameras: Rear Device States: 默 认 Input: 勾 选 Keyboard DPad RAM: 512 MiB 图 建 立 s210xa80 模 拟 器 配 置 3) 返 回 到 图 Android Virtual Devices 选 项 卡, 点 击 右 上 角 的 New 按 钮 新 建 模 拟 器, 并 按 照 下 图 进 行 设 置 模 拟 器 参 数 : AVD Name: s210xa80 Device: s210xa80(1024 x 768:hdpi) Target: Android API Level 9 CPU/ABI: ARM(armeabi) Keyboard: 勾 选 Skin: 勾 选 Front Camera: None Back Camera: None Memory Options: RAM: 512 Internal Storage: 200 MiB SD Card: 空 VM Heap:32 图 建 立 s210xa80 模 拟 器

11 4) 模 拟 器 创 建 完 成 后, 可 以 在 图 Android Virtual Devices 选 项 卡 窗 口 看 到 创 建 的 模 拟 器 列 表, 其 中 s210xa80 即 为 创 建 的 模 拟 器 设 备 : 图 建 立 s210xa80 模 拟 器 4) 选 中 s210xa80 模 拟 器 设 备, 点 击 右 侧 栏 Start 按 钮, 启 动 模 拟 器, 弹 出 的 Launch Options 菜 单, 可 以 勾 选 Scale display to real size 选 项, 然 后 设 置 Screen Size(in) 为 7, 即 可 启 动 一 个 尺 寸 合 适 的 Android 模 拟 器 设 备 : 图 运 行 模 拟 器 设 备

12 为 了 避 免 每 次 模 拟 器 漫 长 的 启 动, 在 运 行 Android 程 序 后, 不 要 关 闭 模 拟 器 1.2 创 建 第 一 个 应 用 程 序 实 验 目 的 学 习 使 用 Android ADT 工 具 创 建 应 用 工 程 ; 了 解 Android ADT 工 具 工 程 配 置 选 项 ; 学 习 Android 应 用 工 程 编 译 及 运 行 过 程 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT 实 验 原 理 Android 应 用 是 基 于 JAVA 语 言 开 发, 主 要 是 采 用 Eclipses IDE 进 行 程 序 的 开 发,Android Developer Tools 包 含 了 Android 应 用 开 发 必 备 的 Eclipse 插 件 本 实 验 将 通 过 一 个 简 单 HelloWorld 工 程 来 学 习 Android 应 用 程 序 的 开 发 流 程 实 验 步 骤 创 建 HelloWorld 工 程 : 下 面 将 介 绍 ADT 环 境 的 安 装 及 配 置 : 1) 打 开 Eclipse, 在 菜 单 栏 依 次 选 择 :File -> New -> Android Application Project:

13 图 新 建 Android 工 程 2) 弹 出 对 话 框 并 按 如 下 所 示 进 行 设 置 : 界 面 信 息 说 明 如 下 : Appication Name: HelloWorld Project Name: HelloWorld Package Name: com.example.helloworld Minimum Required SDK: API 8: Android 2.2(Froyo) Target SDK: API 9: Android 2.3(Gingerbread) Compile With: API 9: Android 2.3(Gingerbread) Theme: None # 应 用 程 序 的 名 称, 将 在 程 序 的 标 题 栏 显 示 # 工 程 的 名 称 # 包 名, 格 式 必 须 为 string1.string2 # 所 支 持 的 最 小 SDK 版 本 # 程 序 目 标 SDK 版 本 # 程 序 的 编 译 SDK 版 本, 一 般 与 Target SDK 一 致 图 新 建 Android 工 程

14 3) 设 置 完 毕 后, 连 续 选 择 Next, 直 到 Finish: 界 面 信 息 说 明 如 下 : Activity Name: HelloWorld # 第 一 个 Activity 名 称 Layout Name: main # 主 Layout 布 局 名 称 Navigation Type: None 图 新 建 Android 工 程 4) 工 程 建 立 完 成 后, 在 Eclipse 界 面 的 工 程 窗 口 将 显 示 工 程 树 状 结 构 : 图 新 建 Android 工 程

15 在 模 拟 器 运 行 HelloWorld 工 程 : 参 照 前 面 章 节 内 容 运 行 建 立 好 的 s210xa80 模 拟 器, 在 工 程 窗 口 选 择 HelloWorld, 右 键 依 次 选 择 Run As -> Android Application, 将 会 自 动 运 行 程 序 到 模 拟 器 中 : 图 在 模 拟 器 运 行 应 用 程 序 在 硬 件 平 台 运 行 HelloWorld 工 程 : 准 备 实 验 平 台, 连 接 电 源, 连 接 Mini USB 线 到 电 脑, 长 按 Power 按 键 启 动 Android 系 统, 系 统 启 动 完 成 后 解 锁 进 入 到 Android 主 界 面, 在 工 程 窗 口 选 择 HelloWorld, 右 键 依 次 选 择 Run As -> Android Application, 程 序 将 会 运 行 到 Android 设 备 中, 如 果 之 前 模 拟 器 设 备 也 是 运 行 状 态, 则 会 出 现 选 择 菜 单 :

16 图 选 择 Android 应 用 所 运 行 的 设 备 此 时 选 择 硬 件 设 备, 程 序 将 传 输 到 硬 件 平 台 运 行 : 图 在 硬 件 平 台 运 行 应 用 程 序 识 别 硬 件 设 备 需 要 安 装 USB 驱 动, 驱 动 文 件 位 于 :DISK-S210xA80\04- 常 用 工 具 \Android\usb_driver, 按 照 提 示 安 装 即 可

17 1.3 导 入 Android 应 用 项 目 实 验 目 的 掌 握 导 入 Android 应 用 项 目 到 Eclipse IDE 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT 实 验 原 理 Android 应 用 开 发 是 这 几 年 来 非 常 火 热 的 技 术, 市 场 上 出 现 大 量 的 相 关 专 业 书 籍, 同 时 提 供 了 许 多 Android 应 用 项 目 例 程, 这 些 应 用 项 目 可 以 给 我 们 学 习 带 来 很 大 的 便 捷 性 Eclipse IDE 工 程 的 管 理 方 式 比 较 特 别, 它 不 能 直 接 通 过 打 开 工 程 文 件 来 加 载 项 目, 需 要 通 过 导 入 的 功 能 加 载 到 IDE 中 在 Google 发 布 的 SDK 工 具 包 中 也 提 供 了 一 些 例 程, 本 实 验 将 导 入 其 中 一 个 例 子 到 Eclipse IDE 中 实 验 步 骤 下 面 将 介 绍 如 何 导 入 已 经 存 在 的 Android 工 程 到 Eclipse IDE: 1) 拷 贝 SDK 提 供 的 一 个 例 子 到 工 作 目 录, 比 如 :D:\adt-bundle-windows\sdk\samples\android-9\ Snake 工 程 ; 2) 打 开 Eclipse, 在 菜 单 栏 依 次 选 择 :File -> Import..., 弹 出 导 入 窗 口, 选 择 Android -> Existing Android Code Into Workspace 或 者 选 择 General -> Existing Project into Workspace:

18 图 选 择 导 入 已 经 存 在 的 工 程 3) 弹 出 新 的 窗 口,Root Directory 选 择 所 需 要 导 入 工 程 的 源 码 路 径, 选 择 好 后, 会 在 Projects 窗 体 内 显 示 可 添 加 的 工 程 项 目, 比 如 我 们 选 中 Snake 项 目, 点 击 Finish 完 成 工 程 的 导 入 : 图 设 置 所 需 要 导 入 的 工 程 4) 此 时 Snake 工 程 已 经 导 入 到 Eclipse IDE 的 项 目 浏 览 窗 口 :

19 图 Snake 工 程 导 入 成 功 5) 我 们 可 以 编 译 Snake 工 程 在 模 拟 器 运 行 : 图 模 拟 器 运 行 Snake 应 用

20 第 二 章 程 序 设 计 基 础 Android & linux 系 统 与 应 用 开 发 在 上 一 章 的 学 习 中, 我 们 了 解 了 Eclipse+ADT 的 开 发 流 程, 对 其 有 了 初 步 的 认 识 和 了 解 这 一 章 的 主 要 是 学 习 掌 握 进 行 Android 开 发 的 基 础 知 识, 这 也 是 进 行 Android 应 用 程 序 设 计 的 第 一 步 2.1 Android 程 序 框 架 实 验 目 的 了 解 HelloWorld.java 文 件 的 用 途 和 生 成 方 法 ; 了 解 R.java 文 件 的 用 途 和 生 成 方 法 ; 了 解 AndroidManifest.xml 文 件 的 用 途 ; 了 解 资 源 文 件 夹 中 一 些 常 量 的 定 义 ; 了 解 Android 应 用 开 发 中 的 重 要 模 块 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; Windows 7/Windows XP Android ADT 实 验 原 理 上 一 章 我 们 建 立 了 HelloWorld 工 程 项 目, 在 项 目 中, 所 有 的 代 码 是 由 ADT 插 件 自 动 生 成 的, 我 们 并 没 有 对 其 进 行 编 码, 也 没 有 对 其 框 架 进 行 分 析, 其 实 每 一 个 平 台 都 有 自 己 的 结 构 框 架 本 实 验 将 通 过 一 个 简 单 HelloWorld 工 程 来 学 习 Android 应 用 程 序 的 实 验 平 台 的 目 录 结 构 文 件 类 型 及 其 负 责 的 功 能 和 Android 平 台 的 main 方 法 剖 析 Android 项 目 框 架 在 建 立 HelloAndroid 程 序 的 过 程 中,ADT 会 自 动 建 立 一 些 目 录 和 文 件, 这 些 目 录 和 文 件 有 其 固 定 的 作 用, 有 的 允 许 修 改, 有 的 不 能 修 改

21 在 Package Explore 中,ADT 以 工 程 名 称 HelloWorld 作 为 根 目 录, 将 所 有 字 段 生 成 的 和 非 自 动 生 成 的 文 件 都 保 存 在 这 个 根 目 录 下 根 目 录 包 含 六 个 子 目 录 :src assets res bin libs 和 gen, 两 个 库 文 件 android.jar android.dependencies, 一 个 ic_launcher-web.png 文 件, 一 个 proguard-project.txt 文 件, 以 及 两 个 工 程 文 件 Androidmanifest.xml 和 project.properties src 目 录 是 源 代 码 目 录, 所 有 允 许 用 户 修 改 的 java 文 件 和 用 户 自 己 添 加 的 java 文 件 都 保 存 在 这 个 目 录 中 HelloWorld 工 程 建 立 初 期,ADT 根 据 用 户 在 工 程 向 导 中 的 Create Activity 选 项, 自 动 建 立 HelloWorld.java 文 件 HelloWorld.java 是 Android 工 程 向 导 根 据 Activity 名 称 创 建 的 java 文 件, 这 个 文 件 完 全 可 以 手 工 修 改 为 了 在 Android 系 统 上 显 示 图 形 界 面, 需 要 使 用 代 码 继 承 Activity 类, 并 在 oncreate() 函 数 中 声 明 需 要 显 示 的 内 容 assets : 包 含 应 用 程 序 需 要 使 用 到 的 视 频 与 音 频 文 件 bin 目 录 是 编 译 之 后 的 字 节 码 存 放 目 录 libs 目 录 用 来 放 第 三 方 jar 包 gen 目 录 是 1.5 版 本 新 增 的 目 录, 用 来 保 存 ADT 自 动 生 成 的 java 文 件, 例 如 R.java 或 AIDL 文 件 R.java 文 件 是 ADT 自 动 生 成 的 文 件, 包 含 对 drawable layout 和 values 目 录 内 的 资 源 的 引 用 指 针,Android 程 序 能 够 直 接 通 过 R 类 引 用 目 录 中 的 资 源 R.java 文 件 不 能 手 工 修 改, 如 果 向 资 源 目 录 中 增 加 或 删 除 了 资 源 文 件, 则 需 要 在 工 程 名 称 上 右 击, 选 择 Refresh 来 更 新 R.java 文 件 中 的 代 码 R 类 包 含 的 几 个 内 部 类, 分 别 与 资 源 类 型 相 对 应, 资 源 ID 便 保 存 在 这 些 内 部 类 中, 例 如 子 类 drawable 表 示 图 像 资 源, 内 部 的 静 态 变 量 icon 表 示 资 源 名 称, 其 资 源 ID 为 0x7f 一 般 情 况 下, 资 源 名 称 与 资 源 文 件 名 相 同 res 目 录 是 资 源 目 录, 有 七 个 子 目 录 用 来 保 存 Android 程 序 所 有 资 源 : drawabel-hdpi: 应 用 程 序 中 使 用 的 图 标 文 件, 高 分 辨 率 ; drawabel-ldpi: 应 用 程 序 中 使 用 的 图 标 文 件 低, 分 辨 率 ; drawabel-mdpi: 应 用 程 序 中 使 用 的 图 标 文 件, 中 分 辨 率 ;( 系 统 会 根 据 模 拟 器 的 分 辨 率 自 动 到 这 几 个 文 件 夹 中 去 寻 找 对 应 的 图 片 ); layout: 界 面 布 局 文 件 ; values: 保 存 文 件 颜 色 风 格 主 题 和 字 符 串 等 ; menu: 设 置 菜 单 属 性 在 HelloWorld 工 程 中,ADT 在 drawable 目 录 中 自 动 引 入 了 ic_launcher.png 文 件, 作 为

22 HelloAndroid 程 序 的 图 标 文 件 ; 在 layout 目 录 生 成 了 main.xml 文 件, 用 于 描 述 用 户 界 面 在 menu 目 录 生 成 了 main.xml 文 件, 用 于 设 置 菜 单 属 性 在 valuest 目 录 生 成 了 strings.xml 文 件, 用 于 定 义 字 符 串 资 源 proguard-project.txt 是 定 义 混 淆 器 project.properties 是 工 程 属 性 的 配 置 文 件 AndroidManifest.xml 是 XML 格 式 的 Android 程 序 声 明 文 件, 包 含 了 Android 系 统 运 行 Android 程 序 前 所 必 须 掌 握 的 重 要 信 息, 这 些 信 息 包 含 应 用 程 序 名 称 图 标 包 名 称 模 块 组 成 授 权 和 SDK 最 低 版 本 等, 而 且 每 个 Android 程 序 必 须 在 根 目 录 下 包 含 一 个 AndroidManifest.xml 文 件 AndroidManifest.xml 文 件 的 根 元 素 是 manifest, 包 含 了 xmlns:android package android:versioncode 和 android:versionname 共 4 个 属 性 : xmlns:android 定 义 了 Android 的 命 名 空 间, 值 为 package 定 义 了 应 用 程 序 的 包 名 称 ; android:versioncode 定 义 了 应 用 程 序 的 版 本 号, 是 一 个 整 数 值, 数 值 越 大 说 明 版 本 越 新, 但 仅 在 程 序 内 部 使 用, 并 不 提 供 给 应 用 程 序 的 使 用 者 ; android:versionname 定 义 了 应 用 程 序 的 版 本 名 称, 是 一 个 字 符 串, 仅 限 于 为 用 户 提 供 一 个 版 本 标 识 manifest 元 素 仅 能 包 含 一 个 application 元 素,application 元 素 中 能 够 声 明 Android 程 序 中 最 重 要 的 四 个 组 成 部 分, 包 括 Activity Service BroadcastReceiver 和 ContentProvider, 所 定 义 的 属 性 将 影 响 所 有 组 成 部 分 default.properties: 该 文 件 负 责 记 录 项 目 所 需 要 的 环 境 信 息, 如 Android 的 版 本 信 息 等 Android 应 用 解 析 Android 应 用 开 发 中 所 应 用 到 的 重 要 模 块 有 : Activity Intent Content Provider Service 并 非 所 有 的 Android 应 用 程 序 都 必 须 由 这 4 部 分 组 成, 它 可 以 根 据 开 发 者 需 求 来 进 行 组 合, 对 于 任 何 一 个 应 用 程 序 来 说, 都 必 须 在 AndroidManifest.mxl 文 件 中 申 明 使 用 到 的 模 块 Activity 一 个 程 序 一 般 由 多 个 Activity 组 成, 各 activities 之 间 关 系 很 松 散, 它 们 之 间 没 有 直 接 的 关 联 必 须 有 一 个 activity 被 指 定 为 主 activity, 它 是 程 序 启 动 时 首 先 显 示 的 界 面 每 个 activity 都 可 以 随 意 启 动 其 它 的 activity 每 当 一 个 activity 被 启 动, 则 前 一 个 activity 就 被 停 止 一 个 程 序 中 的 所 有 启 动 的 activity 都 被 放 在 一 个 栈 中, 所 以 被 停 止 的 activity 并 没 有 销 毁, 而 在 存 于 棧 中 新 启 动 的 activity 先 被 存 放 于 栈 中, 然 后 获 得 输 入 焦 点 在 当 前 活 动 的 activity 上 点 返 回 键, 它 被 从 棧 中 取 出, 然 后 销 毁, 然 后 上 一 个 activity 被 恢 复

23 当 一 个 activity 因 为 新 的 activity 启 动 而 被 停 止 时, 它 会 收 到 状 态 变 化 的 通 知, 这 样 的 变 化 有 多 个, 每 个 都 会 引 起 系 统 调 用 一 个 相 应 的 回 调 方 法 以 通 知 activity, 这 些 回 调 方 法 被 统 称 为 生 命 周 期 回 调 方 法 这 些 回 调 方 法 分 别 在 Activity 被 创 建 停 止 恢 复 销 毁 时 被 调 用 Intent 在 这 些 组 件 之 间 的 通 讯 中, 主 要 是 由 Intent 协 助 完 成 的 Intent 负 责 对 应 用 中 一 次 操 作 的 动 作 动 作 涉 及 数 据 附 加 数 据 进 行 描 述,Android 则 根 据 此 Intent 的 描 述, 负 责 找 到 对 应 的 组 件, 将 Intent 传 递 给 调 用 的 组 件, 并 完 成 组 件 的 调 用 因 此,Intent 在 这 里 起 着 一 个 媒 体 中 介 的 作 用, 专 门 提 供 组 件 互 相 调 用 的 相 关 信 息, 实 现 调 用 者 与 被 调 用 者 之 间 的 解 耦 Content Provider Content Provider 属 于 Android 应 用 程 序 的 组 件 之 一, 作 为 应 用 程 序 之 间 唯 一 的 共 享 数 据 的 途 径,Content Provider 主 要 的 功 能 就 是 存 储 并 检 索 数 据 以 及 向 其 他 应 用 程 序 提 供 访 问 数 据 的 借 口 Service Service 跟 Activity 的 级 别 差 不 多, 但 不 能 自 己 运 行 只 能 后 台 运 行, 并 且 可 以 和 其 他 组 件 进 行 交 互 service 可 以 在 很 多 场 合 的 应 用 中 使 用, 比 如 播 放 多 媒 体 的 时 候 用 户 启 动 了 其 他 Activity 这 个 时 候 程 序 要 在 后 台 继 续 播 放, 比 如 检 测 SD 卡 上 文 件 的 变 化, 再 或 者 在 后 台 记 录 你 地 理 信 息 位 置 的 改 变 等 等, 总 之 服 务 总 是 藏 在 后 台 的 实 验 步 骤 下 面 通 过 HelloWorld 示 例 来 介 绍 Android 程 序 框 架 : 1) 打 开 eclipse, 导 入 上 一 章 1.2 节 创 建 的 HelloWorld 工 程, 双 击 HelloWorld 工 程 可 以 看 到 其 子 目 录 如 下 图 : 图 子 目 录 界 面

24 Activity 类 R 文 件 布 局 文 件 配 置 文 件 图 子 目 录 详 细 信 息 界 面 下 面 举 例 说 明 Android 应 用 解 析 中 如 何 实 现 两 个 Activity 之 间 的 切 换 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 Activity1 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 :

25 图 Activity1 界 面 2) 当 单 击 切 换 按 钮 时, 屏 幕 显 示 布 局 main2.xml, 如 果 在 单 击 切 换 按 钮, 又 会 回 到 上 图 图 所 示 状 态, 就 这 样 通 过 Intent 完 成 了 两 个 Activity 之 间 的 切 换 图 Activity2 界 面 2.2 Android Java 基 础 实 验 目 的 了 解 Interface 在 Android 应 用 程 序 中 的 使 用 ; 了 解 For 循 环 在 Android 应 用 程 序 中 的 使 用 ; 了 解 Map 类 在 Android 应 用 程 序 中 的 使 用 ; 了 解 String 在 Android 应 用 程 序 中 的 使 用 ;

26 2.2.2 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT 实 验 原 理 Interface 即 为 接 口 的 意 思, 多 用 于 实 现 回 调 方 法 对 于 Interface 内 部 的 方 法 而 已, 只 要 声 明, 而 不 需 要 具 体 实 现 从 编 译 的 角 度 来 看,Interface 会 被 认 为 是 一 个 指 向 方 法 的 指 针 For 循 环 Android 应 用 程 序 中 使 用 除 了 传 统 的 for 循 环 (for(int i=0;i<n;i++)) 以 外 还 有 forecah 循 环 For 循 环 使 用 代 码 : public void dolist(){ int[] ages = new int[5]; String str = ""; for(int i=0;i<5;i++){// 初 始 化 ages[i] = i; } for(int age : ages){ str = str+" 这 是 我 的 年 龄 :"+age+"\n"; } codeview.settext(str); } 第 二 个 for 语 法 是 增 强 for 循 环, 完 成 对 某 个 集 合 进 行 循 环 不 输 出, 第 一 个 参 数 是 循 环 过 程 集 合 元 素 值 的 引 用, 第 二 个 参 数 是 集 合 对 象, 其 执 行 效 率 较 高 Map 类 是 一 类 关 联 式 容 器, 它 是 模 板 类 关 联 的 本 质 在 于 元 素 的 值 与 某 个 特 定 的 键 相 关 联, 而 并 非 通 过 元 素 在 数 组 中 的 位 置 类 获 取 它 的 特 点 是 增 加 和 删 除 节 点 对 迭 代 器 的 影 响 很 小, 除 了 操 作 节 点, 对 其 他 的 节 点 都 没 有 什 么 影 响 对 于 迭 代 器 来 说, 不 可 以 修 改 键 值, 只 能 修 改 其 对 应 的 实 值 Map 类 使 用 代 码 : Map<String,Object> maps = new HashMap<String, Object>(); maps.put("age", "20"); maps.put("name", "andy"); maps.put("favourate", "football");

27 for(string key: maps.keyset()){ str = str + "key 值 :"+key.tostring() +"\n"; str = str + "Value 值 :"+ maps.get(key).tostring()+"\n"; } String String 就 是 java 中 的 字 符 串, 用 双 引 号 引 起 来 的 几 个 字 符. 如 "Abc"," 一 天 " String 类 是 不 可 变 (final) 的, 对 String 类 的 任 何 改 变, 都 是 返 回 一 个 新 的 String 类 对 象 这 样 的 话 把 String 类 的 引 用 传 递 给 一 个 方 法, 该 方 法 对 String 的 任 何 改 变, 对 原 引 用 指 向 的 对 象 没 有 任 何 影 响, 这 一 点 和 基 本 数 据 类 型 相 似 String 可 以 调 用 的 方 法 有 很 多 如 : 将 字 符 串 转 换 换 成 小 写 :String.toLowerCase(); 使 用 字 符 串 替 换 功 能 :String.replace( 新 的 字 符 串 "); 使 用 字 符 串 截 取 功 能 :String.substring(start, end) 实 验 步 骤 下 面 举 例 说 明 Java 语 言 在 Android 应 用 程 序 中 的 使 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 InterfaceAndroid 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 InterfaceAndroid 运 行 界 面 2) 单 击 确 定 按 钮, 显 示 这 个 按 钮 被 点 击 了 说 明 Interface 方 法 使 用 正 常, 如 图 所 示 :

28 图 Interface 方 法 使 用 界 面 3) 单 击 显 示 for 循 环 信 息 按 钮,for 循 环 的 使 用 结 果 如 图 所 示 : 图 for 循 环 的 使 用 界 面 4) 单 击 显 示 Map 信 息 按 钮, Map 类 的 使 用 结 果 如 图 所 示 : 图 Map 类 的 使 用 界 面 5) 单 击 处 理 字 符 串 信 息 按 钮, 字 符 串 的 使 用 结 果 如 图 所 示 :

29 图 Map 类 的 使 用 界 面 2.3 程 序 生 命 周 期 实 验 目 的 了 解 Android 系 统 的 进 程 优 先 级 的 变 化 方 式 ; 了 解 Activity 的 生 命 周 期 中 各 状 态 的 变 化 关 系 ; 了 解 全 生 命 周 期 可 视 生 命 周 期 活 动 生 命 周 期 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT 实 验 原 理 程 序 的 生 命 周 期 是 在 Android 系 统 中 进 程 从 启 动 到 终 止 的 所 有 阶 段, 也 就 是 Android 程 序 启 动 到 停 止 的 全 过 程 程 序 的 生 命 周 期 由 Android 系 统 进 行 调 度 和 控 制 的 Android 系 统 中 的 进 程 优 先 级 由 高 到 低 : 前 台 进 程 可 见 进 程 服 务 进 程 后 台 进 程 空 进 程 组 件 是 可 以 调 用 的 基 本 功 能 模 块,Android 应 用 程 序 就 是 由 组 件 组 成 的 Android 系 统 有 四 个 重 要 的 组 件, 分 别 是 Activity Service BroadcaseReceiver 和

30 ContentProvider 图 Activity 生 命 周 期 Activity 生 命 周 期 指 Activity 从 启 动 到 销 毁 的 过 程,Activity 表 现 为 四 种 状 态, 分 别 是 活 动 状 态 暂 停 状 态 停 止 状 态 和 非 活 动 状 态 活 动 状 态,Activity 在 用 户 界 面 中 处 于 最 上 层, 完 全 能 不 用 户 看 到, 能 够 与 用 户 进 行 交 互 暂 停 状 态,Activity 在 界 面 上 被 部 分 遮 挡, 该 Activity 不 再 处 于 用 户 界 面 的 最 上 层, 且 不 能 够 与 用 户 进 行 交 互 停 止 状 态,Activity 在 界 面 上 完 全 不 能 被 用 户 看 到, 也 就 是 说 这 个 Activity 被 其 他 Activity 全 部 遮 挡 非 活 动 状 态 不 在 以 上 三 种 状 态 中 的 Activity 则 处 于 非 活 动 状 态 全 生 命 周 期 是 从 Activity 建 立 到 销 毁 的 全 部 过 程, 始 于 oncreate(), 结 束 于 ondestroy() 使 用 者 通 常 在 oncreate() 中 初 始 化 Activity 所 能 使 用 的 全 局 资 源 和 状 态, 并 在 ondestroy() 中 释 放 这 些 资 源 在 一 些 极 端 的 情 况 下,Android 系 统 会 不 调 用 ondestroy() 函 数, 而 直 接 终 止 进 程 可 视 生 命 周 期 是 Activity 在 界 面 上 从 可 见 到 不 可 见 的 过 程, 开 始 于 onstart(), 结 束 于 onstop() onstart() 一 般 用 来 初 始 化 或 启 动 与 更 新 界 面 相 关 的 资 源,onStop() 一 般 用 来 暂 停 或 停 止 一 切 与 更

31 新 用 户 界 面 相 关 的 线 程 计 时 器 和 服 务,onRestart() 函 数 在 onsart() 前 被 调 用, 用 来 在 Activity 从 不 可 见 变 为 可 见 的 过 程 中, 进 行 一 些 特 定 的 处 理 过 程 onstart() 和 onstop() 会 被 多 次 调 用, onstart() 和 onstop() 也 经 常 被 用 来 注 册 和 注 销 BroadcastReceiver 活 动 生 命 周 期 活 动 生 命 周 期 是 Activity 在 屏 幕 的 最 上 层, 并 能 够 与 用 户 交 互 的 阶 段, 开 始 于 onresume(), 结 束 于 onpause() 在 Activity 的 状 态 变 换 过 程 中 onresume() 和 onpause() 经 常 被 调 用, 因 此 这 两 个 函 数 中 应 使 用 更 为 简 单 高 效 的 代 码 实 验 步 骤 下 面 举 例 说 明 Activity 生 命 周 期 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 ActivityLifeCycle 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 为 了 显 示 结 果 易 于 观 察 和 分 析, 通 过 Toast 来 显 示 相 关 信 息 3) 启 动 ActivityLifeCycle, 按 下 返 回 键, 关 闭 ActivityLifeCycle,Toast 依 次 输 出 结 果 如 下 : 图 Activity 全 生 命 周 期 oncreate() oncreate() 用 来 初 始 化 Activity 所 能 使 用 的 全 局 资 源 和 状 态

32 图 Activity 全 生 命 周 期 onstart() onstart() 一 般 用 来 初 始 化 或 启 动 与 更 新 界 面 相 关 的 资 源 图 Activity 全 生 命 周 期 onresume() 当 Activity 能 够 与 用 户 交 互, 接 收 用 户 输 入 时, onresume() 方 法 被 调 用

33 图 Activity 全 生 命 周 期 onresume() 当 Activity 进 入 暂 停 状 态 时,onResume() 方 法 被 调 用 图 Activity 全 生 命 周 期 onstop() 当 Activity 进 入 停 止 状 态 时,onStop() 方 法 被 调 用

34 图 Activity 全 生 命 周 期 ondestroy() 在 Activity 被 终 止 前, 即 进 入 非 活 动 状 态 前,onDestroy() 方 法 被 调 用 4) 启 动 ActivityLifeCycle, 通 过 电 源 键 进 入 休 眠 状 态, 再 通 过 电 源 键 使 其 唤 醒, 活 动 生 命 周 期 的 Toast 输 出 : 图 Activity 活 动 生 命 周 期 onsaveinstancestate() Android 系 统 因 资 源 不 足 终 止 Activity 前 调 用 该 方 法, 用 以 保 存 Activity 的 状 态 信 息, 记 录 活 动 的 临 时 数 据, 供 onrestoreinstancestate() 或 oncreate() 恢 复 使 用

35 图 Activity 活 动 生 命 周 期 onrestart() onrestart 常 用 来 保 存 持 久 数 据, 如 界 面 上 用 户 输 入 的 信 息 等 图 Activity 活 动 生 命 周 期 onresume() 当 Activity 能 够 与 用 户 交 互, 接 收 用 户 输 入 时,onResume() 方 法 被 调 用 2.4 程 序 调 试 实 验 目 的 了 就 Android 系 统 提 供 的 两 种 调 试 工 具 LogCat 的 使 用 ;

36 了 解 Android 系 统 中 ADB 和 DDMS 的 使 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT 实 验 原 理 Logcat 的 使 用 logcat 命 令 可 以 用 来 查 看 系 统 日 志 缓 冲 区 的 内 容 : [adb] logcat [<option>]... [<filter-spec>]... 详 细 内 容, 请 查 看 Listing of logcat Command Options, 它 对 logcat 命 令 有 详 细 的 描 述. 你 也 可 以 在 你 的 电 脑 或 运 行 在 模 拟 器 / 设 备 上 的 远 程 adb shell 端 来 使 用 logcat 命 令, 也 可 以 在 你 的 电 脑 上 查 看 日 志 输 出 $ adb logcat, 你 也 这 样 使 用 : # logcat 每 一 个 输 出 的 Android 日 志 信 息 都 有 一 个 标 签 和 它 的 优 先 级. 日 志 的 标 签 是 系 统 部 件 原 始 信 息 的 一 个 简 要 的 标 志 ( 比 如 : View 就 是 查 看 系 统 的 标 签 ). 优 先 级 有 下 列 几 中, 是 按 照 从 低 到 高 顺 利 排 列 的 : V Verbose (lowest priority); D Debug; I Info; W Warning; E Error; F Fatal; S Silent (highest priority, on which nothing is ever printed) 在 运 行 logcat 的 时 候 在 前 两 列 的 信 息 中 你 就 可 以 看 到 logcat 的 标 签 列 表 和 优 先 级 别, 它 是 这 样 标 出 的 :<priority>/<tag> 通 过 添 加 过 滤 器, 无 论 什 么 样 类 型 的 日 志 信 息, 属 于 哪 一 个 进 程, 只 要 标 签 为 LogCat, 都 将 显 示 在 LogCatFilter 区 域 中 adb(android Debug Bridge) adb(android Debug Bridge) 是 Android 提 供 的 一 个 通 用 的 调 试 工 具, 借 助 这 个 工 具, 我 们 可 以 管 理 设 备 或 手 机 模 拟 器 的 状 态 还 可 以 进 行 以 下 的 操 作 : 1 快 速 更 新 设 备 或 手 机 模 拟 器 中 的 代 码, 如 应 用 或 Android 系 统 升 级 ; 2 在 设 备 上 运 行 shell 命 令 ; 3 管 理 设 备 或 手 机 模 拟 器 上 的 预 定 端 口 ; 4 在 设 备 或 手 机 模 拟 器 上 复 制 或 粘 贴 文 件

37 DDMS DDMS 的 全 称 是 Dalvik Debug Monitor Service, 它 为 我 们 提 供 例 如 : 为 测 试 设 备 截 屏, 针 对 特 定 的 进 程 查 看 正 在 运 行 的 线 程 以 及 堆 信 息 Logcat 广 播 状 态 信 息 模 拟 电 话 呼 叫 接 收 SMS 虚 拟 地 理 坐 标 等 等 DDMS 将 搭 建 起 IDE 与 测 试 终 端 (Emulator 或 者 connected device) 的 链 接, 它 们 应 用 各 自 独 立 的 端 口 监 听 调 试 器 的 信 息,DDMS 可 以 实 时 监 测 到 测 试 终 端 的 连 接 情 况 当 有 新 的 测 试 终 端 连 接 后,DDMS 将 捕 捉 到 终 端 的 ID, 并 通 过 adb 建 立 调 试 器, 从 而 实 现 发 送 指 令 到 测 试 终 端 的 目 的 DDMS 监 听 第 一 个 终 端 App 进 程 的 端 口 为 8600,APP 进 程 将 分 配 8601, 如 果 有 更 多 终 端 或 者 更 多 APP 进 程 将 按 照 这 个 顺 序 依 次 类 推 DDMS 通 过 8700 端 口 ( base port ) 接 收 所 有 终 端 的 指 令 实 验 步 骤 下 面 举 例 说 明 LogCat 的 使 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 LogCat 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 添 加 LOGCAT 过 滤 器. 首 先, 单 击 左 上 角 的 +, 弹 出 过 滤 器 设 置 对 话 框 如 图 所 示 : 图 添 加 过 滤 器 3) 对 话 框 中 填 入 过 滤 器 的 名 称 :LOGCAT, 设 置 过 滤 条 件 为 标 签 =LOGCAT 即 可, 下 拉 选 项 框 可 以 选 择 不 同 级 别 的 日 志 信 息 V: 详 细 信 息 ;D: 调 试 信 息 ;I: 通 告 信 息 ;W: 警 告 信 息 ;E: 错 误 信 息 操 作 方 法 如 下 图 :

38 图 设 置 过 滤 器 4) 经 过 上 述 过 滤 器 过 滤 后, 无 论 什 么 样 的 日 志 信 息, 只 要 被 标 签 为 LOGCAT, 都 将 显 示 在 LOGCAT 区 域 里, 如 下 图 所 示 : 下 面 举 例 说 明 adb 的 使 用 : 首 先, 进 入 系 统 的 CMD 命 令 窗 口 : 图 LOGAT 输 出 结 果 图 CMD 命 令 窗 口 输 入 adb devices 命 令 来 查 看 设 备 连 接 状 态 : C:\Users\Administrator>adb devices

39 List of devices attached ABCDEF device 输 入 adb version 命 令 来 查 看 adb 版 本 : C:\Users\Administrator>adb version Android Debug Bridge version 输 入 adb shell 命 令 进 入 设 备 的 shell 中 这 时 会 有 一 个 # 号 出 现 : C:\Users\Administrator>adb shell # 输 入 exit 命 令 便 可 退 出 : # exit exit 输 入 ls 命 令 查 看 出 当 前 目 录 的 清 单 : # ls ls config cache sdcard acct mnt vendor d bin etc ueventd.smdkv210.rc ueventd.rc ueventd.goldfish.rc system sys sbin proc init.smdkv210.rc init.rc init.goldfish.rc init default.prop data root dev

40 安 装 APK 文 件, 命 令 是 adb install + 文 件 路 径, 相 应 的 文 件 用 鼠 标 拖 动 的 方 法 拖 到 CMD 界 面 中 即 可 : C:\>adb install C:\HelloWorld.apk 4395 KB/s ( bytes in 0.040s) pkg: /data/local/tmp/helloworld.apk Success 下 面 举 例 说 明 DDMS 的 使 用 : 在 Eclipes 调 试 程 序 的 过 程 中 启 动 DDMS, 在 Eclipes 中 的 界 面 如 下 : 图 启 动 DDMS 在 eclipse 界 面 选 择 window -> Open Perspective -> Other, 界 面 如 下 : 图 Other 界 面 双 击 DDMS 就 可 以 启 动 了,DDMS 对 Emulator 和 外 接 测 试 机 有 同 等 效 用 如 果 系 统 检 测 到 它

41 们 (VM) 同 时 运 行, 那 么 DDMS 将 会 默 认 指 向 Emulator 在 GUI 的 左 上 角 可 以 看 到 标 签 为 Devices 的 面 板, 这 里 可 以 查 看 到 所 有 与 DDMS 连 接 的 终 端 的 详 细 信 息, 以 及 每 个 终 端 正 在 运 行 的 APP 进 程, 每 个 进 程 最 右 边 相 对 应 的 是 与 调 试 器 链 接 的 端 口 因 为 Android 是 基 于 Linux 内 核 开 发 的 操 作 平 台, 同 时 也 保 留 了 Linux 中 特 有 的 进 程 ID, 它 介 于 进 程 名 和 端 口 号 之 间 图 Devices 面 板 界 面 在 面 板 的 右 上 角 有 一 排 很 重 要 的 按 键 他 们 分 别 是 Debug the selected process Update Threads Update Heap Stop Process 和 ScreenShot, 通 过 screen capture 按 钮 可 以 进 行 截 图 Emulator Control 面 板 : 通 过 这 个 面 板 的 一 些 功 能 可 以 非 常 容 易 的 使 测 试 终 端 模 拟 真 实 手 机 所 具 备 的 一 些 交 互 功 能, 比 如 : 接 听 电 话, 根 据 选 项 模 拟 各 种 不 同 网 络 情 况, 模 拟 接 受 SMS 消 息 和 发 送 虚 拟 地 址 坐 标 用 于 测 试 GPS 功 能 等 图 Emulator Control 面 板 File Exporler 面 板 : 通 过 File Exporler 可 以 查 看 Android 模 拟 器 中 的 文 件, 选 中 文 件 后 通 过 右

42 上 角 的 导 入 和 导 出 按 钮, 可 以 很 方 便 的 导 入 / 出 文 件 图 File Exporler 界 面

43 第 三 章 用 户 界 面 开 发 Android & linux 系 统 与 应 用 开 发 本 章 节 主 要 介 绍 Android 程 序 界 面 开 发, 包 括 用 户 界 面 基 础 用 户 界 面 的 控 件 的 使 用 界 面 布 局 的 特 点 及 使 用 方 法 菜 单 的 使 用 方 法 界 面 事 件 的 处 理 方 法 等 3.1 用 户 界 面 基 础 用 户 界 面 (User Interface,UI) 是 系 统 和 用 户 之 间 进 行 信 息 交 换 的 媒 介, 实 现 信 息 的 内 部 形 式 与 人 类 可 以 接 受 形 式 之 间 的 转 换, 在 计 算 机 出 现 早 期, 批 处 理 界 面 ( ) 和 命 令 行 界 面 ( ) 得 到 广 泛 的 使 用 目 前, 流 行 图 像 用 户 界 面 (Graphical User Interface,GUI), 采 用 图 形 方 式 与 用 户 进 行 交 互 的 界 面 未 来 的 用 户 界 面 将 更 多 的 运 用 虚 拟 现 实 技 术, 使 用 户 能 够 摆 脱 键 盘 与 鼠 标 的 交 互 方 式, 而 通 过 动 作 语 言, 甚 至 是 脑 电 波 来 控 制 计 算 机 Android 用 户 界 面 框 架 (Android UI Framework) 采 用 MVC(Model-View-Controller) 模 型 视 图 键 盘 输 入 控 制 器 绘 制 界 面 更 新 模 型 图 Android 用 户 界 面 框 架 MVC 模 型 MVC 模 型 提 供 了 处 理 用 户 输 入 的 控 制 器 (Controller) 显 示 用 户 界 面 和 图 像 的 视 图 (View), 以 及 保 存 数 据 和 代 码 的 模 型 (Model) MVC 模 型 中 的 控 制 器 能 够 接 受 并 响 应 程 序 的 外 部 动 作, 如 按 键 动 作 或 触 摸 屏 动 作 等 控 制 器 使 用 队 列 处 理 外 部 动 作, 每 个 外 部 动 作 作 为 一 个 对 立 的 事 件 被 加 入 队 列 中, 然 后 Android 用 户 界 面 框 架 按 照 先 进 先 出 的 规 则 从 队 列 中 获 取 事 件, 并 将 这 个 事 件 分 配 给 所 对 应 的 事 件 处 理

44 函 数 Android 用 户 界 面 框 架 (Android UI Framework) 采 用 视 图 树 (View Tree) 模 型 Android 用 户 界 面 框 架 中 的 界 面 元 素 以 一 种 树 型 结 构 组 织 在 一 起, 称 为 视 图 树 ViewGroup View ViewGroup View View View View 图 Android 视 图 树 Android 系 统 会 依 据 视 图 树 的 结 构 从 上 至 下 绘 制 每 一 个 界 面 元 素 每 个 元 素 负 责 对 自 身 的 绘 制, 如 果 元 素 包 含 子 元 素, 该 元 素 会 通 知 其 下 所 有 子 元 素 进 行 绘 制 视 图 树 由 View 和 ViewGroup 构 成 View 是 界 面 的 最 基 本 的 可 视 单 元, 存 储 了 屏 幕 上 特 定 矩 形 区 域 内 所 显 示 内 容 的 数 据 结 构, 并 能 够 实 现 所 占 据 区 域 的 界 面 绘 制 焦 点 变 化 用 户 输 入 和 界 面 事 件 处 理 等 功 能 View 也 是 一 个 重 要 的 基 类, 所 有 在 界 面 上 的 可 见 元 素 都 是 View 的 子 类 ViewGroup 是 一 种 能 够 承 载 含 多 个 View 的 显 示 单 元 ViewGroup 功 能 : 一 个 是 承 载 界 面 布 局, 另 一 个 是 承 载 具 有 原 子 特 性 的 重 构 模 块 3.2 界 面 布 局 实 验 目 的 了 解 界 面 布 局 (Layout) 的 使 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP Android ADT

45 3.2.3 实 验 原 理 界 面 布 局 (Layout) 是 用 户 界 面 结 构 的 描 述, 定 义 了 界 面 中 所 有 的 元 素 结 构 和 相 互 关 系 声 明 Android 程 序 的 界 面 布 局 有 两 种 方 法 : 使 用 XML 文 件 描 述 界 面 布 局 ; 在 程 序 运 行 时 动 态 添 加 或 修 改 界 面 布 局 用 户 既 可 以 独 立 使 用 任 何 一 种 声 明 界 面 布 局 的 方 式, 也 可 以 同 时 使 用 两 种 方 式 使 用 XML 文 件 声 明 界 面 布 局 的 特 点 : 将 程 序 的 表 现 层 和 控 制 层 分 离 ; 在 后 期 修 改 用 户 界 面 时, 无 需 更 改 程 序 的 源 代 码 用 户 还 能 够 通 过 可 视 化 工 具 直 接 看 到 所 设 计 的 用 户 界 面, 有 利 于 加 快 界 面 设 计 的 过 程, 并 且 为 界 面 设 计 与 开 发 带 来 极 大 的 便 利 性 线 性 布 局 (LinearLayout) 是 一 种 重 要 的 界 面 布 局 中, 也 是 经 常 使 用 到 的 一 种 界 面 布 局 在 线 性 布 局 中, 所 有 的 子 元 素 都 按 照 垂 直 或 水 平 的 顺 序 在 界 面 上 排 列, 如 果 垂 直 排 列, 则 每 行 仅 包 含 一 个 界 面 元 素 如 果 水 平 排 列, 则 每 列 仅 包 含 一 个 界 面 元 素 框 架 布 局 (FrameLayout) 是 最 简 单 的 界 面 布 局, 是 用 来 存 放 一 个 元 素 的 空 白 空 间, 且 子 元 素 的 位 置 是 不 能 够 指 定 的, 只 能 够 放 置 在 空 白 空 间 的 左 上 角 如 果 有 多 个 子 元 素, 后 放 置 的 子 元 素 将 遮 挡 先 放 置 的 子 元 素, 使 用 Android SDK 中 提 供 的 层 级 观 察 器 (Hierarchy Viewer) 进 一 步 分 析 界 面 布 局 层 级 观 察 器 能 够 对 用 户 界 面 进 行 分 析 和 调 试, 并 以 图 形 化 的 方 式 展 示 树 形 结 构 的 界 面 布 局 还 提 供 了 一 个 精 确 的 像 素 级 观 察 器 (Pixel Perfect View), 以 栅 格 的 方 式 详 细 观 察 放 大 后 的 界 面 界 面 表 格 布 局 (TableLayout) 是 一 种 常 用 的 界 面 布 局, 它 将 屏 幕 划 分 网 格, 通 过 指 定 行 和 列 可 以 将 界 面 元 素 添 加 的 网 格 中 网 格 的 边 界 对 用 户 是 不 可 见 的, 表 格 布 局 还 支 持 嵌 套, 可 以 将 另 一 个 表 格 布 局 放 置 在 前 一 个 表 格 布 局 的 网 格 中, 也 可 以 在 表 格 布 局 中 添 加 其 他 界 面 布 局, 例 如 线 性 布 局 相 对 布 局 等 等 相 对 布 局 (RelativeLayout) 是 一 种 非 常 灵 活 的 布 局 方 式, 能 够 通 过 指 定 界 面 元 素 与 其 他 元 素 的 相 对 位 置 关 系, 确 定 界 面 中 所 有 元 素 的 布 局 位 置 特 点 : 能 够 最 大 程 度 保 证 在 各 种 屏 幕 类 型 的 手 机 上 正 确 显 示 界 面 布 局 绝 对 布 局 (AbsoluteLayout) 能 通 过 指 定 界 面 元 素 的 坐 标 位 置, 来 确 定 用 户 界 面 的 整 体 布 局 绝 对 布 局 是 一 种 不 推 荐 使 用 的 界 面 布 局, 因 为 通 过 X 轴 和 Y 轴 确 定 界 面 元 素 位 置 后,Android 系 统 不 能 够 根 据 不 同 屏 幕 对 界 面 元 素 的 位 置 进 行 调 整, 降 低 了 界 面 布 局 对 不 同 类 型 和 尺 寸 屏 幕 的 适 应 能 力

46 3.2.4 实 验 步 骤 下 面 将 介 绍 界 面 布 局 的 具 体 应 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 LayOut 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 在 LayOut.java 文 件 中 通 过 取 消 其 中 一 个 界 面 布 局 文 件 注 释, 使 其 被 调 用 则 显 示 不 同 布 局 效 果 : 图 布 局 文 件 被 调 用 界 面 3) 取 消 线 性 垂 直 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 : 图 线 性 垂 直 布 局 效 果 图 4) 取 消 线 性 水 平 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 :

47 图 线 性 水 平 布 局 效 果 图 5) 取 消 框 架 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 : 图 框 架 布 局 效 果 图 6) 取 消 表 格 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 : 图 表 格 布 局 效 果 图 7) 取 消 相 对 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 :

48 图 相 对 布 局 效 果 图 8) 取 消 绝 对 布 局 注 释 使 其 被 调 用, 显 示 效 果 如 下 : 图 绝 对 布 局 效 果 图 3.3 界 面 控 件 实 验 目 的 了 解 Android 应 用 编 程 的 界 面 控 件 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP

49 3.3.3 实 验 原 理 Android 系 统 的 界 面 控 件 分 为 定 制 控 件 和 系 统 控 件 定 制 控 件 是 用 户 独 立 开 发 的 控 件, 或 通 过 继 承 并 修 改 系 统 控 件 后 所 产 生 的 新 控 件 能 够 为 用 户 提 供 特 殊 的 功 能 或 与 众 不 同 的 显 示 需 求 方 式 系 统 控 件 是 Android 系 统 提 供 给 用 户 已 经 封 装 的 界 面 控 件 提 供 在 应 用 程 序 开 发 过 程 中 常 见 功 能 控 件 系 统 控 件 更 有 利 于 帮 助 用 户 进 行 快 速 开 发, 同 时 能 够 使 Android 系 统 中 应 用 程 序 的 界 面 保 持 一 致 性 常 见 的 系 统 控 件 包 括 TextView EditText Button ImageButton Checkbox RadioButton Spinner ListView 和 TabHost TextView 是 一 种 用 于 显 示 字 符 串 的 控 件,EditText 则 是 用 来 输 入 和 编 辑 字 符 串 的 控 件,EditText 是 一 个 具 有 编 辑 功 能 的 TextView Button 是 一 种 按 钮 控 件, 用 户 能 够 在 该 控 件 上 点 击, 并 后 引 发 相 应 的 事 件 处 理 函 数,ImageButton 用 以 实 现 能 够 显 示 图 像 功 能 的 控 件 按 钮 CheckBox 是 一 个 同 时 可 以 选 择 多 个 选 项 的 控 件,RadioButton 则 是 仅 可 以 选 择 一 个 选 项 的 控 件,RadioGroup 是 RadioButton 的 承 载 体, 程 序 运 行 时 不 可 见, 应 用 程 序 中 可 能 包 含 一 个 或 多 个 RadioGroup, 一 个 RadioGroup 包 含 多 个 RadioButton, 在 每 个 RadioGroup 中, 用 户 仅 能 够 选 择 其 中 一 个 RadioButton Spinner 是 一 种 能 够 从 多 个 选 项 中 选 一 选 项 的 控 件, 类 似 于 桌 面 程 序 的 组 合 框 (ComboBox), 但 没 有 组 合 框 的 下 拉 菜 单, 而 是 使 用 浮 动 菜 单 为 用 户 提 供 选 择 ListView 是 一 种 用 于 垂 直 显 示 的 列 表 控 件, 如 果 显 示 内 容 过 多, 则 会 出 现 垂 直 滚 动 条 ListView 能 够 通 过 适 配 器 将 数 据 和 自 身 绑 定, 在 有 限 的 屏 幕 上 提 供 大 量 内 容 供 用 户 选 择, 所 以 是 经 常 使 用 的 用 户 界 面 控 件 ListView 支 持 点 击 事 件 处 理, 用 户 可 以 用 少 量 的 代 码 实 现 复 杂 的 选 择 功 能 Tab 标 签 页 是 界 面 设 计 经 常 使 用 的 界 面 控 件, 可 以 实 现 多 个 分 页 之 间 的 快 速 切 换, 每 个 分 页 可 以 显 示 不 同 内 容 实 验 步 骤 下 面 将 介 绍 TextView EditText 界 面 控 件 的 具 体 应 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 TextViewDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2)TextView 显 示 了 字 符 串 用 户 名 :,EditText 则 可 以 用 来 输 入 和 编 辑 字 符 串, 如 图 所 示 :

50 图 TextView 和 EditView 效 果 图 下 面 将 介 绍 Button ImageButton 界 面 控 件 的 具 体 应 用 : 1) 将 范 例 程 序 ButtonDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 用 户 点 击 Button 按 钮 控 件 后, 引 发 相 应 的 事 件 本 例 是 通 过 TextView 显 示 字 符 串 Button 按 钮, ImageButton 按 钮 用 以 表 示 能 够 显 示 图 像 功 能 图 Button 和 ImageButton 效 果 图 下 面 将 介 绍 Checkbox RadioButton 界 面 控 件 的 具 体 应 用 : 1) 将 范 例 程 序 CheckRadiobuttonDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2 ) CheckBox01 和 CheckBox02 可 以 同 时 被 选 择 也 可 只 选 其 一, RadioButton01 和 RadioButton02 则 是 仅 可 以 选 择 一 个 如 图 所 示 :

51 图 CheckRadiobutton 效 果 图 下 面 将 介 绍 Spinner 界 面 控 件 的 具 体 应 用 : 1) 将 范 例 程 序 SpinnerDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 单 击 Spinner 子 项 按 钮, 便 会 弹 出 浮 动 菜 单 供 用 户 选 择, 如 下 图 所 示 : 图 Spinner 效 果 图 下 面 将 介 绍 ListView 界 面 控 件 的 具 体 应 用 : 1) 将 范 例 程 序 ListViewDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2)ListView 垂 直 显 示 选 项 列 表, 如 果 显 示 内 容 过 多, 右 侧 则 会 出 现 垂 直 滚 动 条 如 图 所 示 :

52 图 ListView 效 果 图 下 面 将 介 绍 TabHost 界 面 控 件 的 具 体 应 用 : 1) 将 范 例 程 序 TabDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 点 击 标 签 线 性 布 局 相 对 布 局 可 以 实 现 这 两 个 分 页 之 间 的 快 速 切 换, 每 个 分 页 可 以 显 示 不 同 内 容 图 TabHost 效 果 图 3.4 菜 单 实 验 目 的 了 解 Android 应 用 编 程 菜 单 控 件 的 使 用 ;

53 3.4.2 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 菜 单 是 应 用 程 序 中 非 常 重 要 的 组 成 部 分, 能 够 在 不 占 用 界 面 空 间 的 前 提 下, 为 应 用 程 序 提 供 了 统 一 的 功 能 和 设 置 界 面, 并 为 程 序 开 发 人 员 提 供 了 易 于 使 用 的 编 程 接 口 Android 系 统 支 持 三 种 菜 单 : 选 项 菜 单 (Option Menu); 子 菜 单 (Submenu); 快 捷 菜 单 (Context Menu) 选 项 菜 单 是 一 种 经 常 被 使 用 的 Android 系 统 菜 单, 打 开 方 式 : 通 过 菜 单 键 (MENU key) 打 开, 选 项 菜 单 分 类 : 图 标 菜 单 ( Icon Menu ) 扩 展 菜 单 ( Expanded Menu ) 重 载 Activity 的 oncreateoptionmenu() 函 数, 才 能 够 在 Android 应 用 程 序 中 使 用 选 项 菜 单, 初 次 使 用 选 项 菜 单 时, 会 调 用 oncreateoptionmenu() 函 数, 用 来 初 始 化 菜 单 子 项 的 相 关 内 容 子 菜 单 是 能 够 显 示 更 加 详 细 信 息 的 菜 单 子 项, 菜 单 子 项 使 用 了 浮 动 窗 体 的 显 示 形 式, 能 够 更 好 适 应 小 屏 幕 的 显 示 方 式 Android 系 统 的 子 菜 单 使 用 非 常 灵 活, 可 以 在 选 项 菜 单 或 快 捷 菜 单 中 使 用 子 菜 单, 有 利 于 将 相 同 或 相 似 的 菜 单 子 项 组 织 在 一 起, 便 于 显 示 和 分 类 子 菜 单 不 支 持 嵌 套, 子 菜 单 的 添 加 是 使 用 addsubmenu() 函 数 实 现 快 捷 菜 单 同 样 采 用 了 浮 动 窗 体 的 显 示 方 式, 与 子 菜 单 的 实 现 方 式 相 同, 但 两 种 菜 单 的 启 动 方 式 却 截 然 不 同 启 动 方 式 : 快 捷 菜 单 类 似 于 普 通 桌 面 程 序 中 的 右 键 菜 单, 当 用 户 点 击 界 面 元 素 超 过 2 秒 后, 将 启 动 注 册 到 该 界 面 元 素 的 快 捷 菜 单 使 用 方 法 : 与 使 用 选 项 菜 单 的 方 法 非 常 相 似, 需 要 重 载 oncreatecontextmenu() 函 数 和 oncontextitemselected() 函 数 oncreatecontextmenu() 函 数 主 要 用 来 添 加 快 捷 菜 单 所 显 示 的 标 题 图 标 和 菜 单 子 项 等 内 容 选 项 菜 单 中 的 oncreateoptionsmenu() 函 数 仅 在 选 项 菜 单 第 一 次 启 动 时 被 调 用 一 次 快 捷 菜 单 的 oncreatecontextmenu() 函 数 每 次 启 动 时 都 会 被 调 用 一 次

54 3.4.4 实 验 步 骤 下 面 将 介 绍 选 项 菜 单 的 具 体 应 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 OptionsMenu 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 通 过 单 击 菜 单 键 可 以 调 出 程 序 设 计 的 两 个 菜 单 子 项, 如 图 所 示 : 图 OptionsMenu 效 果 图 下 面 将 介 绍 子 菜 单 的 具 体 应 用 : 1) 将 范 例 程 序 SubMenu 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 通 过 单 击 菜 单 键 可 以 调 出 程 序 设 计 的 菜 单, 然 后 再 单 击 菜 单, 菜 单 子 项 便 会 以 浮 动 窗 体 的 形 式 显 示, 如 图 所 示 : 下 面 将 介 绍 快 捷 菜 单 的 具 体 应 用 : 图 SubMenu 效 果 图 1) 将 范 例 程 序 ContextMenu 通 过 Import->Existing Projects into Workspace 导 入 到 Java

55 Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 点 击 界 面 超 过 2 秒 后, 快 捷 菜 单 将 被 启 动, 如 图 所 示 : 图 ContextMenu 效 果 图 3.5 界 面 事 件 实 验 目 的 了 解 Android 界 面 框 架 如 何 调 用 界 面 控 件 的 事 件 处 理 函 数 对 事 件 进 行 处 理 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 在 Android 系 统 中, 存 在 多 种 界 面 事 件, 如 点 击 事 件 触 摸 事 件 焦 点 事 件 和 菜 单 事 件 等 等 在 这 些 界 面 事 件 发 生 时,Android 界 面 框 架 调 用 界 面 控 件 的 事 件 处 理 函 数 对 事 件 进 行 处 理 Android 系 统 界 面 事 件 的 传 递 和 处 理 遵 循 以 下 规 则 如 果 界 面 控 件 设 置 了 事 件 监 听 器, 则 事 件 将 先 传 递 给 事 件 监 听 器 如 果 界 面 控 件 没 有 设 置 事 件 监 听 器, 界 面 事 件 则 会 直 接 传 递 给 界 面 控 件 的 其 他 事 件 处 理 函 数 即 使 界 面 控 件 设 置 了 事 件 监 听 器, 界 面 事 件 也 可 以 再 次 传 递 给 其 他 事 件 处 理 函 数 是 否 继 续 传 递 事 件 给 其 他 处 理 函 数 是 由 事 件 监 听 器 处 理 函 数 的 返 回 值 决 定 的

56 如 果 监 听 器 处 理 函 数 的 返 回 值 为 true, 表 示 该 事 件 已 经 完 成 处 理 过 程, 不 需 要 其 他 处 理 函 数 参 与 处 理 过 程, 这 样 事 件 就 不 会 再 继 续 进 行 传 递 如 果 监 听 器 处 理 函 数 的 返 回 值 为 false, 则 表 示 该 事 件 没 有 完 成 处 理 过 程, 或 需 要 其 他 处 理 函 数 捕 获 到 该 事 件, 事 件 会 被 传 递 给 其 他 的 事 件 处 理 函 数 在 MVC 模 型 中, 控 制 器 根 据 界 面 事 件 (UI Event) 类 型 不 同, 将 事 件 传 递 给 界 面 控 件 不 同 的 事 件 处 理 函 数 按 键 事 件 (KeyEvent) 将 传 递 给 onkey() 函 数 进 行 处 理 触 摸 事 件 (TouchEvent) 将 传 递 给 ontouch() 函 数 进 行 处 理 Android 界 面 框 架 支 持 对 按 键 事 件 的 监 听, 并 能 够 将 按 键 事 件 的 详 细 信 息 传 递 给 处 理 函 数 为 了 处 理 控 件 的 按 键 事 件, 先 需 要 设 置 按 键 事 件 的 监 听 器, 并 重 载 onkey() 函 数 Android 界 面 框 架 支 持 对 触 摸 事 件 的 监 听, 并 能 够 将 触 摸 事 件 的 详 细 信 息 传 递 给 处 理 函 数, 需 要 设 置 触 摸 事 件 的 监 听 器, 并 重 载 ontouch () 函 数 实 验 步 骤 以 下 以 EditText 控 件 中 的 按 键 事 件 为 例, 说 明 Android 系 统 按 键 事 件 传 递 和 处 理 过 程 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 KeyEventDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 最 上 方 的 EditText 控 件 是 输 入 字 符 的 区 域, 中 间 的 CheckBox 控 件 用 来 控 制 onkey() 函 数 的 返 回 值, 选 择 后 将 阻 止 按 键 事 件 传 递 给 界 面 元 素, 按 键 内 容 就 不 能 显 示 在 EditText 控 件 中 最 下 方 的 TextView 控 件 用 来 显 示 按 键 事 件 的 详 细 信 息, 包 括 按 键 动 作 按 键 代 码 重 复 次 数 硬 件 编 码 和 按 键 标 志 3) 在 没 有 选 中 CheckBox 控 件 时, 按 下 音 量 键, 最 下 方 的 TextView 控 件 显 示 了 按 键 的 详 细 信 息, 由 于 没 有 选 择 阻 止 事 件 传 递, 按 键 内 容 将 显 示 在 EditText 控 件 中, 如 图 所 示 : 图 KeyEvent 效 果 图

57 4) 在 选 中 CheckBox 控 件 时, 按 下 音 量 键, 最 下 方 的 TextView 控 件 显 示 了 按 键 的 详 细 信 息, 由 于 选 择 阻 止 事 件 传 递, 按 键 内 容 将 不 显 示 在 EditText 控 件 中, 如 图 所 示 : 图 阻 止 事 件 传 递 KeyEvent 效 果 图 以 下 以 TouchEventDemo 为 例, 说 明 Android 系 统 触 摸 事 件 传 递 和 处 理 过 程 1) 将 范 例 程 序 TouchEventDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 浅 蓝 色 区 域 是 可 以 接 受 触 摸 事 件 的 区 域, 用 户 可 以 在 Android 模 拟 器 中 使 用 鼠 标 点 击 屏 幕, 用 以 模 拟 触 摸 手 机 屏 幕 下 方 黑 色 区 域 是 显 示 区 域, 用 来 显 示 触 摸 事 件 的 类 型 相 对 坐 标 绝 对 坐 标 触 点 压 力 触 点 尺 寸 等 信 息 3) 接 触 触 摸 事 件 的 区 域, 其 相 关 信 息 将 显 示 在 下 方 的 TextView 控 件 中, 如 图 所 示 : 图 TouchEvent 效 果 图

58 第 四 章 组 件 间 通 信 Android & linux 系 统 与 应 用 开 发 本 章 节 主 要 介 绍 使 用 Intent 进 行 组 件 通 信 的 原 理, 使 用 Intent 启 动 Activity 的 方 法, 获 取 Activity 返 回 值 的 方 法,Intent 过 滤 器 的 原 理 与 匹 配 机 制, 发 送 和 接 收 广 播 消 息 的 方 法 4.1 Intent 对 象 及 其 属 性 Intent 是 一 个 动 作 的 完 整 描 述, 包 含 了 动 作 的 产 生 组 件 接 收 组 件 和 传 递 的 数 据 信 息 Intent 也 可 称 为 一 个 在 不 同 组 件 之 间 传 递 的 消 息, 这 个 消 息 在 到 达 接 收 组 件 后, 接 收 组 件 会 执 行 相 关 的 动 作 Intent 为 Activity Service 和 BroadcastReceiver 等 组 件 提 供 交 互 能 力 Intent 的 用 途 : 启 动 Activity 和 Service; 在 Android 系 统 上 发 布 广 播 消 息 ; 广 播 消 息 可 以 是 接 收 到 特 定 数 据 或 消 息, 也 可 以 是 手 机 的 信 号 变 化 或 电 池 的 电 量 过 低 等 信 息. Intent 主 要 有 以 下 四 个 重 要 属 性, 它 们 分 别 为 : Action:Action 属 性 的 值 为 一 个 字 符 串, 它 代 表 了 系 统 中 已 经 定 义 了 一 系 列 常 用 的 动 作 通 过 setaction() 方 法 或 在 清 单 文 件 AndroidManifest.xml 中 设 置 默 认 为 :DEFAULT Data:Data 通 常 是 URI 格 式 定 义 的 操 作 数 据 例 如 :tel://, 通 过 setdata() 方 法 设 置 Category:Category 属 性 用 于 指 定 当 前 动 作 (Action) 被 执 行 的 环 境 通 过 addcategory() 方 法 或 在 清 单 文 件 AndroidManifest.xml 中 设 置 默 认 为 :CATEGORY_DEFAULT Extras:Extras 属 性 主 要 用 于 传 递 目 标 组 件 所 需 要 的 额 外 的 数 据, 通 过 putextras() 方 法 设 置 4.2 系 统 标 准 ActivityAction 应 用 实 验 目 的 了 解 使 用 Intent 启 动 Activity 的 方 法 ; 掌 握 获 取 Activity 返 回 值 的 方 法

59 4.2.2 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 在 Android 系 统 中, 应 用 程 序 一 般 都 有 多 个 Activity,Intent 可 以 实 现 不 同 Activity 之 间 的 切 换 和 数 据 传 递, 启 动 Activity 方 式, 显 式 启 动, 必 须 在 Intent 中 指 明 启 动 的 Activity 所 在 的 类 隐 式 启 动,Android 系 统 根 据 Intent 的 动 作 和 数 据 来 决 定 启 动 哪 一 个 Activity, 也 就 是 说 在 隐 式 启 动 时,Intent 中 只 包 含 需 要 执 行 的 动 作 和 所 包 含 的 数 据, 而 无 需 指 明 具 体 启 动 哪 一 个 Activity, 选 择 权 有 Android 系 统 和 最 终 用 户 来 决 定 显 式 启 动 使 用 Intent 显 式 启 动 Activity, 创 建 一 个 Intent, 指 定 当 前 的 应 用 程 序 上 下 文 以 及 要 启 动 的 Activity 把 创 建 好 的 这 个 Intent 作 为 参 数 传 递 给 startactivity() 方 法 关 键 代 码 如 下 : Intent intent = new Intent(IntentDemo.this, ActivityToStart.class); startactivity(intent); 隐 式 启 动 优 点 : 不 需 要 指 明 需 要 启 动 哪 一 个 Activity, 而 由 Android 系 统 来 决 定, 有 利 于 使 用 第 三 方 组 件 隐 式 启 动 Activity 时,Android 系 统 在 应 用 程 序 运 行 时 解 析 Intent, 并 根 据 一 定 的 规 则 对 Intent 和 Activity 进 行 匹 配, 使 Intent 上 的 动 作 数 据 与 Activity 完 全 吻 合 匹 配 的 Activity 可 以 是 应 用 程 序 本 身 的, 也 可 以 是 Android 系 统 内 置 的, 还 可 以 是 第 三 方 应 用 程 序 提 供 的 因 此, 这 种 方 式 更 加 强 调 了 Android 应 用 程 序 中 组 件 的 可 复 用 性 默 认 情 况 下 调 用 内 置 Web 浏 览 器 代 码 如 下 : Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(" startactivity(intent); Intent 语 法 如 下 : Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlString)); Activity 中 获 取 返 回 值 在 很 多 情 况 下, 后 启 动 的 Activity 是 为 了 让 用 户 对 特 定 信 息 进 行 选 择, 在 关 闭 这 个 Activity 后, 用 户 的 选 择 信 息 需 要 返 回 给 未 关 闭 的 那 个 Activity 按 照 Activity 启 动 的 先 后 顺 序, 先 启 动 的 称 为 父 Activity, 后 启 动 的 称 为 子 Activity 如 果 需 要 将 子 Activity 的 部 分 信 息 返 回 给 父 Activity, 则 可 以 使 用

60 Sub-Activity 的 方 式 去 启 动 子 Activity 获 取 子 Activity 的 返 回 值, 一 般 可 以 分 为 以 下 三 个 步 骤 : 以 Sub-Activity 的 方 式 启 动 子 Activity 设 置 子 Activity 的 返 回 值 在 父 Activity 中 获 取 返 回 值 以 Sub-Activity 的 方 式 启 动 子 Activity 代 码 如 下 : Int SUBACTIVITY = 1; Intent intent = new Intent( this, SubActivity1.class); startactivityforresult(intent,subactivity1); 下 面 代 码 说 明 如 何 在 子 Activity 中 设 置 返 回 值 : Uri data = Uri.parse("tel:" + tel_number); Intent result = new Intent(null, data); result.putextra("address", " "); setresult(result_ok, result); finish(); 在 父 Activity 中 获 取 返 回 值, 当 子 Activity 关 闭 时, 启 动 它 的 父 Activity 的 onactivityresult() 函 数 将 被 调 用 ; 如 果 需 要 在 父 Activity 中 处 理 子 Activity 的 返 回 值, 则 重 载 此 函 数 即 可, 此 函 数 的 语 法 如 下 : public void onactivityresult(int requestcode, int resultcode, Intent data); 实 验 步 骤 下 面 将 通 过 示 例 演 示 Intent 显 示 启 动 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 IntentDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 单 击 跳 转 到 Actibity2 按 钮 后, 程 序 将 启 动 Activity2 这 个 Activity, 如 图 所 示 : 图 IntentDemo 效 果 图 下 面 将 通 过 示 例 演 示 Intent 隐 式 启 动 : 1) 将 范 例 程 序 WebViewIntentDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 在 文 本 框 中 输 入 要 访 问 的 网 址 后, 通 过 单 击 Go 按 钮, 程 序 根 据 输 入 的 网 址 生 成 一 个 Intent, 并 以 隐 式 启 动 的 方 式 调 用 Android 的 Web 浏 览 器, 并 打 开 指 定 的 Web 页 面 如 图 所 示 :

61 图 WebViewIntentDemo 效 果 图 下 面 将 通 过 示 例 演 示 获 取 Activity 返 回 值 : 1) 将 范 例 程 序 ActivityCommunication 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 2) 单 击 启 动 Acivity1 按 钮 和 启 动 Acivity2 按 钮, 程 序 分 别 启 动 两 个 不 同 的 子 Acivity SubAtivity1 提 供 了 一 个 输 入 框, 已 经 接 受 和 撤 销 按 钮, 在 输 入 框 输 入 信 息 后 单 击 接 受 按 钮, 信 息 会 被 传 递 给 父 Activity, 如 果 单 击 撤 销 按 钮, 则 程 序 不 会 向 父 Activity 传 递 如 何 信 息 SubAtivity2 主 要 为 了 说 明 如 何 在 父 Activity 中 处 理 多 个 子 Activity 图 ActivityCommunication 主 界 面 图 SubActivity1 和 SubActivity2 界 面

62 图 SubActivity1 传 递 信 息 到 父 Activity 4.3 Intent 过 滤 器 实 验 目 的 了 解 Android 应 用 编 程 中 Intent 过 滤 器 的 使 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 Intent 过 滤 器 是 一 种 根 据 Intent 中 的 动 作 (Action) 类 别 (Categorie) 和 数 据 (Data) 等 内 容, 对 适 合 接 收 该 Intent 的 组 件 进 行 匹 配 和 筛 选 的 机 制 Intent 过 滤 器 可 以 匹 配 数 据 类 型 路 径 和 协 议, 还 包 括 可 以 用 来 确 定 多 个 匹 配 项 顺 序 的 优 先 级 (Priority) 应 用 程 序 的 Activity 组 件 Service 组 件 和 BroadcastReceiver 都 可 以 注 册 Intent 过 滤 器, 则 这 些 组 件 在 特 定 的 数 据 格 式 上 就 可 以 产 生 相 应 的 动 作 注 册 Intent 过 滤 器 注 册 Intent 过 滤 器 方 法 如 下 :

63 在 AndroidManifest.xml 文 件 的 各 个 组 件 的 节 点 下 定 义 <intent-filter> 节 点, 然 后 在 <intent-filter> 节 点 中 声 明 该 组 件 所 支 持 的 动 作 执 行 的 环 境 和 数 据 格 式 等 信 息 表 <intent-filter> 节 点 的 标 签 和 属 性 标 签 属 性 说 明 <action> android:name 指 定 组 件 所 能 响 应 的 动 作, 用 字 符 串 表 示, 通 常 使 用 Java 类 名 和 包 的 完 全 限 定 名 构 成 <category> android:category 指 定 以 何 种 方 式 去 服 务 Intent 请 求 的 动 作 <data> android:mimetype 指 定 组 件 能 处 理 的 数 据 类 型 android:path 有 效 的 URI 路 径 名 android:port 主 机 的 有 效 端 口 android:scheme 所 需 要 的 特 定 的 协 议 android:host 指 定 一 个 有 效 的 主 机 名 <category> 标 签 用 来 指 定 Intent 过 滤 器 的 服 务 方 式, 每 个 Intent 过 滤 器 可 以 定 义 多 个 <category> 标 签, 程 序 开 发 人 员 可 使 用 自 定 义 的 类 别, 或 使 用 Android 系 统 提 供 的 类 别 表 Android 系 统 提 供 的 类 别 值 说 明 ALTERNATIVE Intent 数 据 默 认 动 作 的 一 个 可 替 换 的 执 行 方 法 SELECTED_ALTERNATIVE 和 ALTERNATIVE 类 似, 但 替 换 的 执 行 不 是 定 向 的, 而 是 被 解 析 出 来 的 BROWAABLE 声 明 Activity 可 以 有 浏 览 器 启 动 DEFAULT 为 Intent 过 滤 器 中 定 义 的 数 据 提 供 默 认 动 作 HOME 设 备 启 动 后 显 示 的 第 一 个 Activity LANCHER 在 应 用 程 序 启 动 时 首 先 被 显 示 AndroidManifest.xml 文 件 中 的 每 个 组 件 的 <intent-filter> 都 被 解 析 成 一 个 Intent 过 滤 器 对 象 当 应 用 程 序 安 装 到 Android 系 统 时, 所 有 的 组 件 和 Intent 过 滤 器 都 会 注 册 到 Android 系 统 中 这 样, Android 系 统 便 知 道 了 如 何 将 任 意 一 个 Intent 请 求 通 过 Intent 过 滤 器 映 射 到 相 应 的 组 件 上 Intent 解 析 Intent 到 Intent 过 滤 器 的 映 射 过 程 称 为 Intent 解 析 Intent 解 析 可 以 在 所 有 的 组 件 中, 找 到 一 个 可 以 与 请 求 的 Intent 达 成 最 佳 匹 配 的 Intent 过 滤 器 Intent 解 析 的 匹 配 规 则,Android 系 统 把 所 有 应 用 程 序 包 中 的 Intent 过 滤 器 集 合 在 一 起, 形 成 一 个 完 整 的 Intent 过 滤 器 列 表, 在 Intent 与 Intent 过 滤 器 进 行 匹 配 时,Android 系 统 会 将 列 表 中 所 有 Intent 过 滤 器 的 动 作 和 类 别 与 Intent 进 行 匹 配, 任 何 不 匹 配 的 Intent 过 滤 器 都 将 被 过 滤 掉 没 有 指 定 动 作 的 Intent 过 滤 器 可 以 匹 配 任 何 的 Intent, 但 是 没 有 指 定 类 别 的 Intent 过 滤 器 只 能 匹 配 没 有 类 别 的 Intent 把 Intent 数 据 Uri 的 每 个 子 部 与 Intent 过 滤 器 的 <data> 标 签 中 的 属 性 进 行 匹 配, 如 果 <data> 标 签 指 定 了 协 议 主

64 机 名 路 径 名 或 MIME 类 型, 那 么 这 些 属 性 都 要 与 Intent 的 Uri 数 据 部 分 进 行 匹 配, 任 何 不 匹 配 的 Intent 过 滤 器 均 被 过 滤 掉 如 果 Intent 过 滤 器 的 匹 配 结 果 多 于 一 个, 则 可 以 根 据 在 <intent-filter> 标 签 中 定 义 的 优 先 级 标 签 来 对 Intent 过 滤 器 进 行 排 序, 优 先 级 最 高 的 Intent 过 滤 器 将 被 选 择 实 验 步 骤 下 面 将 通 过 示 例 Intent Filter 演 示 Intent 过 滤 器 的 应 用 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 Intents Filters 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 图 Intents Filters 效 果 图 2) 当 点 击 空 Action 的 Activity 的 时 候, 会 报 异 常, 因 为 Intent 什 么 都 没 有 设 置, 没 有 任 何 的 Activity 能 处 理 它 当 点 击 Action 检 测 -Activity 的 时 候 会 打 开 我 们 的 ActionActivity 这 个 Activity, 点 击 Action 检 测 -Broadcast 会 弹 出 Toast 提 示, 说 明 已 经 被 接 收 到 图 测 试 Intents Filters 效 果 图 3) 从 上 面 我 们 可 以 看 出, 当 Intent 设 置 了 Action 时, 只 要 对 应 的 组 件 的 Intent Filter 中 包 含 该 Action 的 定 义, 那 么 这 个 组 件 就 会 接 收 该 Intent

65 4.4 广 播 信 息 实 验 目 的 了 解 Android 应 用 编 程 中 通 过 Intent 发 送 广 播 消 息 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 应 用 程 序 和 Android 系 统 都 可 以 使 用 Intent 发 送 广 播 消 息, 广 播 消 息 的 内 容 可 以 与 应 用 程 序 密 切 相 关 的 数 据 信 息, 也 可 以 Android 的 系 统 信 息, 例 如 网 络 连 接 变 化 电 池 电 量 变 化 接 收 到 短 信 和 系 统 设 置 变 化 等 等 如 果 应 用 程 序 注 册 了 BroadcastReceiver, 则 可 以 接 收 到 指 定 的 广 播 消 息 广 播 信 息 的 使 用 方 法 首 先, 创 建 一 个 Intent, 注 意 : 在 构 造 Intent 时 必 须 用 一 个 全 局 唯 一 的 字 符 串 标 识 其 要 执 行 的 动 作, 通 常 使 用 应 用 程 序 包 的 名 称 调 用 sendbroadcast() 函 数, 就 可 把 Intent 携 带 的 消 息 广 播 出 去 如 果 要 在 Intent 传 递 额 外 数 据, 可 以 用 Intent 的 putextra() 方 法 代 码 如 下 : Intent intent = new Intent ("com.x210.broadcast"); // 识 别 广 播 消 息 的 字 符 串 标 识 intent.putextra("message", edittext.gettext().tostring()); sendbroadcast(intent);// 发 送 广 播 信 息 广 播 信 息 发 送 后, 利 用 BroadcastReceiver 监 听 广 播 消 息 具 体 方 法 是 在 AndroidManifest.xml 文 件 或 在 代 码 中 注 册 一 个 BroadcastReceiver, 并 在 其 中 使 用 Intent 过 滤 器 指 定 要 处 理 的 广 播 消 息 BroadcastReceiver 的 应 用 程 序 不 需 要 一 直 运 行, 当 Android 系 统 接 收 到 与 之 匹 配 的 广 播 消 息 时, 会 自 动 启 动 此 BroadcastReceiver 基 于 以 上 的 特 征,BroadcastReceiver 适 合 做 一 些 资 源 管 理 的 工 作 在 BroadcastReceiver 接 收 到 与 之 匹 配 的 广 播 消 息 后,onReceive() 方 法 会 被 调 用 onreceive() 方 法 必 须 要 在 5 秒 钟 执 行 完 毕, 否 则 Android 系 统 会 认 为 该 组 件 失 去 响 应, 并 提 示 用 户 强 行 关 闭 该 组 件 创 建 BroadcastReceiver 需 要 继 承 BroadcastReceiver 类, 并 重 载 onreceive() 方 法 代 码 如 下 : public class MyBroadcastReceiver extends BroadcastReceiver

66 public void onreceive(context context, Intent intent) { } //TODO: React to the Intent received. } 实 验 步 骤 下 面 将 通 过 BroadcastReceiverDemo 示 例 介 绍 发 送 广 播 消 息 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 BroadcastReceiverDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 在 输 入 框 中 输 入 要 发 送 的 信 息 图 BroadcastReceiverDemo 界 面 2) 单 击 发 送 按 钮,EditText 控 件 中 的 内 容 将 以 广 播 消 息 的 形 式 发 送 出 去 图 广 播 消 息 发 送 界 面

67 第 五 章 数 据 存 储 与 访 问 Android & linux 系 统 与 应 用 开 发 本 章 节 主 要 介 绍 SharedPreferences 的 使 用 方 法, 各 种 文 件 存 储 的 区 别 与 适 用 情 况,SQLite 数 据 库 的 特 点 和 体 系 结 构,SQLite 数 据 库 的 建 立 和 操 作 方 法,ContentProvider 的 用 途 和 原 理, ContentProvider 的 创 建 与 使 用 方 法 5.1 简 单 存 储 实 验 目 的 了 解 SharedPreferences 的 使 用 方 法 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 SharedPreferences 是 一 种 轻 量 级 的 数 据 保 存 方 式, 通 过 SharedPreferences 可 以 将 NVP (Name/Value Pair, 名 称 / 值 对 ) 保 存 在 Android 的 文 件 系 统 中, 而 且 SharedPreferences 完 全 屏 蔽 的 对 文 件 系 统 的 操 作 过 程, 开 发 人 员 仅 是 通 过 调 用 SharedPreferences 对 NVP 进 行 保 存 和 读 取 SharedPreferences 不 仅 能 够 保 存 数 据, 还 能 够 实 现 不 同 应 用 程 序 间 的 数 据 共 享, SharedPreferences 支 持 三 种 访 问 模 式 : 私 有 (MODE_PRIVATE): 仅 有 创 建 程 序 有 权 限 对 其 进 行 读 取 或 写 入 ; 全 局 读 (MODE_WORLD_READABLE): 不 仅 创 建 程 序 可 以 对 其 进 行 读 取 或 写 入, 其 他 应 用 程 序 也 读 取 操 作 的 权 限, 但 没 有 写 入 操 作 的 权 限 ; 全 局 写 (MODE_WORLD_WRITEABLE): 创 建 程 序 和 其 他 程 序 都 可 以 对 其 进 行 写 入 操 作, 但 没 有 读 取 的 权 限

68 在 使 用 SharedPreferences 前, 先 定 义 SharedPreferences 的 访 问 模 式 下 面 的 代 码 将 访 问 模 式 定 义 为 私 有 模 式 : public static int MODE = MODE_PRIVATE; 有 的 时 候 需 要 将 SharedPreferences 的 访 问 模 式 设 定 为 即 可 以 全 局 读, 也 可 以 全 局 写, 这 样 就 需 要 将 两 种 模 式 写 成 下 面 的 方 式 : public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE; 定 义 完 访 问 模 式 后, 需 定 义 SharedPreferences 的 名 称, 这 个 名 称 与 在 Android 文 件 系 统 中 保 存 的 文 件 同 名 因 此, 只 要 具 有 相 同 的 SharedPreferences 名 称 的 NVP 内 容, 都 会 保 存 在 同 一 个 文 件 中 public static final String PREFERENCE_NAME = "SaveSetting"; 为 了 可 以 使 用 SharedPreferences, 需 要 将 访 问 模 式 和 SharedPreferences 名 称 作 为 参 数, 传 递 到 getsharedpreferences() 函 数, 并 获 取 到 SharedPreferences 对 象 代 码 如 下 : SharedPreferences sharedpreferences = getsharedpreferences(preference_name, MODE); 在 获 取 到 SharedPreferences 对 象 后, 则 可 以 通 过 SharedPreferences.Editor 类 对 SharedPreferences 进 行 修 改, 最 后 调 用 commit() 函 数 保 存 修 改 内 容 SharedPreferences 广 泛 支 持 各 种 基 本 数 据 类 型, 包 括 整 型 布 尔 型 浮 点 型 和 长 型 等 等 代 码 如 下 : SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putstring("name", "Tom"); editor.putint("age", 20); editor.putfloat("height", ); editor.commit(); 如 果 需 要 从 已 经 保 存 的 SharedPreferences 中 读 取 数 据, 同 样 是 调 用 getsharedpreferences() 函 数, 并 在 函 数 的 第 1 个 参 数 中 指 明 需 要 访 问 的 SharedPreferences 名 称, 最 后 通 过 get<type>() 函 数 获 取 保 存 在 SharedPreferences 中 的 NVP 代 码 如 下 : SharedPreferences sharedpreferences = getsharedpreferences(preference_name, MODE); String name = sharedpreferences.getstring("name","default Name"); int age = sharedpreferences.getint("age", 20); float height = sharedpreferences.getfloat("height",); 实 验 步 骤 下 面 将 通 过 SimplePreferenceDemo 示 例 具 体 说 明 SharedPreferences 的 文 件 保 存 位 置 和 保 存 格 式 及 其 读 取 :

69 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 SimplePreferenceDemo 通 过 Import -> Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 图 SimplePreferenceDemo 界 面 2) 在 界 面 上 输 入 信 息 后, 然 后 退 出, 即 关 闭 Activity 时 SharedPreferences 进 行 保 存, 当 在 应 用 程 序 中 找 到 这 个 应 用 重 新 开 启 时, 保 存 在 SharedPreferences 的 信 息 将 被 读 出 来, 并 重 新 呈 现 在 用 户 界 面 上 图 重 启 SharedPreferences 界 面 3)SharedPreferences 是 以 XML 的 格 式 被 自 动 保 存 的, 实 例 运 行 后, 在 DDMS 中 的 File Explorer 相 应 目 录 下 可 以 看 到 一 个 叫 SETTING_infos.xml, 如 图 所 示 :

70 图 SharedPreferences 内 容 保 存 位 置 4) 将 SETTING_infos.xml 导 出 至 设 备, 其 代 码 如 下 : <?xml version="1.0" encoding="utf-8" standalone="true"?> -<map> <float value="1.81" name="height"/> <string name="name">tom </string> </map> 5.2 文 件 存 储 实 验 目 的 了 解 各 种 文 件 存 储 的 区 别 与 适 用 情 况 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 Android 使 用 的 是 基 于 Linux 的 文 件 系 统, 程 序 开 发 人 员 可 以 建 立 和 访 问 程 序 自 身 的 私 有 文 件, 也 可 以 访 问 保 存 在 资 源 目 录 中 的 原 始 文 件 和 XML 文 件, 还 可 以 在 SD 卡 等 外 部 存 储 设 备 中 保 存 文 件 内 部 存 储 Android 系 统 允 许 应 用 程 序 创 建 仅 能 够 自 身 访 问 的 私 有 文 件, 文 件 保 存 在 设 备 的 内 部 存 储 器 上,

71 在 Linux 系 统 下 的 /data/data/<package name>/files 目 录 中 Android 系 统 不 仅 支 持 标 准 Java 的 IO 类 和 方 法, 还 提 供 了 能 够 简 化 读 写 流 式 文 件 过 程 的 函 数 主 要 介 绍 的 两 个 函 数 openfileoutput() openfileinput() openfileoutput() 函 数 为 写 入 数 据 做 准 备 而 打 开 的 应 用 程 序 私 文 件, 如 果 指 定 的 文 件 不 存 在, 则 创 建 一 个 新 的 文 件 openfileoutput() 函 数 的 语 法 格 式 如 下 : public FileOutputStream openfileoutput(string name, int mode) 第 1 个 参 数 是 文 件 名 称, 这 个 参 数 不 可 以 包 含 描 述 路 径 的 斜 杠 第 2 个 参 数 是 操 作 模 式,Android 系 统 支 持 四 种 文 件 操 作 模 式 : 表 Android 系 统 支 持 四 种 文 件 操 作 模 式 模 式 说 明 MODE_PRIVATE 私 有 模 式, 缺 陷 模 式, 文 件 仅 能 够 被 文 件 创 建 程 序 访 问, 或 具 有 相 同 UID 的 程 序 访 问 MODE_APPEND 追 加 模 式, 如 果 文 件 已 经 存 在, 则 在 文 件 的 结 尾 处 添 加 新 数 据 MODE_WORLD_READABLE 全 局 读 模 式, 允 许 任 何 程 序 读 取 私 有 文 件 MODE_WORLD_WRITEABLE 全 局 写 模 式, 允 许 任 何 程 序 写 入 私 有 文 件 openfileinput() 函 数 为 打 开 应 用 程 序 私 文 件 为 从 其 中 读 取 数 据 做 准 备 openfileinput() 函 数 的 语 法 格 式 如 下 : public FileInputStream openfileinput (String name) 外 部 存 储 Android 的 外 部 存 储 设 备 指 的 是 SD 卡 (Secure Digital Memory Card), 是 一 种 广 泛 使 用 于 数 码 设 备 上 的 记 忆 卡 不 是 所 有 的 Android 手 机 都 有 SD 卡, 但 Android 系 统 提 供 了 对 SD 卡 的 便 捷 的 访 问 方 法 Android 模 拟 器 支 持 SD 卡, 但 模 拟 器 中 没 有 缺 省 的 SD 卡, 开 发 人 员 须 在 模 拟 器 中 手 工 添 加 SD 卡 的 映 像 文 件 使 用 <Android SDK>/tools 目 录 下 的 mksdcard 工 具 创 建 SD 卡 映 像 文 件, 命 令 如 下 : mksdcard -l SDCARD E:\android\sdcard_file 第 1 个 参 数 -1 表 示 后 面 的 字 符 串 是 SD 卡 的 标 签, 这 个 新 建 立 的 SD 卡 的 标 签 是 SDCARD 第 2 个 参 数 256M 表 示 SD 卡 的 容 量 是 256 兆 最 后 一 个 参 数 表 示 SD 卡 映 像 文 件 的 保 存 位 置, 上 面 的 命 令 将 映 像 保 存 在 E:\android 目 录 下 sdcard_file 文 件 中 在 CMD 中 执 行 该 命 令 后, 则 可 在 所 指 定 的 目 录 中 找 到 生 产 的 SD 卡 映 像 文 件 测 试 SD 卡 映 像 是 否 正 确 加 载, 在 模 拟 器 启 动 后, 使 用 FileExplorer 向 SD 卡 中 随 意 上 传 一 个 文 件, 如 果 文 件 上 传 成 功, 则 表 明 SD 卡 映 像 已 经 成 功 加 载 编 程 访 问 SD 卡, 首 先 需 要 检 测 系 统 的 /sdcard 目 录 是 否 可 用 如 果 不 可 用, 则 说 明 设 备 中 的

72 SD 卡 已 经 被 移 除, 在 Android 模 拟 器 则 表 明 SD 卡 映 像 没 有 被 正 确 加 载 如 果 可 用, 则 直 接 通 过 使 用 标 准 的 Java.io.File 类 进 行 访 问 资 源 文 件 程 序 开 发 人 员 可 以 将 程 序 开 发 阶 段 已 经 准 备 好 的 原 始 格 式 文 件 和 XML 文 件 分 别 存 放 在 /res/raw 和 /res/xml 目 录 下, 供 应 用 程 序 在 运 行 时 进 行 访 问 原 始 格 式 文 件 可 以 是 任 何 格 式 的 文 件, 例 如 视 频 格 式 文 件 音 频 格 式 文 件 图 像 文 件 和 数 据 文 件 等 等, 在 应 用 程 序 编 译 和 打 包 时,/res/raw 目 录 下 的 所 有 文 件 都 会 保 留 原 有 格 式 不 变 /res/xml 目 录 下 的 XML 文 件, 一 般 用 来 保 存 格 式 化 的 数 据, 在 应 用 程 序 编 译 和 打 包 时 会 将 XML 文 件 转 换 为 高 效 的 二 进 制 格 式, 应 用 程 序 运 行 时 会 以 特 殊 的 方 式 进 行 访 问 实 验 步 骤 下 面 将 通 过 示 例 演 示 内 部 存 储 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 InternalFileDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 图 InternalFileDemo 示 例 界 面 2) 在 文 本 框 中 输 入 信 息 后, 单 击 写 入 文 件 按 钮, 信 息 将 被 保 存 到 设 备 的 内 部 存 储 器 上, 在 DDMS 中 的 File Explorer 相 应 目 录 下 (data->data->com.x210.interalfile->files) 可 以 看 到 一 个 叫 filedemo.txt 文 件, 如 图 所 示 :

73 图 InternalFileDemo 内 容 保 存 位 置 3) 单 击 读 取 文 件 按 钮, 信 息 会 显 示 到 下 方 的 TextView 控 件 中, 下 边 的 选 择 框 用 来 控 制 输 入 信 息 是 否 要 附 加 到 先 前 的 信 息 中 图 读 取 文 件 界 面 下 面 将 通 过 示 例 演 示 外 部 存 储 : 1) 将 范 例 程 序 SDcardFileDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 如 图 所 示 : 图 SDcardFileDemo 示 例 界 面

74 2) 单 击 生 成 随 机 数 按 钮, 随 机 数 显 示 在 下 方, 单 击 写 入 SD 卡 按 钮, 随 机 数 将 被 保 存 到 /sdcard/ 目 录 下 一 个 txt 文 件 内 图 写 入 SD 卡 界 面 下 面 将 通 过 示 例 演 示 访 问 资 源 文 件 : 1) 将 范 例 程 序 ResourceFileDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 单 击 读 取 原 始 文 件 按 钮, 程 序 将 读 取 res/raw/ raw_file.txt 文 件 并 将 内 容 显 示 在 界 面 上, 如 图 所 示 : 图 读 取 原 始 文 件 2) 单 击 读 取 XML 文 件 按 钮, 程 序 将 读 取 /res/xml/people/.xml 文 件, 并 将 内 容 显 示 在 界 面 上, 如 图 所 示 :

75 3) 单 击 清 除 显 示 按 钮, 可 以 清 除 显 示 图 读 取 XML 文 件 5.3 数 据 库 存 储 实 验 目 的 了 解 SQLite 数 据 库 并 掌 握 其 基 本 应 用 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 SQLite 数 据 库 具 有 很 强 的 移 植 性, 可 以 运 行 在 Windows,Linux,BSD,Mac OS X 和 一 些 商 用 Unix 系 统, 比 如 Sun 的 Solaris,IBM 的 AIX SQLite 数 据 库 也 可 以 工 作 在 许 多 嵌 入 式 操 作 系 统 下, 例 如 QNX,VxWorks,Palm OS,Symbin 和 Windows CE SQLite 的 核 心 大 约 有 3 万 行 标 准 C 代 码, 模 块 化 的 设 计 使 这 些 代 码 更 加 易 于 理 解 手 动 建 立 数 据 库 指 的 是 使 用 sqlite3 工 具, 通 过 手 工 输 入 命 令 行 完 成 数 据 库 的 建 立 过 程 sqlite3 是 SQLite 数 据 库 自 带 的 一 个 基 于 命 令 行 的 SQL 命 令 执 行 工 具, 并 可 以 显 示 命 令 执 行 结 果 sqlite3 工 具 被 集 成 在

76 Android 系 统 中, 用 户 在 Linux 的 命 令 行 界 面 中 输 入 sqlite3 可 启 动 sqlite3 工 具, 并 得 到 工 具 的 版 本 信 息 启 动 Linux 的 命 令 行 界 面 的 方 法 是 在 CMD 中 输 入 adb shell 命 令 : # sqlite3 SQLite version Enter.help for instructions sqlite> 在 启 动 sqlite3 工 具 后, 提 示 符 从 # 变 为 sqlite>, 表 示 命 令 行 界 面 进 入 与 SQLite 数 据 库 的 交 互 模 式, 此 时 可 以 输 入 命 令 建 立 删 除 或 修 改 数 据 库 的 内 容 正 确 退 出 sqlite3 工 具 的 方 法 是 使 用.exit 命 令 : 原 则 上, 每 个 应 用 程 序 的 数 据 库 都 保 存 在 各 自 的 /data/data/<package name>/databases 目 录 下, 但 如 果 使 用 手 工 方 式 建 立 数 据 库, 则 必 须 手 工 建 立 数 据 库 目 录, 目 前 版 本 无 须 修 改 数 据 库 目 录 的 权 限 在 SQLite 数 据 库 中, 每 个 数 据 库 保 存 在 一 个 独 立 的 文 件 中, 使 用 sqlite3 工 具 后 加 文 件 名 的 方 式 打 开 数 据 库 文 件, 如 果 指 定 文 件 不 存 在,sqlite3 工 具 则 自 动 创 建 新 文 件, 下 面 的 代 码 将 创 建 名 为 people 的 数 据 库, 在 文 件 系 统 中 将 产 生 一 个 名 为 people.db 的 数 据 库 文 件 # sqlite3 people.db SQLite version Enter.help for instructions sqlite> 新 创 建 的 数 据 库 中, 构 造 了 一 个 名 为 peopleinfo 的 表, 使 用 create table 命 令 为 了 确 认 数 据 表 是 否 创 建 成 功, 可 以 使 用.tables 命 令, 显 示 当 前 数 据 库 中 的 所 有 表 当 然, 也 可 以 使 用.schema 命 令 查 看 建 立 表 时 使 用 的 SQL 命 令 向 peopleinfo 表 中 添 加 数 据, 使 用 insert into values 命 令 在 数 据 添 加 完 毕 后, 使 用 select 命 令, 显 示 指 定 数 据 表 中 的 所 有 数 据 信 息, 命 令 格 式 为 [select 属 性 from 表 名 ] 可 以 使 用 mode 命 令 将 结 果 输 出 格 式 更 改 为 表 格 方 式,mode 命 令 除 了 支 持 常 见 的 column 格 式 为, 还 支 持 csv 格 式 html 格 式 insert 格 式 line 格 式 list 格 式 tabs 格 式 和 tcl 格 式 更 新 数 据 可 以 使 用 update 命 令, 命 令 格 式 为 [update 表 名 set 属 性 = 新 值 where 条 件 ] 删 除 数 据 可 以 使 用 delete 命 令, 命 令 格 式 为 [delete from 表 名 where 条 件 ] sqlite3 工 具 还 支 持 大 量 的 命 令, 可 以 使 用.help 命 令 查 询 sqlite3 的 命 令 列 表 代 码 建 库 在 代 码 中 动 态 建 立 数 据 库 是 比 较 常 用 的 方 法, 在 程 序 运 行 过 程 中, 当 需 要 进 行 数 据 库 操 作 时, 应 用 程 序 会 首 先 尝 试 打 开 数 据 库, 此 时 如 果 数 据 库 并 不 存 在, 程 序 则 会 自 动 建 立 数 据 库, 然 后 再 打 开 数 据 库 在 编 程 实 现 时, 一 般 将 所 有 对 数 据 库 的 操 作 都 封 装 在 一 个 类 中, 因 此 只 要 调 用 这 个 类, 就 可 以 完 成 对 数 据 库 的 添 加 更 新 删 除 和 查 询 等 操 作 代 码 建 库 主 要 通 过 SQLiteOpenHelper 类 来 实 现 建 立 数 据 库,SQLiteOpenHelper 是 个 抽 象 类, 在 该 类 中 有 如 下 两 个 抽 象 方 法,SQLiteOpenHelper 的 子 类 必 须 实 现 这 两 个 方 法

77 public abstract void oncreate(sqlitedatabase db); public abstract void onupdate(sqlitedatabase db,int oldversion,int newversion); SQLiteOpenHelper 会 自 动 检 测 数 据 库 文 件 是 否 存 在 如 果 存 在, 会 打 开 这 个 数 据 库, 在 这 种 情 况 下 就 不 会 调 用 oncreate() 方 法 如 果 数 据 库 文 件 不 存 在,SQLiteOpenHelper 首 先 会 创 建 一 个 数 据 库 文 件, 然 后 打 开 这 个 数 据 库, 最 后 调 用 oncreate() 方 法 因 此,onCreate() 方 法 一 般 用 来 在 新 创 建 的 数 据 库 中 建 立 表 视 图 等 数 据 库 组 建 也 就 是 说 oncreate() 方 法 在 数 据 库 文 件 第 一 次 创 建 时 调 用 如 果 数 据 库 文 件 存 在, 会 调 用 onupdate() 方 法 升 级 数 据 库, 并 更 新 版 本 号 SQLiteDatabase 类, 是 Android 提 供 的 封 装 了 一 些 数 据 库 操 作 的 API 的 类, 使 用 该 类 可 以 完 成 对 数 据 库 的 添 加 删 除 更 新 和 查 找 等 功 能 数 据 操 作 数 据 操 作 是 指 对 数 据 的 添 加 删 除 查 找 和 更 新 的 操 作, 通 过 执 行 SQL 命 名 完 成 数 据 操 作, 但 推 荐 使 用 Android 提 供 的 专 用 类 和 方 法, 这 些 类 和 方 法 更 加 简 洁 易 用 为 了 使 DBAdapter 类 支 持 对 数 据 的 添 加 删 除 更 新 和 查 找 等 功 能, 在 DBAdapter 类 中 增 加 下 面 的 这 些 函 数 : insert(people people) 用 来 添 加 一 条 数 据 ; queryalldata() 用 来 获 取 全 部 数 据 ; queryonedata(long id) 根 据 id 获 取 一 条 数 据 ; deletealldata() 用 来 删 除 全 部 数 据 ; deleteonedata(long id) 根 据 id 删 除 一 条 数 据 ; updateonedata(long id, People people) 根 据 id 更 新 一 条 数 据 实 验 步 骤 下 面 将 通 过 示 例 演 示 SQLite 数 据 库 存 储 的 基 本 操 作 : 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 SQLiteDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上

78 图 SQLiteDemo 示 例 界 面 2) 单 击 其 中 的 任 何 一 条 记 录, 便 可 以 查 看 其 详 细 信 息,DBHelper 类 封 装 了 增 删 改 查 的 方 法, 但 本 例 中 用 到 的 并 不 多, 只 用 了 查 询 的 方 法 图 记 录 详 细 信 息 查 看 界 面 5.4 数 据 共 享 实 验 目 的 了 解 ContentProvider 的 用 途 和 原 理 ; 了 解 ContentProvider 的 创 建 与 使 用 方 法

79 5.4.2 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 ContentProvider( 数 据 提 供 者 ) 是 在 应 用 程 序 间 共 享 数 据 的 一 种 接 口 机 制,ContentProvider 提 供 了 更 为 高 级 的 数 据 共 享 方 法, 应 用 程 序 可 以 指 定 需 要 共 享 的 数 据, 而 其 他 应 用 程 序 则 可 以 在 不 知 数 据 来 源 路 径 的 情 况 下, 对 共 享 数 据 进 行 查 询 添 加 删 除 和 更 新 等 操 作 许 多 Android 系 统 的 内 置 数 据 也 通 过 ContentProvider 提 供 给 用 户 使 用, 例 如 通 讯 录 音 视 频 文 件 和 图 像 文 件 等 在 创 建 ContentProvider 时, 需 要 首 先 使 用 数 据 库 文 件 系 统 或 网 络 实 现 底 层 存 储 功 能, 然 后 在 继 承 ContentProvider 的 类 中 实 现 基 本 数 据 操 作 的 接 口 函 数, 包 括 添 加 删 除 查 找 和 更 新 等 功 能 调 用 者 不 能 够 直 接 调 用 ContentProvider 的 接 口 函 数, 而 需 要 使 用 ContentResolver 对 象, 通 过 URI 间 接 调 用 ContentProvider ContentResolver URI ContenProvider 文 件 系 统 数 据 库 网 络 图 ContentProvider 调 用 关 系 程 序 开 发 人 员 使 用 ContentResolver 对 象 与 ContentProvider 进 行 交 互, 而 ContentResolver 则 通 过 URI 确 定 需 要 访 问 的 ContentProvider 的 数 据 集 在 发 起 一 个 请 求 的 过 程 中,Android 首 先 根 据 URI 确 定 处 理 这 个 查 询 的 ContentResolver, 然 后 初 始 化 ContentResolver 所 有 需 要 的 资 源, 这 个 初 始 化 的 工 作 是 Android 系 统 完 成 的, 无 需 程 序 开 发 人 员 参 与 一 般 情 况 下 只 有 一 个 ContentResolver 对 象, 但 却 可 以 同 时 与 多 个 ContentResolver 进 行 交 互 ContentProvider 完 全 屏 蔽 了 数 据 提 供 组 件 的 数 据 存 储 方 法 在 使 用 者 看 来, 数 据 提 供 者 通 过 ContentProvider 提 供 了 一 组 标 准 的 数 据 操 作 接 口, 却 无 法 得 知 数 据 提 供 者 的 数 据 存 储 方 数 据 提 供 者 可 以 使 用 SQLite 数 据 库 存 储 数 据, 也 可 以 通 过 文 件 系 统 或 SharedPreferences 存 储 数 据, 甚 至 是 使 用 网 络 存 储 的 方 法, 这 些 内 容 对 数 据 使 用 者 都 是 不 可 见 同 时 也 正 是 因 为 屏 蔽 数 据 的 存 储 方 法, 很 大 程 度 上 简 化 的

80 ContentProvider 的 使 用 难 度, 使 用 者 只 要 调 用 ContentProvider 提 供 的 接 口 函 数, 就 可 完 成 所 有 的 数 据 操 作 URI 是 通 用 资 源 标 志 符 (Uniform Resource Identifier), 用 来 定 位 任 何 远 程 或 本 地 的 可 用 资 源 ContentProvider 使 用 的 URI 语 法 结 构 如 下 : content://<authority>/<data_path>/<id> content:// 是 通 用 前 缀, 表 示 该 URI 用 于 ContentProvider 定 位 资 源, 无 需 修 改 <authority> 是 授 权 者 名 称, 用 来 确 定 具 体 由 哪 一 个 ContentProvider 提 供 资 源 因 此, 一 般 <authority> 都 由 类 的 小 写 全 称 组 成, 以 保 证 唯 一 性 <data_path> 是 数 据 路 径, 用 来 确 定 请 求 的 是 哪 个 数 据 集 <id> 可 以 指 定 某 个 ID 的 数 据 创 建 数 据 提 供 者 程 序 开 发 人 员 通 过 继 承 ContentProvider 类 可 以 创 建 一 个 新 的 数 据 提 供 者, 过 程 可 以 分 为 三 步 : 1) 继 承 ContentProvider, 并 重 载 六 个 函 数 ; 继 承 ContentProvider, 并 重 载 六 个 函 数 : delete(): 删 除 数 据 集 ; insert(): 添 加 数 据 集 ; qurey(): 查 询 数 据 集 ; update(): 更 新 数 据 集 ; oncreate(): 初 始 化 底 层 数 据 集 和 建 立 数 据 连 接 等 工 作 ; gettype(): 返 回 指 定 URI 的 MIME 数 据 类 型, 如 果 URI 是 单 条 数 据, 则 返 回 的 MIME 数 据 类 型 应 以 vnd.android.cursor.item 开 头, 如 果 URI 是 多 条 数 据, 则 返 回 的 MIME 数 据 类 型 应 以 vnd.android.cursor.dir/ 开 头 2) 声 明 CONTENT_URI, 实 现 UriMatcher; 在 新 构 造 的 ContentProvider 类 中, 通 过 构 造 一 个 UriMatcher, 判 断 URI 是 单 条 数 据 还 是 多 条 数 据 为 了 便 于 判 断 和 使 用 URI, 一 般 将 URI 的 授 权 者 名 称 和 数 据 路 径 等 内 容 声 明 为 静 态 常 量, 并 声 明 CONTENT_URI 3) 注 册 ContentProvider; 在 完 成 ContentProvider 类 的 代 码 后, 需 要 在 AndroidManifest.xml 文 件 下 进 行 注 册 注 册 ContentProvider 使 用 <ContentProvider> 标 签 使 用 数 据 提 供 者 使 用 ContentProvider 是 通 过 Android 组 件 都 具 有 的 ContentResolver 对 象, 通 过 URI 进 行 数 据 操 作 程 序 开 发 人 员 只 需 要 知 道 URI 和 数 据 集 的 数 据 格 式, 则 可 以 进 行 数 据 操 作, 解 决 不 同 应 用 程 序 之 间 的 数 据 共 享 问 题 每 个 Android 组 件 都 具 有 一 个 ContentResolver 对 象, 获 取 ContentResolver 对 象 的 方 法 是 调 用 getcontentresolver() 函 数 代 码 如 下 :

81 ContentResolver resolver = getcontentresolver(); 查 询 操 作, 在 获 取 到 ContentResolver 对 象 后, 程 序 开 发 人 员 则 可 以 使 用 query() 函 数 查 询 目 标 数 据 如 果 需 要 获 取 数 据 集 中 的 全 部 数 据, 则 可 直 接 使 用 CONTENT_URI, 此 时 ContentProvider 在 分 析 URI 时 将 认 为 需 要 返 回 全 部 数 据 代 码 如 下 : String KEY_ID = "_id"; String KEY_NAME = "name"; String KEY_AGE = "age"; String KEY_HEIGHT = "height"; Uri uri = Uri.parse(CONTENT_URI_STRING + "/" + "2"; Cursor cursor = resolver.query(uri, new String[] {KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT}, null, null, null); 添 加 操 作, 向 ContentProvider 中 添 加 数 据 有 两 种 方 法 一 种 是 使 用 insert() 函 数, 向 ContentProvider 中 添 加 一 条 数 据 另 一 种 是 使 用 bultinsert() 函 数, 批 量 的 添 加 数 据 代 码 如 下 : ContentValues values = new ContentValues(); values.put(key_name, "Tom"); values.put(key_age, 21); values.put(key_height, ); Uri newuri = resolver.insert(content_uri, values); 删 除 操 作, 需 要 使 用 delete() 函 数 如 果 需 要 删 除 单 条 数 据, 则 可 以 在 URI 中 指 定 需 要 删 除 数 据 的 ID, 如 果 需 要 删 除 多 条 数 据, 则 可 以 在 selection 中 声 明 删 除 条 件 代 码 如 下 : Uri uri = Uri.parse(CONTENT_URI_STRING + "/" + "2"); int result = resolver.delete(uri, null, null); 更 新 操 作, 需 要 使 用 update() 函 数, 参 数 定 义 与 delete() 函 数 相 同, 同 样 可 以 在 URI 中 指 定 需 要 更 新 数 据 的 ID, 也 可 以 在 selection 中 声 明 更 新 条 件 代 码 如 下 : ContentValues values = new ContentValues(); values.put(key_name, "Tom"); values.put(key_age, 21); values.put(key_height, ); Uri uri = Uri.parse(CONTENT_URI_STRING + "/" + "7"); int result = resolver.update(uri, values, null, null); 实 验 步 骤 下 面 将 通 过 示 例 演 示 ContentProvider 的 基 本 操 作 : 1 ) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 ContentProvider_Demo 通 过

82 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 图 ContentProvider_Demo 示 例 界 面 2) 单 击 添 加 信 息 按 钮, 可 以 添 加 人 物 信 息 : 图 添 加 信 息 界 面 3) 单 击 菜 单 按 钮, 弹 出 添 加 信 息 和 删 除 信 息 两 个 菜 单 : 图 操 作 菜 单 界 面 4) 单 击 删 除 信 息 按 钮, 可 以 删 除 人 物 信 息 :

83 图 删 除 信 息 界 面

84 第 六 章 多 媒 体 开 发 Android & linux 系 统 与 应 用 开 发 Android 提 供 了 常 见 媒 体 的 编 码 解 码 机 制, 因 此 可 以 非 常 容 易 地 集 成 音 频 视 频 和 图 片 等 多 媒 体 文 件 到 应 用 程 序 中 本 章 主 要 是 通 过 调 用 Android 提 供 的 现 有 API, 实 现 音 乐 播 放 器 视 频 播 放 器 录 音 和 摄 像 等 应 用 程 序 当 然, 有 些 需 要 硬 件 的 支 持, 通 过 前 面 章 节 学 习 的 Activity 和 Intent, 可 以 非 常 直 接 的 来 访 问 这 些 媒 体 文 件 6.1 在 窗 体 布 局 上 -VideoView 实 验 目 的 了 解 Android 系 统 提 供 的 内 置 的 媒 体 格 式 ; 掌 握 Android 多 媒 体 开 发 在 窗 体 布 局 上 所 需 要 调 用 的 API, 即 VideoView; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 VideoView 类 可 以 从 不 同 的 来 源, 比 如 说 文 件 系 统 和 内 容 提 供 商 的 网 站 下 载 视 频 文 件, 并 显 示 在 窗 体 布 局 上 因 为 它 可 以 配 合 窗 体 布 局 设 计 上 的 需 要 来 控 制 视 频 窗 体 的 大 小, 提 供 各 种 选 项, 比 如 缩 放 和 着 色 使 用 VideoView 类 进 行 视 频 信 息 的 显 示, 按 如 下 步 骤 操 作 即 可 : 1) 通 过 id 获 得 VideoView 实 例, 在 VideoView 类 上, 使 用 setviewpath() 方 法 来 设 置 视 频 文 件 路 径 ; String path = Environment.getExternalStorageDirectory().getPath()+"/oppc.3gp"; videoview.setvideopath(path); 2) 使 用 setmediacontroller() 方 法 来 控 制 媒 体 播 放, 使 用 start() 方 法 来 开 始 播 放 视 频

85 MediaController mediacontroller = new MediaController(this); videoview.setmediacontroller(mediacontroller); videoview.requestfocus(); videoview.start(); 实 验 步 骤 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 在 Java Eclipse 集 成 开 发 环 境 中, 单 击 window/show view/file Explorer, 选 择 FileExplorer 视 图, 在 当 前 Device 对 应 的 File Explorer 视 图, 如 图 所 示 单 击 Push 按 钮 添 加 第 6 章 \common\oppo.3gp 音 乐 文 件 到 mnt/sdcard 中 ; 图 添 加 音 乐 文 件 到 sdcard 中 2) 将 范 例 程 序 HelloVideoView 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 利 用 VideoView 控 件 播 放 视 频, 运 行 界 面 如 图 所 示 : 图 VideoView 控 件 显 示 的 视 频 信 息

86 6.2 音 频 及 视 频 播 放 -MediaPlayer 实 验 目 的 了 解 MediaPlayer 的 常 用 方 法 ; 掌 握 Android 多 媒 体 开 发 音 频 及 视 频 播 放 的 多 种 读 取 媒 体 文 件 的 方 式 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 播 放 媒 体 的 来 源 可 以 来 自 源 文 件 文 件 系 统 或 网 络 的 数 据 流 (URL) 只 能 在 标 准 的 输 出 设 备 上 播 放 音 频, 输 出 设 备 指 的 是 移 动 设 备 上 扬 声 器 或 蓝 牙 耳 机, 不 可 以 从 电 话 的 话 筒 播 放 音 频 一 般 而 言, 移 动 手 机 会 有 播 放 音 乐 用 的 扬 声 器 和 通 话 用 的 话 筒 这 里 我 们 主 用 使 用 MediaPlayer 来 实 现 音 频 及 视 频 的 播 放 功 能 从 源 文 件 中 播 放 : 使 用 MediaPlayer 类 播 放 音 频 及 视 频, 最 简 单 的 一 种 方 式 就 是 从 源 文 件 中 播 放 要 实 现 该 功 能 需 要 以 下 步 骤 1) 将 Android 支 持 的 媒 体 文 件 放 在 项 目 的 res/raw 文 件 夹 下,*.mp3 或 者 *.3gp 格 式 的 文 件 均 可, 为 了 便 于 实 验, 文 件 不 需 要 太 大,Eclipse 开 发 环 境 的 内 置 功 能 会 发 现 这 个 文 件, 并 自 动 添 加 到 R.java 文 件 中 2) 创 建 一 个 MediaPlayer 实 例, 使 用 MediaPlayer 的 静 态 方 法 MediaPlayer.create() 来 读 取 媒 体 资 源 接 着 调 用 start() 方 法 播 放 媒 体 资 源 3) 同 样, 如 果 需 要 实 现 停 止 播 放 功 能, 直 接 调 用 stop() 方 法 即 可 ; 调 用 pause() 方 法 暂 停 播 放, 如 暂 停 后 再 播 放, 需 再 次 调 用 start() 方 法 如 果 希 望 重 复 播 放, 再 调 用 start() 方 法 之 前, 必 须 调 用 reset() 和 prepare() 方 法 特 别 提 示 : 由 上 述 可 知, 从 源 文 件 中 播 放 是 放 在 < 工 程 >/res/raw, 然 后 发 布 的 时 候 被 打 成 APK 包 一 起 安 装 在 手 机 上 很 显 然 这 种 方 式 不 适 合 用 于 播 放 娱 乐 为 主 的 多 媒 体 文 件, 由 于 娱 乐 的 多 媒 体 文 件 是 经 常

87 更 新 的, 而 放 置 在 这 个 raw 下 面 的 文 件 用 户 是 没 有 权 限 更 新 的, 因 此 这 种 方 式 一 般 用 于 应 用 自 己 的 一 些 音 频 和 视 频 播 放, 如 开 机 启 动 音 按 键 音 信 息 提 示 音 等 应 用 使 用 的 声 音 MediaPlayer.create(this,R.raw.oppa); mmediaplayer.setonpreparedlistener(prelistener) 进 入 prepared 状 态 调 用 start() 方 法 播 放 媒 体 从 文 件 系 统 中 播 放 : 从 文 件 系 统 中 播 放 也 是 一 种 比 较 常 见 的 方 式 我 们 经 常 对 在 SDCard 中 的 一 些 音 频 和 视 频 文 件 进 行 直 接 播 放, 那 么 就 使 用 这 样 方 式 从 文 件 系 统 中 播 放 需 要 以 下 几 个 步 骤 : 1) 实 例 化 一 个 MediaPlayer 2) 调 用 setdatasource() 方 法 来 设 置 想 要 播 放 文 件 的 路 径, 取 得 播 放 的 媒 体 文 件 3) 首 先 调 用 prepare(), 然 后 调 用 start() 来 进 行 播 放 特 别 提 示 : 从 SDCard 中 获 取 音 频 视 频 播 放 和 从 < 工 程 >/res/raw 中 获 取 音 频 视 频 播 放 差 别 在 于 play() 方 法 中 的 mmediaplayer = new MediaPlayer(), 而 不 是 MediaPlayer.Create(), 然 后 设 置 预 处 理 监 听 器, 设 置 setdatasource(path), 其 中 的 path 是 指 定 的 音 频 文 件, 这 里 放 置 SD 卡 中 的 MP3 文 件, mmediaplayer.prepare() 开 始 预 处 理 从 网 络 中 播 放 : 随 着 3G 的 不 断 完 善 和 推 广, 自 费 不 断 降 低, 直 接 利 用 网 络 资 源 已 经 不 是 什 么 问 题 移 动 互 联 网 的 时 代 已 经 到 来 接 下 来 我 们 就 来 实 现 如 何 通 过 网 络 来 播 放 多 媒 体 文 件 要 实 现 该 功 能 有 两 种 方 法 方 法 一 : 1) 创 建 网 络 URI 实 例 2) 创 建 一 个 MediaPlayer 实 例, 通 过 传 递 URI 参 数, 使 用 MediaPlayer 的 静 态 方 法 create 完 成 MediaPlayer player = MediaPlayer.create(this,uri); 3) 调 用 start() 方 法 开 始 播 放 方 法 二 : 1) 实 例 化 一 个 MediaPlayer 2) 调 用 setdatasource() 方 法 来 设 置 想 要 播 放 文 件 的 路 径, 该 路 径 是 网 络 上 的 可 用 路 径 MediaPlayer mediaplayer = new MediaPlayer();

88 mediaplayer.setdatasource(path); 3) 首 先 调 用 prepare(), 然 后 调 用 start() 方 法 来 进 行 播 放 实 验 步 骤 视 频 播 放 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 在 Java Eclipse 集 成 开 发 环 境 中, 选 择 当 前 Device 对 应 的 File Explorer 视 图, 单 击 Push 按 钮 添 加 第 6 章 \common\oppo.3gp 音 乐 文 件 到 mnt/sdcard 中 ; 2) 将 范 例 程 序 MediaPlayerVideo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 在 surfacecreated () 方 法 测 试 播 放 本 地 音 频 文 件 方 法 playvideo(lacal_video), 运 行 界 面 如 图 所 示 : 图 播 放 本 地 视 频 文 件 视 频 大 小 改 变 图 播 放 本 地 视 频 文 件 视 频 资 源 已 准 备 好

89 音 频 播 放 图 播 放 本 地 视 频 文 件 1) 将 实 验 平 台 通 过 Min USB 连 接 上 电 脑, 在 Java Eclipse 集 成 开 发 环 境 中, 选 择 当 前 Device 对 应 的 File Explorer 视 图, 单 击 Push 按 钮 添 加 第 6 章 \common\ miss.mp3 音 乐 文 件 到 mnt/sdcard 中 ; 2) 将 范 例 程 序 MediaPlayerAudio 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 单 击 播 放 应 用 中 音 乐 文 件 按 钮, 运 行 的 界 面 如 图 所 示 : 图 播 放 本 地 音 频 文 件 3) 单 击 播 放 SDCard 音 乐 文 件 按 钮, 运 行 的 界 面 如 图 所 示 :

90 图 播 放 SDCard 音 频 文 件 6.3 音 / 视 频 的 录 制 鉴 于 现 在 大 部 分 手 机 都 提 供 了 音 频 录 制 功 能,Android 系 统 相 应 地 提 供 了 对 音 频 及 视 频 录 制 的 支 持, 当 然 这 也 需 要 有 硬 件 的 支 持 要 想 录 制 音 频 及 视 频 需 要 通 过 MediaRecorder 来 完 成 实 验 目 的 掌 握 通 过 MediaRecorder 类 来 实 现 android 音 频 录 制 的 功 能 ; 掌 握 MediaRecorder 的 一 些 常 用 的 方 法 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 MediaRecorder 类 位 于 android.media 包 中, 它 包 含 了 音 频 及 视 频 的 记 录 功 能 常 用 的 方 法 如 下 : 表 MediaRecorder 类 的 常 用 方 法 方 法 描 述 方 法 描 述 Start() 开 始 录 制 Prepare() 准 备 录 制

91 Pauser() 暂 停 录 制 Reset() 重 新 开 始 Stop() 停 止 录 制 Release() 释 放 资 源 要 实 现 音 频 及 视 频 的 录 制 的 步 骤 说 明 如 下 所 示 1) 在 工 程 的 res/dravable 目 录 下 放 置 两 个 图 片 文 件, 用 来 设 置 控 制 按 钮 的 图 片 2) 在 布 局 文 件 main.xml 中 添 加 3 个 View 组 件, 其 中 TextView 用 来 显 示 标 题, 其 余 两 个 按 钮 用 来 控 制 开 始 录 制 和 停 止 录 制 3) 创 建 Activity 类 MainActivity, 生 成 两 个 ImageButton 实 例 4) 创 建 record() 方 法, 调 用 MediaRecorder 的 start() 方 法 录 制, 同 时 使 录 制 按 钮 失 效, 使 停 止 按 钮 生 效 5) 创 建 stop() 方 法, 调 用 MediaRecorder 的 sttop() 方 法 停 止 录 制 6) 创 建 error() 方 法 捕 获 异 常 7) 创 建 setpath() 方 法, 设 置 录 音 文 件 的 存 储 位 置 8 ) 创 建 setproperty() 方 法, 设 置 MediaRecorder 的 属 性, 包 括 用 MediaRecorde r.setaudiosource() 方 法 来 设 置 音 频 源, 用 MediaRecorder.setOutputFormat() 方 法 来 设 置 输 出 文 件 格 式 9) 创 建 setup() 方 法, 使 录 制 按 钮 生 效, 使 停 止 按 钮 失 效 ; 10) 为 录 制 按 钮 添 加 单 击 事 件, 调 用 play() 方 法 录 制 11) 为 停 止 按 钮 添 加 单 击 事 件, 调 用 stop() 方 法 停 止 录 制 12) 当 实 现 的 MediaRecorder 类 完 成 音 频 的 捕 捉 后, 调 用 release() 方 法 实 验 步 骤 1) 将 范 例 程 序 MediaRecordDemo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 迷 你 录 音 器 开 始 录 音 界 面 图 迷 你 录 音 器 暂 停 录 音 界 面

92 2) 单 击 迷 你 录 音 器 的 开 按 钮 之 后, 开 始 录 音, 录 音 文 件 默 认 是 保 存 在 mnt/sdcard 中 的, 单 击 关 按 钮, 停 止 录 音, 在 Java Eclipse 集 成 开 发 环 境 中, 选 择 当 前 Device 对 应 的 File Explorer 视 图, 可 以 通 过 如 图 所 示 步 骤 将 录 音 文 件 导 出 图 迷 你 录 音 器 录 音 文 件 保 存 界 面 6.4 Camera 照 相 实 验 目 的 掌 握 通 过 Camera 类 来 实 现 android 拍 照 的 功 能 ; 掌 握 SurfaceView 视 图 组 件 SurfaceHolder 抽 象 接 口 的 一 些 常 用 的 方 法 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 手 机 除 了 可 以 录 制 音 频 视 频 外, 手 机 拍 照 已 经 不 是 什 么 新 奇 的 事 情 了,Android 相 应 地 提 供 了 手 机 拍 照 功 能 API SurfaceView: 该 类 是 一 个 视 图 组 件, 实 现 了 照 片 的 预 览 功 能 SurfaceHolder: 一 个 抽 象 接 口, 是 SurfaceView 的 支 持 类, 一 般 通 过 SurfaceView 的 getholder() 方 法 获 得 允 许 你 控 制 界 面 的 尺 寸 和 格 式 编 辑 界 面 的 像 素, 以 及 监 控 界 面 尺 寸 的 改 变

93 SurfaceHolder.Callback:SurfaceHodler 的 一 个 内 部 接 口, 可 以 实 现 该 接 口 获 取 界 面 改 变 的 信 息 该 接 口 中 有 三 个 方 法,surfaceCreated() 方 法 在 界 面 创 建 时 被 调 用, 一 般 在 该 方 法 中 打 开 照 相 机 并 设 置 预 览 SurfaceChanged() 方 法 在 界 面 尺 寸 改 变 时 被 调 用, 一 般 在 该 方 法 中 设 置 相 机 的 参 数 SufaceDestroyed() 方 法 在 界 面 被 销 毁 时 调 用, 在 该 方 法 中 清 除 相 机 实 例, 释 放 资 源 Camera: 相 机 类, 实 现 拍 照 功 能 Camera.PictureCallback:Camera 的 一 个 内 部 接 口, 处 理 照 片 准 备 好 后 的 回 调 通 过 上 面 类 的 介 绍, 可 以 实 现 一 个 拍 照 应 用 了 下 面 是 程 序 的 实 现 流 程 : 1) 创 建 一 个 Android 工 程 Camera, 实 现 MainActivity 类, 并 在 该 类 中 声 明 SurfaceView SurfaceHolder 和 Camera 对 象 2) 在 布 局 文 件 main.xml 文 件 中 添 加 SurfaceView 视 图 组 件 3) 在 oncreate() 方 法 中 获 得 SurfaceView 和 SurfaceHolder 实 例 对 象 4) 实 现 SurfaceHolder.Callback 回 调 接 口, 实 现 该 接 口 中 的 3 个 方 法 5) 创 建 SavePictureTask 任 务 类, 实 现 保 存 照 片 功 能, 主 要 是 将 从 硬 件 获 得 的 字 节 流 保 存 到 设 备 中 6) 实 现 Camera.PictureCallBack 回 调 方 法, 执 行 保 存 照 片 任 务 7) 创 建 保 存 照 片 方 法 takepic() 8) 设 置 相 应 按 键 事 件, 当 拍 照 键 或 者 搜 索 键 被 按 下 时 进 行 拍 照 实 验 步 骤 1) 本 实 验 是 实 现 一 个 Camera 拍 照 应 用, 将 范 例 程 序 CameraDemo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 ; 2) 单 击 拍 照 键 CAM, 会 听 到 咔 嚓 一 声, 在 Device 上 运 行 之 后 得 到 如 图 所 示 界 面 : 图 拍 照 应 用 在 模 拟 器 上 运 行 效 果

94 第 七 章 定 位 与 地 图 Android & linux 系 统 与 应 用 开 发 在 上 一 章 节 的 实 验 中, 主 要 了 解 了 如 何 调 用 Android 提 供 的 现 有 API 来 进 行 多 媒 体 的 开 发, 包 括 音 频 及 视 频 的 播 放 音 频 视 频 的 录 制, 以 及 照 相 功 能 的 实 现 本 章 主 要 学 习 位 置 服 务 的 相 关 概 念 地 图 密 钥 的 申 请 位 置 信 息 的 获 取 MapView 和 MapController 的 使 用 方 法 Google 地 图 覆 盖 层 的 使 用 方 法 等 7.1 位 置 服 务 实 验 目 的 掌 握 Android 系 统 中 的 提 供 位 置 服 务 的 Location API 的 使 用 方 法 ; 掌 握 Android 系 统 对 GPS 定 位 应 用 的 实 现 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 Android 支 持 GPS 和 网 络 地 图, 通 常 将 各 种 不 同 的 定 位 技 术 称 为 位 置 服 务 位 置 服 务 (Location-Based Services,LBS), 又 称 定 位 服 务 或 基 于 位 置 的 服 务, 它 通 过 电 信 运 营 商 的 无 线 电 通 信 网 络 ( 如 GSM 网 CDMA 网 ) 或 外 部 定 位 方 式 ( 如 GPS), 融 合 了 GPS 定 位 移 动 通 信 导 航 等 多 中 技 术, 获 得 移 动 终 端 用 户 的 位 置 信 息, 为 移 动 用 户 提 供 了 于 控 件 位 置 相 关 的 综 合 应 用 服 务 位 置 服 务 首 先 在 日 本 得 到 商 业 化 的 应 用 2001 年 7 月,DoCoMo 发 布 一 第 一 款 具 有 三 角 定 位 功 能 的 手 持 设 备 ;2001 年 12 月,KDDI 发 布 了 第 一 款 具 有 GPS 功 能 的 手 机 ; 如 今, 基 于 位 置 的 服 务 发 展 迅 速, 已 涉 及 商 务 医 疗 工 作 和 生 活 的 各 个 方 面, 为 用 户 提 供 定 位 追 踪 和 敏 感 区 域 警 告 等 一 系 列 服 务

95 Android Location API Android 平 台 支 持 提 供 位 置 服 务 的 API 主 要 包 括 以 下 几 种 LocationMananger 可 以 用 来 获 取 当 前 的 位 置, 追 踪 设 备 的 移 动 路 线, 或 设 定 敏 感 区 域, 在 进 入 或 离 开 敏 感 区 域 时 设 备 会 发 出 特 定 警 报 LocationProviders 是 能 够 提 供 定 位 功 能 的 组 件 集 合, 集 合 中 的 每 种 组 件 以 不 同 的 技 术 提 供 设 备 的 当 前 位 置, 区 别 在 于 定 位 的 精 度 速 度 和 成 本 等 方 面 LocationListener 接 口 用 于 接 收 从 LocationManager 的 位 置 发 生 改 变 时 的 通 知 如 果 LocationListener 被 注 册 添 加 到 LocationManager 对 象, 并 且 此 LocationManager 对 象 调 用 了 requestlocationupdates(string provider, long mintime, float mindistance, LocationListener listener) 方 法, 那 么 接 口 中 的 相 关 方 法 将 会 被 调 用 其 常 用 方 法 如 表 所 示 : 表 LocationListener 类 的 方 法 方 法 名 称 方 法 描 述 onlocationchanged(location location) 当 位 置 发 生 改 变 时 被 调 用 onproviderdisabled(string provider) 在 provider 被 用 户 关 闭 被 调 用 onproviderenabled(string provider) 在 provider 被 用 户 开 启 后 调 用 onstatuschanged(string provider, int status, 在 provider 的 状 态 在 可 用 暂 时 不 可 以 和 无 服 务 三 Bundle extras) 个 状 态 直 接 切 换 时 被 调 用 Location 类, 表 示 某 一 特 定 时 间 地 理 位 置 的 相 关 信 息 其 方 法 如 表 所 示 getlatitude() getlongitude() getaccuracy() getaltitude() gettime() getspeed() getbearing() 方 法 名 称 表 Location 类 的 方 法 方 法 描 述 获 取 纬 度 Latitude 获 取 经 度 Longitude 获 取 精 度 Accuracy 获 取 高 度 Altitude 获 取 时 间 Time 获 取 速 度 Speed 获 取 方 位 Bearing GPS 定 位 实 现 : 1) 提 供 位 置 服 务, 需 要 获 得 LocationManager 对 象 使 用 LOCATION_SERVICE 参 数 调 用 android.app.activity.getsystemservice() 函 数 获 取 一 个 LocationManager 实 例 2) 选 择 LocationManager 的 定 位 方 法 在 获 取 到 LocationManager 后, 还 需 要 指 定 LocationManger 的 定 位 方 法, 然 后 才 能 够 调 用 LocationManager,LocationManager 支 持 的 定 位 方 法 有 以 下 两 种 : GPS 定 位 : 可 以 提 供 更 加 精 确 的 位 置 信 息, 但 定 位 速 度 和 质 量 受 到 卫 星 数 量 和

96 环 境 情 况 的 影 响 网 络 定 位 : 提 供 的 位 置 信 息 精 确 度 差, 但 是 速 度 较 GPS 定 位 快 表 LocationManager 支 持 的 定 位 方 法 比 较 静 态 常 量 值 说 明 GPS_PROVIDER Gps 使 用 GPS 定 位, 利 用 卫 星 提 供 精 确 的 位 置 信 息, 需 要 用 户 权 限 : android.permission.access_fine_location NETWORK_PROVIDER getlongitude() 使 用 网 络 定 位, 利 用 基 站 或 WIFI 提 供 近 似 的 位 置 信 息, 需 要 具 有 如 下 权 限 : android.permission.access_coarse_location 或 android.permission.access_fine_location 3) 以 使 用 GPS 定 位 为 例, 得 到 Location 对 象 之 后, 调 用 Location 中 的 getlatitude() 和 getlongitude() 方 法 得 到 位 置 信 息 中 的 纬 度 和 精 度 4) 利 用 requestlocationupdate() 方 法 启 动 位 置 信 息 的 接 收 LocationManager 提 供 了 一 种 便 捷 高 效 的 位 置 监 视 方 法 requestlocationupdates(), 可 以 根 据 位 置 的 距 离 变 化 和 时 间 间 隔 设 定 产 生 位 置 改 变 事 件 的 条 件, 这 样 可 以 比 卖 弄 因 微 小 的 距 离 变 化 而 产 生 大 量 的 位 置 改 变 事 件 5) 为 了 使 GPS 定 位 功 能 生 效, 还 需 要 在 AndroidManifest.xml 文 件 中 加 入 用 户 许 可 没 有 这 些 权 限, 应 用 程 序 在 运 行 时 是 无 法 获 取 到 位 置 更 新 的 6) 位 置 服 务 一 般 都 需 要 使 用 设 备 上 的 硬 件, 且 GPS 信 号 受 到 很 多 条 件 的 限 制, 天 气 状 况 建 筑 物 遮 挡, 所 以 实 验 时 要 拿 手 持 设 备 去 户 外 测 试 实 验 步 骤 1) 本 次 实 验 是 通 过 GPS 定 位 获 取 到 当 前 位 置, 将 范 例 程 序 LocationBasedServiceDemo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 ; 图 打 开 设 置 选 择 位 置 和 安 全 图 选 中 使 用 GPS 卫 星

97 图 显 示 当 前 位 置 信 息 7.2 Google 地 图 应 用 实 验 目 的 掌 握 Android 中 编 写 Google Map 应 用 所 需 要 的 Google APIs 的 使 用 方 法 掌 握 编 写 Google Map 应 用 中 申 请 地 图 密 钥 的 方 法 ; 重 点 掌 握 通 过 Baidu Map SDK 来 实 现 一 个 android Map 显 示 的 应 用 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 编 写 Google Map 的 应 用 首 先 需 要 Google APIs 借 助 Google APIs, 用 户 可 以 在 地 图 上 显 示 当 前 的 地 理 位 置 在 Android 中 定 义 了 一 个 名 为 com.google.android.maps 的 包, 其 中 包 含 了 一 系 列 用 于 在 GoogleMap 上 显 示 控 制 和 层 叠 信 息 的 功 能 类 因 此, 首 先 需 要 在 项 目 中 导 入 Google Map API 默 认 情 况 下 是 Android 某 个 版 本 比 如 Android2.3, 现 在 需 要 改 为 对 应 版 本 的 Google APIs, 版 本 要 和 Android 版 本 一 致 在 默 认 的 情 况 下

98 Google API 是 没 有 的 这 个 Google APIs 是 同 版 本 的 Android 超 集, 包 含 了 Google 的 私 有 应 用 API 申 请 Google 地 图 密 钥 在 导 入 Google Map API 之 后, 我 们 需 要 向 Google 申 请 一 组 经 过 验 证 的 地 图 密 钥 (Map API Key), 地 图 密 钥 是 访 问 Google 地 图 数 据 的 密 钥, 无 论 是 模 拟 器 还 是 在 真 实 设 备 中 需 要 使 用 这 个 密 钥 然 后 使 用 MapView(com.google.android.maps.MapView) 就 可 以 将 Google 地 图 嵌 入 Android 应 用 程 序 中, 才 能 正 常 使 用 Google 的 地 图 服 务 要 得 到 Google 网 站 的 签 署 取 得 地 图 密 钥 授 权, 首 先 要 申 请 一 个 Google 账 号, 也 就 是 Gmail 邮 箱, 申 请 地 址 是 然 后, 找 到 保 存 Debug 的 keystore 的 保 存 位 置, 并 获 取 证 书 的 MD5 散 列 值 这 里 的 keystore 是 一 个 密 码 保 护 的 文 件, 用 来 存 储 Android 提 供 的 用 于 调 试 的 证 书, 获 取 MD5 散 列 值 的 主 要 目 的 是 为 下 一 步 申 请 地 图 密 钥 做 准 备 获 取 证 书 的 保 存 地 址, 首 先 打 开 Eclipse, 通 过 Window/preferces 命 令 打 开 配 置 窗 体, 在 Android/Build 选 项 中 的 Default debug keystore 中 可 以 找 到, 如 图 所 示 : 图 获 取 证 书 的 保 存 地 址 为 了 获 取 Debug 证 书 MD5 的 散 列 值, 需 要 打 开 命 令 行 工 具 CMD, 然 后 切 换 到 keystroe 的 目 录, 输 入 清 单 命 令 :Keytool list keystore debug.keystore; 如 果 提 示 无 法 找 到 keytool, 可 以 将 <Java JDK>/bin 的 路 径 添 加 到 系 统 的 PATH 变 量 中 在 提 示 输 入 keystore 密 码 时, 输 入 默 认 密 码 andriod,md5 散 列 值 将 显 示 在 最 下 方, 笔 者 的 MD5 散 列 值 为 C5:D2:6B:54:82:CF:B3:E9:6E:FC:F5:C9:D7:85:CC:4B, 如 图 所 示 :

99 图 获 取 Debug 证 书 MD5 散 列 值 申 请 地 图 密 钥 的 最 后 一 步 是 打 开 申 请 页 面, 输 入 MD5 散 列 值 申 请 页 面 的 地 址 是 该 地 址 要 通 过 代 理 服 务 器 来 访 问 使 用 Google 地 图 使 用 Google 地 图 需 要 使 用 到 Android 定 义 的 com.google.android.maps 包, 其 中 包 含 了 一 系 列 用 于 Google Map 上 显 示 控 制 和 层 叠 信 息 的 功 能 类 该 类 主 要 包 括 以 下 几 个 类 MapActivity: 这 个 类 用 于 显 示 Google Map 的 Activity 类, 它 需 要 连 接 底 层 网 络 任 何 想 要 显 示 MapView 的 Activity 都 需 要 继 承 MapActivity, 并 在 其 oncreate() 方 法 中 创 建 一 个 MapView 对 象 MapView 的 地 图 的 显 示 控 件, 可 以 设 置 不 同 的 显 示 模 式, 例 如 卫 星 模 式 街 道 模 式 或 者 交 通 模 式 MapController 则 是 MapView 的 控 制 器, 可 以 控 制 MapView 的 显 示 中 心 和 缩 放 级 别 等 功 能 Overlay: 可 显 示 于 地 图 之 上 的 可 绘 制 对 象 GeoPoint: 包 含 经 纬 位 置 的 对 象 特 别 注 意 : 由 于 获 取 Google 地 图 是 需 要 使 用 互 联 网 的, 所 以 在 运 行 前 还 需 要 在 AndroidManifest.xml 文 件 中 添 加 允 许 访 问 互 联 网 的 许 可 即 需 要 添 加 android.permission.internet 权 限 申 请 Baidu 地 图 API Key 和 使 用 Google map api 一 样, 在 使 用 百 度 地 图 API 之 前 也 需 要 获 取 相 应 的 API Key 百 度 地 图

100 API Key 与 你 的 百 度 账 户 相 关 联, 因 此 您 必 须 先 有 百 度 帐 户, 才 能 获 得 API Key; 并 且, 该 Key 与 您 引 用 API 的 程 序 名 称 有 关 百 度 API Key 的 申 请 要 比 Google 的 简 单 多 了, 其 实 只 要 你 有 百 度 帐 号, 应 该 不 超 过 30 秒 就 能 完 成 API Key 的 申 请 申 请 地 址 : 图 申 请 Baidu 地 图 Api key 网 页 使 用 Overlay 通 过 在 MapView 上 添 加 覆 盖 层, 可 以 在 指 定 的 位 置 上 添 加 注 解 绘 制 图 像 等 Google 地 图 上 可 以 加 入 多 个 覆 盖 层, 所 有 覆 盖 层 均 在 地 图 图 层 之 上, 每 个 覆 盖 层 均 可 以 对 用 户 的 点 击 事 件 做 出 响 应 创 建 覆 盖 层 继 承 Overlay 类 的 子 类, 并 通 过 重 载 draw() 方 法 为 指 定 位 置 添 加 注 解, 重 载 ontap() 方 法 处 理 用 户 的 点 击 操 作 在 覆 盖 层 绘 制 图 形 或 文 字 需 要 使 用 画 布 Canvas 来 实 现, 绘 制 的 位 置 是 屏 幕 坐 标, 这 就 需 要 将 地 图 上 的 物 理 坐 标 于 屏 幕 坐 标 进 行 转 换 ;Projection 类 提 供 了 物 理 坐 标 和 屏 幕 坐 标 的 转 换 功 能, 可 以 在 经 度 和 纬 度 表 示 的 GeoPoint 点 和 屏 幕 上 Point 点 进 行 转 换,toPixels() 方 法 将 物 理 坐 标 转 换 为 屏 幕 坐 标,formPixels() 方 法 将 屏 幕 坐 标 转 换 为 物 理 坐 标 TextOverlay 类 是 MapOverlayDemo 实 例 的 覆 盖 层, 主 要 重 载 了 draw() 方 法, 在 指 定 的 物 理 坐 标 上 绘 制 了 标 记 点 和 提 示 文 字 建 立 了 覆 盖 层 之 后, 还 需 要 将 覆 盖 层 添 加 到 MapView 上 实 验 步 骤 1) 由 于 要 使 用 Google 地 图 API, 注 册 key 时 要 使 用 代 理 服 务 器 访 问, 或 者 通 过 国 外 的 朋 友 帮 你 注 册, 而 这 一 般 难 以 办 到, 考 虑 到 我 们 只 是 作 为 学 习 使 用, 所 以 在 接 下 来 的 实 验 中 我 们 会 通 过 调 用 Baidu Map API 来 实 现 地 图 显 示

101 2) 本 实 验 主 要 是 调 用 Baidu Map API 来 在 显 示 地 图 信 息, 将 范 例 程 序 BaiduMapsApiDemo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 将 应 用 中 的 DemoApplication.java 里 的 strkey 更 改 为 自 己 注 册 的 key, 还 要 注 意 的 是, 要 保 证 实 验 平 台 能 正 常 连 上 互 联 网 : public static final String strkey = "220A6F1E8B889B08D4EE682B7CBD251F987E1C55"; 3) 在 实 验 平 台 对 应 的 Device 设 备 上 运 行, 运 行 界 面 如 图 所 示 : 图 应 用 程 序 欢 迎 界 面 图 单 击 BaseMapDemo 选 项 显 示 地 图

102 图 单 击 RoutePlanDemo 选 项 在 地 图 上 显 示 路 线 图 单 击 CloudSearchDemo 选 项 卡 详 细 搜 索 地 图 信 息 图 单 击 offinedemo 选 项 卡 扫 描 离 线 包

103 第 八 章 Android 中 的 图 形 图 像 Android 处 理 图 形 的 能 力 非 常 强 大, 对 于 2D 图 形 的 处 理 不 使 用 Java API 处 理,Android 系 统 定 义 了 一 系 列 处 理 2D 图 形 的 处 理 类, 这 些 类 分 别 位 于 android.graphics android.graphics.drawbable.shapes 和 android.view.animation 包 中 对 于 3D 图 形 的 处 理 Android 使 用 OPenGL ES, 这 些 类 位 于 javax.microedition.khronos.opengles 和 android.opengl 包 中 Android 系 统 中 图 形 大 体 上 分 两 类, 一 是 静 态 图 形 的 处 理, 也 就 是 不 经 常 变 化 的 图 片, 如 icon logo 动 画 等 对 于 这 种 类 型 的 图 片 通 过 各 种 Drawable 类 来 处 理, 这 种 方 式 一 般 是 将 图 片 放 在 res/drawable 目 录 或 者 res/animation 目 录 中 对 于 动 态 图 片 ( 大 小 位 置 格 式 经 常 变 化 的 图 片 ), 一 般 采 用 不 断 的 重 新 绘 制 绘 制 的 方 式 来 处 理, 例 如 游 戏 中 场 景 角 色 和 道 具 等 8.1 在 Android 中 访 问 图 片 实 验 目 的 掌 握 Android 系 统 中 通 过 使 用 图 片 文 件 创 建 Drawable 对 象 ; 掌 握 Android 系 统 中 通 过 Bitmap 和 BitmapFactory 两 个 类 来 读 取 文 件 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 图 片 在 Android 系 统 中 随 处 可 见 例 如, 列 表 图 标 快 捷 方 式 图 标 图 片 按 钮 等 在 Android 中 我 们 通 过 使 用 Drawable 类 来 完 成 对 图 片 的 操 作 Drawable 类 有 很 多 个 子 类, 如 用 来 操 作 位 图 的 BitmapDrawable 类 用 来 操 作 颜 色 的 ColorDrawable 类, 以 及 用 来 操 作 各 种 形 状 的 ShapeDrawable 类

104 可 以 通 过 以 下 3 种 方 法 来 实 例 化 Drawable 对 象 : 一 是 使 用 保 存 在 工 程 中 的 一 个 图 片 文 件 ; 二 是 使 用 XML 文 件 定 义 Drawable 属 性 ; 三 是 构 造 方 法 实 例 化, 这 种 方 法 在 实 际 开 发 中 一 般 用 不 到 使 用 图 片 文 件 创 建 Drawable 对 象 最 简 单 的 一 种 方 式 是 在 工 程 的 资 源 文 件 下 面 保 存 图 片, 该 图 片 会 被 Eclipse 自 动 加 载 到 R.java 文 件 中, 然 后 可 以 通 过 R.drawable.image 使 用 该 图 片 对 象 使 用 XML 文 件 定 义 Drawable 属 性 在 布 局 文 件 中 定 义 Drawable 属 性 例 如, 可 以 在 布 局 文 件 中 定 义 图 片 按 钮 的 图 片 及 应 用 程 序 的 图 标 等 代 码 演 示 了 如 何 在 AndroidManifest.xml 配 置 文 件 中 引 用 资 源 图 标 <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > 也 可 以 通 过 这 种 方 式 来 配 置 ImageView 的 图 片 资 源 如 代 码 所 示 : <ImageView android:id="@+id/imageview01" android:layout_height="wrap_content" /> Bitmap 和 BitmapFactory 除 了 以 上 提 到 的 两 种 图 片 处 理 方 式 以 外, 还 可 以 将 图 片 文 件 保 存 在 SDCard 中, 此 时 我 们 可 以 通 过 Bitmap 和 BitmapFactory 两 个 类 来 读 取 文 件 实 验 步 骤 使 用 图 片 文 件 创 建 Drawable 对 象 1) 将 范 例 程 序 drawalbe_1 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 从 本 地 资 源 文 件 中 加 载 图 片

105 从 SDCard 中 读 取 图 片 文 件 并 将 其 设 置 为 壁 纸 1) 在 Java Eclipse 集 成 开 发 环 境 中, 选 择 当 前 Device 对 应 的 File Explorer 视 图, 单 击 Push 按 钮 添 加 第 8 章 \common\haibao.jpg 到 mnt/sdcard 中 ; 2) 将 范 例 程 序 drawalbe_0 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 从 SDCard 中 读 取 图 片 文 件 并 将 其 设 置 为 壁 纸 8.2 Android 中 的 动 画 实 验 目 的 掌 握 Android 系 统 中 Tween 动 画 的 两 种 编 码 方 式 ; 掌 握 Android 系 统 中 通 过 配 置 文 件 对 Frame 动 画 的 实 现 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP

106 8.2.3 实 验 原 理 在 Android 系 统 中 提 供 了 两 种 动 画 实 现 方 式 : 一 种 是 Tween 动 画, 通 过 视 图 组 件 移 动 放 大 缩 小, 以 及 产 生 透 明 度 的 变 化 等 来 实 现 动 画 ; 另 外 一 种 是 Frame 动 画, 这 是 一 种 传 统 的 通 过 顺 序 播 放 排 列 好 的 图 片 来 实 现 的 动 画 方 法, 类 似 电 影 Tween 动 画 Tween 动 画 能 完 成 一 系 列 诸 如 位 置 尺 寸 透 明 度 和 旋 转 等 简 单 的 变 化 例 如, 对 程 序 中 的 ImageView 组 件, 可 以 通 过 Tween 动 画 使 该 视 图 实 现 放 大 缩 小 旋 转 渐 变 等 变 化 Tween 动 画 类 位 于 android.view.animation 包 中, 该 包 中 包 含 了 一 些 常 用 的 动 画 实 现 类 Animation: 动 画 抽 象 类, 其 他 几 个 实 现 类 继 承 该 类 ScaleAnimation: 控 制 尺 寸 变 化 的 动 画 类 AlphaAnimation: 控 制 透 明 度 变 化 的 动 画 类 TranslateAnimation: 控 制 位 置 变 化 的 动 画 类 AnimationSet: 定 义 动 画 属 性 集 合 类 AnimationUtils: 动 画 工 具 类 所 以, 在 Android 系 统 中,Tween 动 画 有 4 种 表 现 方 式 : 渐 变 缩 放 平 移 旋 转 Tween 动 画 可 以 通 过 两 种 编 码 方 式 来 实 现 : 一 种 是 直 接 通 过 硬 编 码 的 方 式 在 程 序 代 码 中 实 现 ; 另 一 种 是 在 配 置 文 件 中 定 义 对 于 Android 系 统 来 讲, 建 议 使 用 配 置 文 件 的 方 法, 这 种 方 式 可 扩 展 性 较 高, 便 于 维 护 Frame 动 画 Frame 动 画 是 顺 序 播 放 图 片 来 产 生 动 画 效 果 的, 类 似 电 影 例 如, 要 实 现 一 个 人 物 走 动 的 动 画, 可 以 通 过 三 张 图 片 来 实 现, 第 一 张 两 脚 都 着 地, 第 二 张 左 脚 着 地, 第 三 张 右 脚 着 地 然 后 顺 序 播 放 就 实 现 任 务 行 走 的 动 画 效 果 了 Frame 动 画 是 通 过 AnimationDrawable 类 实 现 的, 该 类 中 的 两 个 重 要 方 法 是 start() 和 stop(), 分 别 用 来 开 始 和 停 止 动 画 动 画 一 般 通 过 XML 配 置 文 件 来 进 行 配 置, 在 工 程 的 res/anim 目 录 下 创 建 一 个 XML 配 置 文 件, 该 配 置 文 件 中 有 一 个 <animation-list> 根 元 素 和 若 干 个 <item> 子 元 素 实 验 步 骤 1) 在 Java Eclipse 集 成 开 发 环 境 中, 选 择 当 前 Device 对 应 的 File Explorer 视 图, 单 击 Push 按 钮 添 加 第 8 章 \common\haibao.jpg 到 mnt/sdcard 中 ; 2) 将 范 例 程 序 GraphicAnimation 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 单 击 各 种 类 型

107 的 按 钮, 运 行 界 面 如 图 所 示 : 图 Test 尺 寸 变 化 动 画 图 Test 渐 变 动 画 图 Test 位 置 变 化 动 画 图 Test 旋 转 动 画 3) 将 范 例 程 序 Graphic_Animation 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 ; 该 项 目 与 上 面 执 行 的 Graphic_Animation 产 生 的 效 果 相 同, 只 是 该 项 目 是 使 用 XML 配 置 文 件 实 现 的 动 画 效 果 读 者 可 以 自 行 去 实 验, 在 这 里 就 不 再 演 示 8.3 动 态 图 形 绘 制 实 验 目 的 掌 握 Android 系 统 中 使 用 Canvas 对 象 在 界 面 上 绘 制 不 同 的 图 形 ; 掌 握 Android 系 统 中 Paint 类 Color 类 Path 类 的 常 用 属 性 和 方 法 ;

108 8.3.2 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 在 Android 中 如 何 绘 制 图 形, 其 中 涉 及 到 的 工 具 类 都 和 形 象, 我 们 首 先 需 要 一 张 画 布, 这 里 就 是 Android 中 的 Canvas; 其 次 还 需 要 画 笔, 这 里 就 是 Android 中 的 Paint; 再 次 需 要 不 同 的 颜 色, 这 里 就 是 Android 中 的 Color 接 下 来, 如 果 要 画 线 还 需 要 连 接 路 径, 这 里 就 是 Android 中 的 Path 我 们 还 可 以 借 助 工 具 直 接 画 出 各 种 图 形 如 圆 形 椭 圆 矩 形 等, 这 里 就 是 Android 中 的 ShapeDrawable 类, 当 然 它 还 有 很 多 子 类, 例 如 OvalShape( 椭 圆 ) RectShape( 矩 形 ) 等 Canvas Canvas 类 主 要 实 现 了 屏 幕 的 绘 制 过 程, 其 中 包 含 了 很 多 实 用 的 方 法, 比 如 绘 制 一 条 路 径 区 域 贴 图 画 点 画 线 渲 染 文 本,Canvas 类 常 用 的 方 法 如 表 所 示 表 Canvas 类 常 用 的 方 法 方 法 名 称 方 法 描 述 drawrect(rectf rect, Paint paint) 使 用 paint 画 矩 形 rect drawtext(string text, float x, float y, Paint paint) 以 (x,y) 为 起 始 坐 标, 使 用 paint 绘 制 文 本 drawline(float startx, float starty, float stopx, float 以 ( startx, starty) 为 起 始 点 坐 标 点,(stopX, stopy) stopy, Paint paint) 为 终 止 坐 标 点, 使 用 paint 画 线 drawcircle(float cx, float cy, float radius, Paint 以 ( cx, cy) 为 原 点,radius 为 半 径 使 用 paint 画 paint) 圆 drawoval(rectf oval, Paint paint) 使 用 paint 画 矩 形 oval 的 内 切 椭 圆 cliprect(float left, float top, float right, float bottom) 剪 切 矩 形 clipregion(region region) 剪 切 区 域 Paint Paint 用 来 描 述 图 形 的 颜 色 和 风 格, 如 线 宽 颜 色 字 体 等 信 息 Paint 位 于 android.graphics 包 中, 该 类 的 详 细 方 法 如 表 所 示 Paint() setcolor(int color) setalpha(int a) reset() 方 法 名 称 表 Paint 常 用 方 法 方 法 描 述 构 造 方 法, 使 用 默 认 设 置 设 置 颜 色 设 置 Alpha 值 重 置

109 setstrokewidth(float width) settextalign(paint.align align) setshader(shader shader) 设 置 线 宽 设 置 文 字 对 齐 设 置 渐 变 Color Color 类 定 义 了 一 些 颜 色 变 量 和 一 些 创 建 颜 色 的 方 法 颜 色 的 定 义 一 般 使 用 RGB 三 原 色 定 义 Color 位 于 android.graphics 包 中, 其 常 用 属 性 和 方 法 如 表 所 示 BLACK BLUE CYAN GREEN RED WHITE YELLOW GRAY TRANSPARENT Path 属 性 名 称 表 Color 常 用 属 性 黑 色 蓝 色 青 色 绿 色 红 色 白 色 黄 色 灰 色 透 明 方 法 描 述 Path 一 般 用 来 从 一 个 点 移 动 到 另 一 个 点 连 线 Path 位 于 android.graphics 包 中 详 细 方 法 如 表 所 示 方 法 名 称 lineto(float x,float y) moveto(float x,float y) reset() 表 Path 常 用 方 法 方 法 描 述 从 最 后 点 到 指 定 点 划 线 移 动 到 指 定 点 复 位 实 验 步 骤 1) 案 例 一 : 将 范 例 程 序 MainActivityDraw1 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 :

110 图 几 何 图 形 的 绘 制 2) 案 例 二 :ViewDemoTest 实 例 是 一 个 根 据 触 摸 位 置 变 化, 图 片 跟 着 变 化 的 实 例 将 范 例 程 序 ViewDemoTest 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 根 据 触 摸 位 置 变 化 的 绘 制 几 何 图 形 图 根 据 触 摸 位 置 变 化 的 绘 制 几 何 图 形 3) 案 例 三 :MainActivityDraw 实 例 是 一 个 小 球 上 下 跳 动 的 实 例 将 范 例 程 序 MainActivityDraw 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 :

111 图 小 球 动 态 跳 动 的 画 图 实 例 图 小 球 动 态 跳 动 的 画 图 实 例 8.4 图 形 特 效 实 验 目 的 掌 握 Android 系 统 中 使 用 Matrix 类 实 现 旋 转 缩 放 和 平 移 ; 掌 握 Android 系 统 中 使 用 Shader 类 渲 染 属 性 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 使 用 Matrix 实 现 旋 转 缩 放 和 平 移 在 Android 图 形 API 中 提 供 了 一 个 Matrix 矩 形 类, 该 类 具 有 一 个 3*3 的 矩 阵 坐 标 通 过 该 类 可 以 实 现 图 形 的 旋 转 平 移 和 缩 放 该 类 的 详 细 方 法 如 表 所 示 表 Matrix 常 用 方 法 方 法 名 称 方 法 描 述 reset() 重 置 一 个 Matrix 对 象 set(matrix src) 复 制 一 个 源 矩 阵 setrotate(float degrees) 指 定 一 个 角 度 以 (0,0) 为 坐 标 进 行 旋 转 setrotate(float degrees, float px, float py) 指 定 一 个 角 度 以 (px,py) 为 坐 标 进 行 旋 转

112 setscale(float sx, float sy) setscale(float sx, float sy, float px, float py) settranslate(float dx, float dy) setskew(float kx, float ky) setskew(float kx, float ky, float px, float py) 缩 放 处 理 以 (px,py) 进 行 缩 放 平 移 倾 斜 处 理 以 (px,py) 为 坐 标 进 行 倾 斜 接 下 来 我 们 会 通 过 一 个 实 例 演 示 Matrix 的 具 体 应 用, 在 本 实 例 中 我 们 自 定 义 一 个 View 类, 在 该 类 中 拥 有 一 个 Bitmap 和 Matrix 实 例,Bitmap 实 例 从 系 统 资 源 加 载 一 张 图 片, 覆 盖 View 类 的 ondraw() 方 法, 在 该 方 法 中 通 过 reset() 方 法 初 始 化 Matrix, 并 设 置 其 旋 转 或 缩 放 属 性, 使 用 Canvas 的 drawbitmap() 方 法 将 Bitmap 重 新 绘 制 在 视 图 中 通 过 键 盘 事 件 onkeydown() 实 现 旋 转 属 性 和 缩 放 属 性 的 改 变, 调 用 postinvalidate() 方 法 重 新 绘 制 Bitmap 使 用 Shader 类 渲 染 属 性 经 常 会 看 到 一 些 屏 保 或 者 音 乐 播 放 器 的 界 面 中 有 一 些 非 常 绚 丽 的 图 形, 这 些 其 实 是 在 一 些 原 有 图 形 的 基 础 上 进 行 渲 染 的 结 果 Android 系 统 中 提 供 了 Shader 渲 染 类 来 实 现 这 一 功 能 Shader 是 一 个 抽 象 父 类, 其 子 类 有 很 多 个, 如 BitmapShader( 位 图 渲 染 ) ComposeShader( 混 合 渲 染 ) LinearGradient( 线 性 渲 染 ) RadialGradient( 光 束 渲 染 ) 和 SweepGradient( 梯 度 渲 染 ) 等 通 过 Paint 对 象 的 paint.setshader(shader) 方 法 来 使 用 Shader 实 验 步 骤 使 用 Matrix 实 现 旋 转 缩 放 和 平 移 1) 本 次 实 验 我 们 将 使 用 Matrix 实 现 旋 转 缩 放 和 平 移, 将 范 例 程 序 VideoDemo 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 2) 单 击 各 类 型 按 钮, 图 片 会 做 相 应 的 变 化, 运 行 界 面 如 图 所 示 : 图 使 用 Matrix 右 旋 转 图 图 使 用 Matrix 左 旋 转 图

113 图 使 用 Matrix 放 大 图 图 使 用 Matrix 缩 小 图 使 用 Shader 类 渲 染 属 性 1) 将 范 例 程 序 MainActivityDraw3 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 单 击 不 同 的 渲 染 方 式 按 钮, 可 以 得 到 不 同 类 型 的 渲 染 效 果, 在 这 里 只 列 出 其 中 几 种 效 果 如 图 所 示, 读 者 可 运 行 源 码 去 测 试 其 他 的 效 果 ; 图 使 用 梯 度 渲 染 效 果 图 使 用 线 性 渲 染 效 果 图 使 用 光 束 渲 染 效 果 图 使 用 位 图 渲 染 效 果

114 第 九 章 Android 网 络 编 程 Android & linux 系 统 与 应 用 开 发 本 章 我 们 主 要 来 学 习 Android 网 络 编 程 手 机 的 确 给 我 们 带 来 了 不 少 的 方 便 1995 年 问 世 的 第 一 代 (1G) 模 拟 制 式 手 机 只 能 进 行 语 音 通 话 ; 年 出 现 的 第 二 代 (2G)GSM CDMA 等 数 字 制 式 手 机 便 增 加 了 接 收 数 据 ( 如 接 收 电 子 邮 件 或 网 页 ) 等 功 能 ; 而 2009 年 诞 生 的 3G, 其 功 能 更 是 让 人 眼 花 缭 乱, 比 如 高 速 的 无 线 宽 带 上 网 视 频 通 话 无 线 搜 索 手 机 音 乐 手 机 网 游 等 无 线 网 络 发 展 的 速 度 也 非 常 迅 猛 有 了 无 线 网 络 的 支 持, 我 们 就 不 必 受 时 间 和 空 间 的 限 制, 可 以 随 时 随 地 进 行 数 据 交 换, 浏 览 Internet, 第 一 时 间 获 取 新 闻 随 着 人 们 认 知 水 平 的 提 高, 生 活 圈 子 越 来 越 广, 人 们 需 要 网 络 的 帮 助 来 处 理 一 些 事 物, 比 如 手 机 炒 股 手 机 证 劵 手 机 银 行 手 机 地 图 等, 而 在 Android 中, 掌 握 了 网 络 通 信 便 可 以 开 发 出 这 些 优 秀 的 网 络 应 用 在 前 面 的 学 习 中, 已 经 了 解 到 Android 出 色 的 界 面 设 计 及 强 大 的 数 据 管 理 功 能 除 了 这 些 强 大 的 功 能 外,Android 在 网 络 通 信 方 面 也 非 常 的 优 秀, 例 如, 我 们 可 以 很 轻 松 的 使 用 Android 自 带 的 浏 览 器 来 访 问 网 页 Android 基 于 Linux 内 核, 它 包 含 一 组 优 秀 的 联 网 功 能, 这 些 只 是 Android 自 带 的 一 些 功 能, 它 们 是 开 源 软 件, 大 家 可 以 拿 来 学 习 研 究 目 前,Android 平 台 有 3 种 网 络 接 口 可 以 使 用, 它 们 分 别 是 :java.net.*( 标 准 Java 接 口 ),org.apacher(apache) 接 口 和 android.net.*(android 网 络 接 口 ) 9.1 Apache 接 口 实 验 目 的 掌 握 将 一 个 web 项 目 部 署 到 本 地 的 apache 服 务 器 上 ; 掌 握 Android 系 统 中 通 过 HttpClient 访 问 apache 服 务 器 上 的 web 资 源 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP

115 9.1.3 实 验 原 理 HTTP 协 议 可 能 是 现 在 Intenet 上 使 用 得 最 多 最 重 要 的 通 信 协 议 了 越 来 越 多 的 Java 应 用 程 序 需 要 通 过 HTTP 协 议 来 访 问 网 络 资 源 虽 然 在 JDK 的 java.net 包 中 已 经 提 供 了 访 问 HTTP 协 议 的 基 本 功 能, 但 是 对 于 大 部 分 应 用 程 序 来 说,JDK 库 本 身 提 供 的 功 能 远 远 不 够 这 时 就 需 要 Android 提 供 的 Apache HttpClient 了 它 是 一 个 开 源 项 目, 功 能 更 加 完 善, 为 客 户 端 的 HTTP 编 程 提 供 了 高 效 最 新 功 能 丰 富 的 工 具 包 支 持 Android 平 台 引 入 了 Apache HttpClient 的 同 时 还 提 供 了 对 它 的 一 些 封 装 和 扩 展, 例 如 设 置 默 认 的 HTTP 超 时 和 缓 存 大 小 等 Android 使 用 的 是 目 前 最 新 的 HttpClient4.0, 可 以 将 Apache 视 为 目 前 流 行 的 开 源 web 服 务 器, 主 要 包 括 创 建 HttpClient Get/Post HttpRequest 等 对 象, 设 置 连 接 参 数, 执 行 HTTP 操 作, 处 理 服 务 返 回 结 果 等 功 能 实 验 步 骤 安 装 Tomcat 服 务 器 : 1) 安 装 Tomcat 7.0, 完 全 按 照 默 然 安 装 即 可, 安 装 时 会 自 动 匹 配 本 机 上 已 经 安 装 好 了 的 JDK, Tomcat7.0 安 装 文 件 目 录 : 第 9 章 /common/apache-tomcat exe; 2) 运 行 Tomcat7w.exe(Tomcat 7.0 安 装 目 录 下 ), 点 击 Start 启 动 服 务 : 图 启 动 Tomcat 服 务 3) 运 行 Tomcat7.exe 启 动 Tomcat, 输 入 如 果 进 入 Tomcat 主 页, 则 配 置 Tomcat 服 务 器 成 功, 如 图 所 示 :

116 图 Tomcat 启 动 成 功 测 试 界 面 使 用 HttpClient 访 问 web 应 用 网 页 资 源 : 1) 此 项 目 要 部 署 Web 服 务 器, 前 面 我 们 已 经 安 装 好 了 Tomcat 7.0, 进 入 Tomcat7.0 安 装 目 录, 将 第 9 章 \common\foo 应 用 复 制 到 webapps 目 录 下, 如 图 所 示 ; 图 将 web 应 用 部 署 到 Tomcat 服 务 器 上 2) 在 命 令 行 里 输 入 cmd 命 令, 进 入 在 Windows 系 统 下 运 行 DOS, 在 DOS 输 入 ipconfig, 得 到 本 地 ip( 比 如 ), 重 新 启 动 Tomcat 服 务 器, 访 问 网 络 : get.html, 测 试 是 否 能 访 问 部 署 在 apache 里 的 web 应 用 图 测 试 web 应 用 是 否 部 署 成 功 3) 本 次 实 验 我 们 主 要 是 通 过 apache 提 供 的 接 口, 通 过 HttpClient 对 象 访 问 web 资 源, 将 范

117 例 程 序 HttpClientTest 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 单 击 访 问 页 面 按 钮, 运 行 界 面 如 图 所 示 ; 特 别 注 意 的 是 将 android 应 用 对 应 要 访 问 的 资 源 的 ip 地 址 修 改 成 本 地 的 ip 地 址 ; 还 有 注 意 的 是, 在 编 写 应 用 时, 一 定 要 在 AndroidManifest.xml 清 单 文 件 里 添 加 访 问 Internet 权 限 需 要 修 改 的 ip 地 址 : HttpGet get = new HttpGet(" 需 要 添 加 的 权 限 : <uses-permission android:name="android.permission.internet"/> 图 使 用 HttpClient 访 问 web 应 用 网 页 资 源 9.2 HTTP 通 信 实 验 目 的 掌 握 Android 系 统 中 使 用 HttpURLConnection 接 口 访 问 web 应 用 中 图 片 ; 掌 握 Android 系 统 中 使 用 HttpURLConnection 接 口 访 问 web 应 用 中 的 网 页 资 源 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP

118 9.2.3 实 验 原 理 HTTP(HyperText Transfer Protocol) 是 一 套 计 算 机 通 过 网 络 进 行 通 信 的 规 则 计 算 机 专 家 设 计 出 HTTP, 使 HTTP 客 户 ( 如 Web 浏 览 器 ) 能 够 从 HTTP 服 务 器 (Web 服 务 器 ) 请 求 信 息 和 服 务,HTTP 目 前 协 议 的 版 本 是 1.1.HTTP 是 一 种 无 状 态 的 协 议, 无 状 态 是 指 Web 浏 览 器 和 Web 服 务 器 之 间 不 需 要 建 立 持 久 的 连 接, 这 意 味 着 当 一 个 客 户 端 向 服 务 器 端 发 出 请 求, 然 后 Web 服 务 器 返 回 响 应 (response), 连 接 就 被 关 闭 了, 在 服 务 器 端 不 保 留 连 接 的 有 关 信 息.HTTP 遵 循 请 求 (Request)/ 应 答 (Response) 模 型 Web 浏 览 器 向 Web 服 务 器 发 送 请 求,Web 服 务 器 处 理 请 求 并 返 回 适 当 的 应 答 所 有 HTTP 连 接 都 被 构 造 成 一 套 请 求 和 应 答 HTTP 使 用 内 容 类 型, 是 指 Web 服 务 器 向 Web 浏 览 器 返 回 的 文 件 都 有 与 之 相 关 的 类 型 所 有 这 些 类 型 在 MIME Internet 邮 件 协 议 上 模 型 化, 即 Web 服 务 器 告 诉 Web 浏 览 器 该 文 件 所 具 有 的 种 类, 是 HTML 文 档 GIF 格 式 图 像 声 音 文 件 还 是 独 立 的 应 用 程 序 大 多 数 Web 浏 览 器 都 拥 有 一 系 列 的 可 配 置 的 辅 助 应 用 程 序, 它 们 告 诉 浏 览 器 应 该 如 何 处 理 Web 服 务 器 发 送 过 来 的 各 种 内 容 类 型 HttpURLConnection 接 口 : HTTP 通 信 中 使 用 最 多 的 就 是 GET 和 POST 方 式,GET 请 求 可 以 获 取 静 态 页 面, 也 可 以 把 参 数 放 在 URL 字 串 后 面, 传 递 给 服 务 器 Post 与 Get 的 不 同 之 处 在 于 Post 的 参 数 不 是 放 在 URL 字 串 里 面, 而 是 放 在 HTTP 请 求 数 据 中 HttpURLConnection 是 Java 的 标 准 类, 继 承 自 URLConnection 类,URLConnection 与 HttpURLConnection 都 是 抽 象 类, 无 法 直 接 实 例 化 对 象 其 对 象 主 要 是 通 过 URL 的 openconnection 方 法 获 得 实 验 步 骤 使 用 HttpURLConnection 接 口 访 问 web 应 用 中 图 片 : 1) 同 9.1Apache 接 口 的 实 验 一 样, 本 实 验 也 需 要 部 署 web 应 用 到 Tomcat7 服 务 器 上, 故 沿 用 上 一 实 验 的 web 应 用 不 变, 只 是 在 web 应 用 中 添 加 了 haibao.jpg 的 图 片, 如 图 所 示 所 示 界 面 : 图 在 web 应 用 中 添 加 haibao.jpg

119 2) 通 过 IP 地 址 测 试 web 应 用 是 否 部 署 成 功, 如 图 所 示 : 图 测 试 web 应 用 是 否 部 署 成 功 3) 将 范 例 程 序 Net_Image 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 ; 特 别 注 意 的 是 将 android 应 用 对 应 要 访 问 的 资 源 的 ip 地 址 修 改 成 本 地 的 ip 地 址 ; 还 有 注 意 的 是, 在 编 写 应 用 时, 一 定 要 在 AndroidManifest.xml 清 单 文 件 里 添 加 访 问 Internet 权 限 图 通 过 HttpURLConnection 访 问 web 应 用 中 图 片 使 用 HttpURLConnection 接 口 访 问 web 应 用 中 的 网 页 资 源 : 1) 将 范 例 程 序 HtmlView 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 ; 特 别 注 意 的 是 将 android 应 用 对 应 要 访 问 的 资 源 的 ip 地 址 修 改 成 本 机 的 ip 地 址, 且 要 添 加 访 问 Internet 权 限, 运 行 后 得 到 如 图 所 示 界 面

120 图 通 过 HttpURLConnection 访 问 web 应 用 中 的 网 页 资 源 9.3 Socket 通 信 实 验 目 的 掌 握 Android 系 统 中 Socket 的 传 输 模 式 已 经 Socket 编 程 原 理 ; 掌 握 Android 系 统 中 实 现 Socket 服 务 器 端 和 Socket 客 户 端 之 间 的 通 信 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 Socket 传 输 模 式 Socket 有 两 种 主 要 的 操 作 方 式 : 面 向 连 接 的 和 无 连 接 的 面 向 连 接 的 Socket 操 作 就 像 一 部 电 话, 必 须 建 立 一 个 连 接 和 一 个 呼 叫 所 有 的 事 情 到 达 时 的 顺 序 与 它 们 发 出 的 顺 序 是 一 样 的 无 连 接 的 Socket 操 作 就 像 是 一 个 邮 件 传 递, 没 有 什 么 保 证, 多 个 邮 件 到 达 时 的 顺 序 可 能 与 出 发 时 的 顺 序 不 一 样 根 据 应 用 程 序 的 需 要 决 定 Socket 传 输 模 式 的 选 择 如 果 可 靠 性 更 高 的 话, 用 面 向 连 接 的 操 作 会 好 一 些 比 如 文 件 服 务 器 需 要 数 据 的 正 确 性 和 有 序 性, 如 果 一 些 数 据 丢 失 了 其 时 效 性 导 致 系 统 的 有 效 性 降 低 但 同 时 确 保 数 据 的 有 序 性 和 正 确 性 需 要 额 外 的 操 作, 这 会 带 来 内 存 消 耗, 额 外 的 费 用 会 降 低 系 统 的 回 应 速 率

121 无 连 接 的 操 作 使 用 数 据 包 协 议 一 个 数 据 报 是 一 个 独 立 单 元 它 包 含 了 这 次 投 递 的 所 有 信 息 它 包 含 了 目 的 地 址 和 要 发 送 的 内 容, 这 个 模 式 下 的 Socket 不 需 要 连 接 一 个 目 的 Socket, 它 只 是 简 单 地 投 出 数 据 报 无 连 接 的 操 作 时 快 速 和 高 效 的, 但 是 数 据 安 全 性 不 佳 面 向 连 接 的 操 作 使 用 TCP 协 议 该 模 式 下 的 Socket 必 须 在 发 送 数 据 之 前 与 目 的 地 的 Socket 取 得 连 接 一 旦 连 接 建 立 了,Socket 就 可 以 使 用 一 个 流 接 口 进 行 打 开 读 写 关 闭 操 作 所 发 送 的 信 息 都 会 在 另 一 端 以 同 样 的 顺 序 被 接 收 面 向 连 接 的 操 作 闭 无 连 接 操 作 的 效 率 地, 但 是 数 据 的 安 全 性 要 高 Socket 编 程 原 理 1)Socket 构 造 Java 在 包 java.net 中 提 供 了 两 个 类 Socket 和 ServerSocket, 分 别 用 来 表 示 双 向 连 接 的 客 户 端 和 服 务 端, 起 重 工 address host 和 port 分 别 是 双 向 连 接 中 另 一 方 的 IP 地 址 主 机 名 和 端 口 号,stream 指 明 Socket 是 流 Socket, 还 是 数 据 包 Socket,localPort 表 示 本 地 主 机 的 端 口 号,localAddr 和 bindaddr 是 本 地 机 器 的 地 址 (ServerSocket 的 主 机 地 址 ),impl 是 Socket 的 父 类, 既 可 以 用 来 创 建 ServerSocket, 又 可 以 用 来 创 建 Socket 特 别 注 意 : 在 选 择 端 口 号 时 必 须 小 心 每 个 端 口 提 供 一 中 特 定 的 服 务, 只 有 给 出 正 确 的 端 口, 才 能 获 得 相 应 的 服 务 的 端 口 号 为 系 统 所 保 留 所 以 我 们 在 选 择 端 口 号 时, 最 好 选 择 一 个 大 于 1023 的 数, 防 止 发 生 冲 突 在 创 建 Socket 时, 如 果 发 生 错 误, 将 产 生 IOException, 在 程 序 中 必 须 对 其 处 理 2) 客 户 端 Socket 要 想 使 用 Socket 来 与 一 个 服 务 器 通 信, 就 必 须 先 在 客 户 端 创 建 一 个 Socket, 并 指 明 需 要 连 接 的 服 务 的 IP 地 址 和 端 口 3)ServerSocket 要 想 使 用 Socket 来 与 一 个 服 务 器 通 信, 就 必 须 先 在 客 户 端 创 建 一 个 Socket, 并 指 出 需 要 连 接 的 服 务 器 的 IP 地 址 和 端 口, 这 也 是 Socket 通 信 的 第 一 步 实 验 程 序 中 我 们 创 建 了 一 个 ServerSocket 在 端 口 8888 监 听 客 户 端 请 求, 它 是 Server 的 典 型 工 作 模 式, 在 这 里 Server 只 能 接 收 一 个 请 求, 接 收 后 Server 就 退 出 了 实 际 的 应 用 中 总 是 让 它 不 听 地 循 环 接 收, 一 旦 有 客 户 请 求,Server 总 是 会 创 建 一 个 服 务 线 程 来 服 务 新 来 的 客 户, 而 自 己 继 续 监 听 4) 输 入 ( 出 ) 流 Socket 提 供 了 getinputstream() 和 getoutstream() 来 得 到 对 于 的 输 入 ( 出 ) 流 来 进 行 读 ( 写 ) 操 作, 这 两 个 方 法 分 别 返 回 InputStream 和 OutputStream 类 对 象 为 了 便 于 读 ( 写 ) 数 据, 我 们 可 以 在 返 回 的 输 入 输 出 流 对 象 上 建 立 过 滤 流, 如 DataInputStream DataOutputStream 或 PrintStream 类 对 象, 对 于 文 本 方 式 流 对 象, 可 以 采 用 InputStreamReader 和 OutputStreamWriter PrintWriter

122 等 处 理 5) 关 闭 Socket 每 一 个 Socket 存 在 时 都 将 占 用 一 定 的 资 源, 在 Socket 对 象 使 用 完 毕 时, 要 使 其 关 闭, 关 闭 Socket 可 以 调 用 Socket 的 close() 方 法 在 关 闭 Socket 之 前, 应 该 将 与 Socket 相 关 的 所 有 输 入 ( 出 ) 流 全 部 关 闭, 然 后 再 关 闭 Socket 实 验 步 骤 1) 本 实 验 主 要 是 测 试 Socket 的 通 信, 打 开 Eclipse 环 境 将 范 例 程 序 SocketServer 通 过 Import->Existing Projects into Workspace 导 入, 右 键 单 击 工 程 选 择 :Run as -> Java Application, 即 启 动 SocketServer 服 务 器 端, 实 现 对 SocketClient 的 监 听, 在 Console 窗 口 查 看 后 台 输 出 消 息 : 图 运 行 服 务 端 应 用 小 提 示 : 如 果 监 听 完 成 后 要 关 闭 服 务 器 的 程 序, 只 需 要 在 Server.java 中 取 消 server.stopserver() 代 码 行 的 的 注 释 并 注 释 server.runserver() 代 码 行 再 运 行 程 序 即 可 2) 将 范 例 程 序 MyClient 通 过 Import->Existing Projects into Workspace 将 android 应 用 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 平 台 对 应 的 Device 设 备 上 ; 3) 单 击 连 接 按 钮, 将 MyClient 端 的 Socket 与 服 务 器 端 的 Socket 连 接 起 来, 此 时, 服 务 器 端 控 制 栏 会 打 印 一 条 成 功 连 接 的 信 息 :accept 图 客 户 端 成 功 连 接 服 务 器

123 图 服 务 器 端 成 功 连 接 到 客 户 端 5) 单 击 发 送 信 息 按 钮,MyClient 端 将 通 过 已 经 建 立 连 接 的 Socket 将 信 息 发 给 服 务 器 端, 并 在 服 务 器 端 的 控 制 栏 显 示, 如 图 所 示 : 图 客 户 端 成 功 向 服 务 器 端 发 送 数 据

124 第 十 章 Linux 操 作 系 统 基 础 Android & linux 系 统 与 应 用 开 发 本 章 主 要 讲 解 嵌 入 式 Linux 开 发 环 境 的 安 装 及 使 用 Linux 常 用 命 令 Linux 各 种 工 具 的 使 用 GCC 和 Makefile 等 学 习 了 本 章 后, 读 者 能 够 掌 握 如 下 内 容 : 熟 悉 Linux 系 统 下 的 开 发 环 境, 熟 悉 vi 的 基 本 操 作, 熟 悉 GCC 编 译 器 的 基 本 原 理, 熟 悉 makefile 基 本 原 理 及 语 法 规 范 10.1 ZEmberOS 操 作 系 统 安 装 实 验 目 的 了 解 Linux 操 作 系 统 ; 掌 握 嵌 入 式 Linux 环 境 的 安 装 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :Windows 7/Windows XP 实 验 原 理 自 由 开 源 软 件 在 嵌 入 式 应 用 上, 受 到 青 睐,Linux 日 益 成 为 主 流 的 嵌 入 式 操 作 系 统 之 一 目 前, 国 外 不 少 大 学 研 究 机 构 和 知 名 公 司 都 加 入 了 嵌 入 式 Linux 的 开 发 工 作, 成 熟 的 嵌 入 式 Linux 产 品 不 断 涌 现 嵌 入 式 Linux 系 统 开 发 一 般 都 要 求 在 Linux 操 作 系 统 下 进 行, 常 用 的 Linux 发 行 版 很 多, 一 般 选 择 Ubuntu 作 为 主 流 的 开 发 环 境 Ubuntu 是 一 个 相 对 较 新 的 发 行 版, 它 的 出 现 可 能 改 变 了 许 多 潜 在 用 户 对 Linux 的 看 法 也 许, 从 前 人 们 会 认 为 Linux 难 以 安 装 难 以 使 用, 但 是,Ubuntu 出 现 后, 这 些 都 成 为 了 历 史 Ubuntu 基 于 Debian Sid, 所 以 这 也 就 是 上 文 所 说 的,Ubuntu 拥 有 Debian 的 所 有 优 点, 包 括 apt-get 然 而, 不 仅 如 此 而 已,Ubuntu 默 认 采 用 的 GNOME 桌 面 系 统 官 方 发 行 的 Ubuntu 一 般 为 桌 面 版 本, 要 进 行 嵌 入 式 开 发, 必 须 联 网 安 装 一 些 必 备 的 软 件 库 及

125 开 发 包 考 虑 到 实 验 室 环 境 的 特 殊 性, 本 产 品 提 供 增 强 定 制 的 ZEmberOS, 安 装 配 置 都 很 简 单, 并 且 包 含 所 有 实 验 环 境 必 备 的 软 件 包 实 验 步 骤 ZD-s210xA80 实 验 平 台 Android 系 统 内 核 开 发 要 求 必 须 在 linux 操 作 系 统 上 面 开 发, 并 且 配 置 好 嵌 入 式 开 发 所 必 须 的 环 境 出 厂 光 盘 DISK-ZEmberOS 即 为 我 们 定 制 好 的 嵌 入 式 开 发 系 统 开 发 环 境 安 装 盘, 用 户 需 要 通 过 下 面 的 方 法 从 硬 盘 安 装 系 统, 安 装 前 需 要 将 电 脑 的 网 线 拔 掉 ( 禁 止 网 络 ): 1)Android 系 统 内 核 开 发 要 求 至 少 30G 以 上 的 剩 余 硬 盘 空 间, 安 装 前 需 在 电 脑 中 准 备 一 个 30G 以 上 的 空 白 分 区 : 图 准 备 空 闲 的 磁 盘 分 区 2) 将 出 厂 光 盘 DISK-ZEmberOS 内 的 文 件 ZEmber-ubuntu amd64.iso 和 wubi.exe 拷 贝 到 任 意 磁 盘 的 根 分 区 ( 同 级 目 录 下 不 能 有 其 他 的 ISO 文 件 ), 双 击 wubi.exe 程 序 运 行, 开 始 准 备 安 装 文 件 进 行 硬 盘 安 装, 设 置 如 下 图 所 示 :

126 Ubuntu WUBI 安 装 选 项 目 标 驱 动 器 : 安 装 文 件 缓 存 分 区 安 装 大 小 : 设 置 为 4G 以 上 桌 面 环 境 : Ubuntu 语 言 : Chinese(CN) 用 户 名 : 任 填 ( 本 系 统 盘 强 制 用 户 名 为 ubuntu) 口 令 : 任 填 ( 本 系 统 盘 强 制 密 码 为 ubuntu) 图 WUBI 安 装 参 数 设 置 3) 接 下 来 系 统 将 准 备 安 装 文 件, 大 约 2-3 分 钟, 安 装 文 件 准 备 完 成, 系 统 提 示 重 启, 选 择 立 即 重 启 : 图 准 备 安 装 文 件 4) 电 脑 在 再 次 启 动 后, 出 现 启 动 选 择 菜 单, 利 用 键 盘 的 上 下 键 可 以 进 行 选 择, 此 处 我 们 选 择 Ubuntu, 回 车 后 进 入 到 Ubuntu 系 统 : 图 开 机 选 项 5) 接 下 来 进 入 Ubuntu 的 开 机 进 度 条, 大 约 1-2 分 钟 左 右 进 入 到 Ubuntu 系 统 界 面, 如 图 示 :

127 图 Ubuntu 启 动 6) 在 系 统 上 方 任 务 栏 选 择 : 应 用 程 序 -> 附 件 -> 终 端, 在 弹 出 的 终 端 窗 口 输 入 以 下 命 令 卸 载 挂 载 的 磁 盘 设 备 : $ sudo umount -l /isodevice # 如 果 提 示 输 入 密 码 则 为 :ubuntu 7) 在 系 统 上 方 任 务 栏 选 择 : 系 统 -> 系 统 管 理 -> 安 装 Ubuntu LTS, 开 始 进 行 系 统 的 安 装 8) 接 下 来 会 先 后 弹 出 语 言 设 置 界 面 时 区 设 置 界 面 键 盘 设 置 界 面, 可 以 都 选 择 默 认 继 续 : 图 设 置 语 言 时 区 键 盘 9) 接 下 来 将 会 进 入 安 装 分 区 的 选 择 菜 单, 此 处 设 置 需 谨 慎, 选 择 手 动 指 定 分 区 ( 高 级 ), 然 后 前 进 继 续 ( 有 时 安 装 没 有 出 现 这 一 步, 直 接 跳 到 了 第 9 步 ): 图 选 择 手 动 分 区

128 10) 继 续 前 进, 接 下 来 弹 出 的 菜 单 将 会 看 到 用 户 的 磁 盘 分 区 列 表, 里 面 有 一 个 之 前 在 windows 中 删 除 未 分 区 的 空 闲 空 间, 我 们 将 在 该 空 闲 分 区 中 安 装 Ubuntu 此 时 选 中 空 闲, 点 击 添 加, 在 弹 出 的 菜 单 中, 将 显 示 的 分 区 容 量 值 减 去 4096 作 为 根 分 区 ( 余 下 的 4096MB 空 间 将 用 于 交 换 分 区, 可 以 根 据 实 际 情 况 调 整, 一 般 为 内 存 大 小 ), 新 分 区 类 型 : 逻 辑 分 区, 新 分 区 的 位 置 : 起 始, 用 于 :Ext4 日 志 文 件 系 统, 挂 载 点 ( 通 过 箭 头 下 拉 菜 单 选 择 ):/, 然 后 点 击 确 认 按 钮 继 续 : 图 建 立 根 节 点 分 区 11) 此 时 会 回 到 磁 盘 分 区 列 表 界 面, 可 以 看 到 已 经 新 建 了 一 个 挂 载 点 为 / 的 ext4 分 区, 接 下 来 继 续 选 择 空 闲, 点 击 添 加, 在 弹 出 的 界 面 中, 设 置 分 区 类 型 用 于 为 交 换 空 间, 其 他 默 认, 点 击 确 认 返 回 :

129 图 设 置 好 Ubuntu 的 安 装 分 区 及 交 换 分 区 12) 分 区 设 置 好 后, 点 击 前 进 继 续, 弹 出 界 面 要 求 设 置 登 陆 的 用 户 密 码 ( 此 处 用 户 名 密 码 设 置 实 际 无 效, 系 统 安 装 完 后, 默 认 用 户 名 密 码 都 是 :ubuntu), 正 确 设 置 后 点 击 前 进 继 续 : 图 设 置 登 陆 用 户 名 及 密 码 13) 接 下 来 弹 出 迁 移 文 档 及 设 置 界 面, 直 接 点 击 前 进 继 续 14) 接 下 来 的 界 面 将 提 示 确 认 你 的 安 装 信 息, 检 查 将 被 格 式 化 的 分 区 是 否 正 确, 确 认 后 直 接 选 择 选 择 前 进 继 续 :

130 图 准 备 安 装 15) 接 下 来, 将 会 自 动 进 行 系 统 的 安 装, 并 提 示 安 装 进 度 条, 这 个 过 程 大 约 会 花 费 分 钟 左 右 的 时 间, 等 待 安 装 完 成 图 安 装 进 度 16) 安 装 结 束 之 后, 系 统 弹 出 界 面 提 示 现 在 重 启 的 选 择 项, 此 时 选 择 它 系 统 会 自 动 重 启, 再 次 开 机 在 启 动 菜 单 中 选 择 ubuntu 进 入, 在 登 陆 界 面 出 现 后 输 入 用 户 名 和 密 码 :ubuntu, 将 正 常 启 动 Ubuntu 系 统 图 安 装 结 束, 重 启 17) 在 电 脑 的 启 动 项 选 择 从 windows 启 动 后, 可 以 在 控 制 面 板 的 添 加 与 删 除 程 序 里 面 把 ubuntu 卸 载 掉 ( 实 际 上 是 把 ubuntu 安 装 时 的 临 时 安 装 包 删 除 掉 )

131 10.2 ZEmberOS 基 本 使 用 实 验 目 的 学 习 使 用 ubuntu 操 作 系 统 ; 了 解 终 端 的 使 用 ; 了 解 串 口 Minicom 的 使 用 ; 学 习 samba 共 享 服 务 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Linux 下 操 作 与 Windows 差 异 比 较 大, 常 见 的 开 发 都 是 基 于 命 令 行 操 作 实 验 步 骤 安 装 完 ZEmberOS 嵌 入 式 开 发 环 境 后, 可 以 按 照 以 下 方 法 做 一 些 系 统 配 置 : 1) 终 端 的 使 用 : 在 Ubuntu 的 标 题 栏 选 择 应 用 程 序 -> 附 件 -> 终 端 运 行 终 端, 在 终 端 可 以 输 入 Linux 命 令 进 行 操 作, 类 似 与 DOS: 图 查 看 终 端

132 2) 设 置 管 理 员 账 户 root 的 密 码 : 设 置 root 用 户 密 码 : 在 Ubuntu 的 标 题 栏 选 择 应 用 程 序 -> 附 件 -> 终 端 运 行 终 端, 在 终 端 的 命 令 行 输 入 以 下 命 令 设 置 root 密 码 : $ sudo passwd root [sudo] password for zonesion -> 此 处 输 入 你 当 前 用 户 的 密 码 输 入 新 的 UNIX 口 令 : -> 此 处 输 入 你 需 要 设 置 的 root 的 密 码 重 新 输 入 新 的 UNIX 口 令 : -> 再 次 输 入 你 需 要 设 置 的 root 的 密 码 passwd: 已 成 功 更 新 密 码 3) 串 口 终 端 minicom 的 设 置 : 在 Ubuntu 的 标 题 栏 选 择 应 用 程 序 -> 附 件 -> 终 端 运 行 终 端, 输 入 命 令 建 立 Minicom 配 置 文 件 minirc.dfl( 默 认 已 经 建 立 设 置 好 了 ) $ sudo gedit /etc/minicom/minirc.dfl 在 弹 出 的 minirc.dfl 文 件 中 编 辑 如 下 : # Machine-generated file - use "minicom -s" to change parameters. pr port /dev/ttys0 # 一 般 台 式 机 的 默 认 串 口, 如 果 是 USB 转 适 配 器, 一 般 为 ttyusb0 pu baudrate pu bits 8 pu parity N pu stopbits 1 pu minit pu mreset pu statusline enabled pu rtscts No 其 中 pr port 的 选 项 根 据 用 户 电 脑 的 实 际 情 况 设 置, 比 如 笔 记 本 使 用 的 USB 转 串 口 的 适 配 器, 则 为 /dev/ttyusb0 4) 中 文 输 入 法 :Ctrl+Space 按 键 可 以 调 出 中 文 输 入 法, 选 择 : 简 体 中 文 -> 智 能 拼 音 5) 另 外 可 以 设 置 文 件 夹 首 选 项 里 面 将 图 标 视 图 默 认 值 修 改 为 默 认 缩 放 级 别 为 75% ; 用 户 也 可 以 根 据 自 己 的 爱 好 修 改 系 统 的 主 题 6)samba 服 务 的 使 用 :Samba 是 用 于 windows 和 linux 之 间 共 享 文 件 的 一 种 服 务, 在 Ubuntu 的 标 题 栏 选 择 应 用 程 序 -> 附 件 -> 终 端 运 行 终 端, 输 入 命 令 修 改 samba 共 享 配 置 : $ sudo gedit /etc/smaba/smb.conf 在 弹 出 的 smb.conf 文 件 最 后 添 加 如 下 ( 可 做 参 考 ): [UBUNTU-SHARE] comment = share read only = no locking = no path = /opt/share

133 guest ok =yes 修 改 好 后, 保 存 退 出, 继 续 在 终 端 输 入 以 下 命 令 重 启 samba 服 务 : $ sudo /etc/init.d/samba restart 在 windows 网 络 邻 居 共 享 就 可 以 看 到 共 享 的 Linux 文 件 夹 了 10.3 Linux 常 用 操 作 命 令 实 验 目 的 掌 握 Linux 常 用 命 令 操 作 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 在 Linux 操 作 系 统 下 开 发 程 序, 必 须 要 对 Linux 的 操 作 和 命 令 熟 悉 才 行 下 面 对 Linux 下 经 常 使 用 到 的 命 令 进 行 详 细 的 讲 解 实 验 步 骤 查 询 当 前 目 录 文 件 列 表 :ls ls 命 令 默 认 状 态 下 将 按 首 字 母 升 序 列 出 你 当 前 文 件 夹 下 面 的 所 有 内 容, 但 这 样 直 接 运 行 所 得 到 的 信 息 也 是 比 较 少 的, 通 常 它 可 以 结 合 以 下 这 些 参 数 运 行 以 查 询 更 多 的 信 息 : ls / 显 示 /. 下 的 所 有 文 件 和 目 录 ; ls -l 给 出 文 件 或 者 文 件 夹 的 详 细 信 息 ; ls -a 显 示 所 有 文 件, 包 括 隐 藏 文 件 ; ls -h 以 KB/MB/GB 方 式 给 出 文 件 大 小, 而 不 仅 仅 是 字 节 查 询 当 前 所 在 目 录 :pwd 在 Linux 层 次 目 录 结 构 中, 用 户 可 以 在 被 授 权 的 任 意 目 录 下 利 用 mkdir 命 令 创 建 新 目 录, 也 可

134 以 利 用 cd 命 令 从 一 个 目 录 转 换 到 另 一 个 目 录 然 而, 没 有 提 示 符 来 告 知 用 户 目 前 处 于 哪 一 个 目 录 中 要 想 知 道 当 前 所 处 的 目 录, 可 以 使 用 pwd 命 令, 该 命 令 显 示 整 个 路 径 名 语 法 :pwd; 说 明 : 此 命 令 显 示 出 当 前 工 作 目 录 的 绝 对 路 径 进 入 其 他 目 录 :cd 功 能 : 改 变 工 作 目 录 ; 语 法 :cd [directory]; 说 明 : 该 命 令 将 当 前 目 录 改 变 至 directory 所 指 定 的 目 录 若 没 有 指 定 directory, 则 回 到 用 户 的 主 目 录 为 了 改 变 到 指 定 目 录, 用 户 必 须 拥 有 对 指 定 目 录 的 执 行 和 读 权 限 例 如 : $ cd /home/ $ pwd /home 在 屏 幕 上 输 出 字 符 :echo 例 如 : $ echo hello Hello 显 示 文 件 内 容 :cat 例 如 : $ cat temp text test temp 复 制 文 件 :cp 该 命 令 的 功 能 是 将 给 出 的 文 件 或 目 录 拷 贝 到 另 一 文 件 或 目 录 中, 同 MSDOS 下 的 copy 命 令 一 样, 功 能 十 分 强 大 语 法 :cp [ 选 项 ] 源 文 件 或 目 录 目 标 文 件 或 目 录 ; 说 明 : 该 命 令 把 指 定 的 源 文 件 复 制 到 目 标 文 件 或 把 多 个 源 文 件 复 制 到 目 标 目 录 中 例 如 : $ ls Desktop Examples file2.txt new_file.txt $ cp file2.txt file2_copy.txt $ ls Desktop Examples file2_copy.txt file2.txt new_file.txt 移 动 文 件 :mv 用 户 可 以 使 用 mv 命 令 来 为 文 件 或 目 录 改 名 或 将 文 件 由 一 个 目 录 移 入 另 一 个 目 录 中 该 命 令 如

135 同 MSDOS 下 的 ren 和 move 的 组 合 语 法 :mv [ 选 项 ] 源 文 件 或 目 录 目 标 文 件 或 目 录 例 如 : $ ls Desktop Examples file1.txt file2.txt $ mv file1.txt new_file.txt $ ls Desktop Examples file2.txt new_file.txt 建 立 一 个 空 文 本 文 件 :touch 例 如 : $ ls Desktop Examples $ touch file1.txt $ ls Desktop Examples file1.txt 建 立 一 个 目 录 :mkdir 功 能 : 创 建 一 个 目 录 ( 类 似 MSDOS 下 的 md 命 令 ); 语 法 :mkdir [ 选 项 ] dir-name; 说 明 : 该 命 令 创 建 由 dir-name 命 名 的 目 录 要 求 创 建 目 录 的 用 户 在 当 前 目 录 中 (dir-name 的 父 目 录 中 ) 具 有 写 权 限, 并 且 dirname 不 能 是 当 前 目 录 中 已 有 的 目 录 或 文 件 名 称 例 如 : $ ls Desktop Examples file2_copy.txt file2_new.txt new_file.txt $ mkdir test_dir $ ls Desktop Examples file2_copy.txt file2_new.txt new_file.txt test_dir 删 除 文 件 / 目 录 :rm 用 户 可 以 用 rm 命 令 删 除 不 需 要 的 文 件 该 命 令 的 功 能 为 删 除 一 个 目 录 中 的 一 个 或 多 个 文 件 或 目 录, 它 也 可 以 将 某 个 目 录 及 其 下 的 所 有 文 件 及 子 目 录 均 删 除 对 于 链 接 文 件, 只 是 断 开 了 链 接, 原 文 件 保 持 不 变 语 法 :rm [ 选 项 ] 文 件 ; 说 明 : 如 果 没 有 使 用 -r 选 项, 则 rm 不 会 删 除 目 录 例 如 : $ ls Desktop Examples file2_copy.txt file2_new.txt new_file.txt test_dir $ rm -r test_dir

136 $ ls Desktop Examples file2_copy.txt file2_new.txt new_file.txt $ rm new_file.txt $ ls Desktop Examples file2_copy.txt file2_new.txt 访 问 权 限 :chmod 确 定 了 一 个 文 件 的 访 问 权 限 后, 用 户 可 以 利 用 Linux 系 统 提 供 的 chmod 命 令 来 重 新 设 定 不 同 的 访 问 权 限 也 可 以 利 用 chown 命 令 来 更 改 某 个 文 件 或 目 录 的 所 有 者 利 用 chgrp 命 令 来 更 改 某 个 文 件 或 目 录 的 用 户 组 chmod u+s file 为 file 的 属 主 加 上 特 殊 权 限 ; chmod g+r file 为 file 的 属 组 加 上 读 权 限 ; chmod o+w file 为 file 的 其 它 用 户 加 上 写 权 限 ; chmod a-x file 为 file 的 所 有 用 户 减 去 执 行 权 限 ; chmod 765 file 为 file 的 属 主 设 为 完 全 权 限, 属 组 设 成 读 写 权, 其 它 用 户 具 有 读 和 执 行 权 限 改 变 所 属 的 组 :chown 命 令 功 能 : 更 改 某 个 文 件 或 目 录 的 属 主 和 属 组 这 个 命 令 也 很 常 用 例 如 root 用 户 把 自 己 的 一 个 文 件 拷 贝 给 用 户 xu, 为 了 让 用 户 xu 能 够 存 取 这 个 文 件,root 用 户 应 该 把 这 个 文 件 的 属 主 设 为 xu, 否 则, 用 户 xu 无 法 存 取 这 个 文 件 语 法 :chown [ 选 项 ] 用 户 或 组 文 件 修 改 密 码 :passwd 命 令 出 于 系 统 安 全 考 虑,Linux 系 统 中 的 每 一 个 用 户 除 了 有 其 用 户 名 外, 还 有 其 对 应 的 用 户 口 令 因 此 使 用 useradd 命 令 增 加 时, 还 需 使 用 passwd 命 令 为 每 一 位 新 增 加 的 用 户 设 置 口 令 ; 用 户 以 后 还 可 以 随 时 用 passwd 命 令 改 变 自 己 的 口 令 该 命 令 的 使 用 方 法 如 下 : $ sudo passwd root New UNIX password: Retype new UNIX password: passwd: all authentication tokens updated successfully write 命 令 write 命 令 的 功 能 是 向 系 统 中 某 一 个 用 户 发 送 信 息 该 命 令 的 一 般 格 式 为 : write 用 户 帐 号 [ 终 端 名 称 ] 例 如 : $ write Guest hello 此 时 系 统 进 入 发 送 信 息 状 态, 用 户 可 以 输 入 要 发 送 的 信 息, 输 入 完 毕, 希 望 退 出 发 送 状 态 时,

137 按 组 合 键 < Ctrl+c> 即 可 mesg 指 令 mesg 命 令 设 定 是 否 允 许 其 他 用 户 用 write 命 令 给 自 己 发 送 信 息 如 果 允 许 别 人 给 自 己 发 送 信 息, 输 入 命 令 :# mesg y 否 则, 输 入 :# mesg n 对 于 超 级 用 户, 系 统 的 默 认 值 为 n; 而 对 于 一 般 用 户 系 统 的 默 认 值 为 y 如 果 mesg 后 不 带 任 何 参 数, 则 显 示 当 前 的 状 态 是 y 还 是 n shutdown 命 令 shutdown 命 令 可 以 安 全 地 关 闭 或 重 启 Linux 系 统, 它 在 系 统 关 闭 之 前 给 系 统 上 的 所 有 登 录 用 户 提 示 一 条 警 告 信 息 该 命 令 还 允 许 用 户 指 定 一 个 时 间 参 数, 可 以 是 一 个 精 确 的 时 间, 也 可 以 是 从 现 在 开 始 的 一 个 时 间 段 精 确 时 间 的 格 式 是 hh:mm, 表 示 小 时 和 分 钟 ; 时 间 段 由 + 和 分 钟 数 表 示 系 统 执 行 该 命 令 后, 会 自 动 进 行 数 据 同 步 的 工 作 该 命 令 的 一 般 格 式 为 :shutdown [ 选 项 ] [ 时 间 ] [ 警 告 信 息 ] 命 令 中 各 选 项 的 含 义 为 : - k 并 不 真 正 关 机, 而 只 是 发 出 警 告 信 息 给 所 有 用 户 ; - r 关 机 后 立 即 重 新 启 动 ; - h 关 机 后 不 重 新 启 动 ; - f 快 速 关 机, 重 启 动 时 跳 过 fsck; - n 快 速 关 机, 不 经 过 init 程 序 ; - c 取 消 一 个 已 经 运 行 的 shutdown 需 要 特 别 说 明 的 是, 该 命 令 只 能 由 超 级 用 户 使 用 cal 命 令 cal 命 令 的 功 能 是 显 示 某 年 某 月 的 日 历 该 命 令 的 一 般 格 式 为 :cal [ 选 项 ] [ 月 [ 年 ]] 命 令 中 各 选 项 的 含 义 为 : - j 显 示 出 给 定 月 中 的 每 一 天 是 一 年 中 的 第 几 天 ( 从 1 月 1 日 算 起 ); - y 显 示 出 整 年 的 日 历 clear 命 令 clear 命 令 的 功 能 是 清 除 屏 幕 上 的 信 息, 它 类 似 于 DOS 中 的 cls 命 令 清 屏 后, 提 示 符 移 动 到 屏 幕 左 上 角 压 缩 解 压 :tar 命 令 # tar -c 创 建 包 x 释 放 包 -v 显 示 命 令 过 程 -z 代 表 压 缩 包 例 如 : tar -cvf benet.tar /home/benet 把 /home/benet 目 录 打 包 ; tar -zcvf benet.tar.gz /mnt 把 目 录 打 包 并 压 缩 ;

138 tar -tf benet.tar 看 非 压 缩 包 的 文 件 列 表 ; tar -tf benet.tar.gz 看 压 缩 包 的 文 件 列 表 ; tar -xf benet.tar 非 压 缩 包 的 文 件 恢 复 ; tar -zxvf benet.tar.gz 压 缩 包 的 文 件 解 压 恢 复 系 统 管 理 命 令 :ps kill ps: 显 示 当 前 系 统 中 由 该 用 户 运 行 的 进 程 列 表 kill: 输 出 特 定 的 信 号 给 指 定 PID( 进 程 号 ) 的 进 程, 并 根 据 该 信 号 完 成 指 定 的 行 为 其 中 可 能 的 信 号 有 进 程 挂 起 进 程 等 待 进 程 终 止 等 ps:ps [ 选 项 ] kill:kill [ 选 项 ] 进 程 号 (PID) 查 看 系 统 命 令 查 看 内 核 :uname a 查 看 Ubuntu 版 本 :cat /etc/issue 查 看 内 核 加 载 的 模 块 :lsmod 查 看 PCI 设 备 :lspci 查 看 USB 设 备 :lsusb 查 看 网 卡 状 态 :sudo ethtool eth0 查 看 CPU 信 息 :cat /proc/cpuinfo 显 示 当 前 硬 件 信 息 :lshw 查 看 当 前 的 内 存 使 用 情 况 :free l 查 看 硬 盘 的 分 区 :sudo fdisk l 查 看 硬 盘 剩 余 空 间 :df -hdf H 查 看 目 录 占 用 空 间 :du -hs 目 录 名 10.4 Vi 编 辑 器 的 使 用 实 验 目 的 学 习 使 用 Vi 编 辑 器

139 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Linux 系 统 提 供 了 一 个 完 整 的 编 辑 器 家 族 系 列, 如 Ed Ex vi 和 emacs 等 按 功 能 它 们 可 以 分 为 两 大 类 : 行 编 辑 器 (Ed Ex) 和 全 屏 幕 编 辑 器 (vi emacs) 行 编 辑 器 每 次 只 能 对 一 行 进 行 操 作, 使 用 起 来 很 不 方 便 而 全 屏 幕 编 辑 器 可 以 对 整 个 屏 幕 进 行 编 辑, 用 户 编 辑 的 文 件 直 接 显 示 在 屏 幕 上, 从 而 克 服 了 行 编 辑 那 种 不 直 观 的 操 作 方 式, 便 于 用 户 学 习 和 使 用, 具 有 强 大 的 功 能 vi 是 Linux 系 统 的 第 一 个 全 屏 幕 交 互 式 编 辑 程 序, 它 从 诞 生 至 今 一 直 得 到 广 大 用 户 的 青 睐, 历 经 数 十 年 仍 然 是 人 们 主 要 使 用 的 文 本 编 辑 工 具, 足 以 见 其 生 命 力 之 强, 而 强 大 的 生 命 力 是 其 强 大 的 功 能 带 来 的 由 于 大 多 数 读 者 在 此 之 前 都 已 经 用 惯 了 Windows 平 台 上 的 编 辑 器, 因 此, 在 刚 刚 接 触 时 总 会 或 多 或 少 不 适 应, 但 只 要 习 惯 之 后, 就 能 感 受 到 它 的 方 便 与 快 捷 实 验 步 骤 vi 的 模 式 vi 有 3 种 模 式, 分 别 为 命 令 行 模 式 插 入 模 式 及 命 令 行 模 式 下 面 具 体 介 绍 各 模 式 的 功 能 1) 命 令 行 模 式 用 户 在 用 vi 编 辑 文 件 时, 最 初 进 入 的 为 一 般 模 式 在 该 模 式 中 用 户 可 以 通 过 上 下 移 动 光 标 进 行 删 除 字 符 或 整 行 删 除 等 操 作, 也 可 以 进 行 复 制 粘 贴 等 操 作, 但 无 法 编 辑 文 字 2) 插 入 模 式 只 有 在 该 模 式 下, 用 户 才 能 进 行 文 字 编 辑 输 入, 用 户 按 [ESC] 可 键 回 到 命 令 行 模 式 3) 底 行 模 式 在 该 模 式 下, 光 标 位 于 屏 幕 的 底 行 用 户 可 以 进 行 文 件 保 存 或 退 出 操 作, 也 可 以 设 置 编 辑 环 境, 如 寻 找 字 符 串 列 出 行 号 等 vi 的 基 本 流 程 1) 进 入 vi, 即 在 命 令 行 下 键 入 vi hello ( 文 件 名 ) 此 时 进 入 的 是 命 令 行 模 式, 光 标 位 于 屏 幕 的 上 方, 如 下 图 所 示 :

140 图 打 开 VI 编 辑 器 2) 在 命 令 行 模 式 下 键 入 i 进 入 插 入 模 式, 如 下 图 所 示 可 以 看 出, 在 屏 幕 底 部 显 示 有 插 入 表 示 插 入 模 式 中 的 输 入 状 态, 在 该 模 式 下 可 以 输 入 文 字 信 息 : 图 编 写 文 件 3) 最 后, 在 插 入 模 式 中, 按 Esc 键, 则 当 前 模 式 转 入 命 令 行 模 式, 并 在 底 行 行 中 输 入 :wq ( 存 盘 退 出 ) 进 入 底 行 模 式, 如 下 图 所 示 这 样, 就 完 成 了 一 个 简 单 的 vi 操 作 流 程 : 命 令 行 模 式 插 入 模 式 底 行 模 式 由 于 vi 在 不 同 的 模 式 下 有 不 同 的 操 作 功 能, 因 此, 一 定 要 时 刻 注 意 屏 幕 最 下 方 的 提 示, 分 清 所 在 的 模 式 :

141 图 保 存 文 件 vi 的 各 模 式 功 能 键 1) 命 令 行 模 式 常 见 功 能 键 如 下 表 所 示 : 功 能 键 功 能 i 切 换 到 插 入 模 式, 在 目 前 的 光 标 所 在 处 插 入 输 入 的 文 字, 已 存 在 的 文 字 会 向 后 退 a 切 换 到 插 入 模 式, 并 从 目 前 光 标 所 在 位 置 的 下 一 个 位 置 开 始 输 入 文 字 o 切 换 到 插 入 模 式, 且 从 行 首 开 始 插 入 新 的 一 行 [ctrl]+[b] 屏 幕 往 后 翻 动 一 页 [ctrl]+[f] 屏 幕 往 前 翻 动 一 页 [ctrl]+[u] 屏 幕 往 后 翻 动 半 页 [ctrl]+[d] 屏 幕 往 前 翻 动 半 页 0( 数 字 0) 光 标 移 到 本 行 的 开 头 G 光 标 移 动 到 文 件 的 最 后 ng 光 标 移 动 到 第 n 行 $ 移 动 到 光 标 所 在 行 的 行 尾 n<enter> 光 标 向 下 移 动 n 行 /name 在 光 标 之 后 查 找 一 个 名 为 name 的 字 符 串?name 在 光 标 之 前 查 找 一 个 名 为 name 的 字 符 串 x 删 除 光 标 所 在 位 置 的 一 个 字 符 X 删 除 光 标 所 在 位 置 的 前 一 个 字 符 dd 删 除 光 标 所 在 行 ndd 从 光 标 所 在 行 开 始 向 下 删 除 n 行 yy 复 制 光 标 所 在 行 nyy 复 制 光 标 所 在 行 开 始 的 向 下 n 行 p 将 缓 冲 区 内 的 字 符 粘 贴 到 光 标 所 在 位 置 ( 与 yy 搭 配 ) u 恢 复 前 一 个 动 作 2) 插 入 模 式 的 功 能 键 只 有 一 个, 即 按 Esc 键 可 回 到 命 令 行 模 式

142 3) 底 行 模 式 常 见 功 能 键 如 如 下 表 所 示 : 功 能 键 功 能 :w 将 编 辑 的 文 件 保 存 到 磁 盘 中 :q 退 出 vi( 系 统 对 做 过 修 改 的 文 件 会 给 出 提 示 ) :q! 强 制 退 出 vi( 对 修 改 过 的 文 件 不 作 保 存 ) :wq 存 盘 后 退 出 :w [filename] 另 存 一 个 名 为 filename 的 文 件 :set nu 显 示 行 号, 设 定 之 后, 会 在 每 一 行 的 前 面 显 示 对 应 行 号 :set nonu 取 消 行 号 显 示 10.5 GCC 编 译 器 实 验 目 的 学 习 和 了 解 Linux GCC 编 译 工 具 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 GCC 基 本 介 绍 GCC(GNU Compiler Collection,GNU 编 译 器 套 装 ), 是 一 套 由 GNU 开 发 的 编 程 语 言 编 译 器 它 是 一 套 以 GPL 及 LGPL 许 可 证 所 发 行 的 自 由 软 件, 也 是 GNU 计 划 的 关 键 部 分, 亦 是 自 由 的 类 Unix 及 苹 果 电 脑 Mac OS X 操 作 系 统 的 标 准 编 译 器 GCC 原 名 为 GNU C 语 言 编 译 器, 因 为 它 原 本 只 能 处 理 C 语 言 GCC 很 快 地 扩 展, 变 得 可 以 处 理 C++ 之 后 也 变 得 可 处 理 Fortran Pascal Objective-C Java, 以 及 Ada 与 其 他 语 言 Linux 系 统 下 的 GCC(GNU C Compiler) 是 GNU 推 出 的 功 能 强 大 性 能 优 越 的 多 平 台 编 译 器, 是 GNU 的 代 表 作 品 之 一 GCC 是 可 以 在 多 种 硬 体 平 台 上 编 译 出 可 执 行 程 序 的 超 级 编 译 器, 其 执 行 效 率 与 一 般 的 编 译 器 相 比 平 均 效 率 要 高 20%~30% GCC 编 译 器 能 将 C C++ 语 言 源 程 序 和 目 标 程 序 编 译 连 接 成 可 执 行

143 文 件, 如 果 没 有 给 出 可 执 行 文 件 的 名 字,GCC 将 生 成 一 个 名 为 a.out 的 文 件 在 Linux 系 统 中, 可 执 行 文 件 没 有 统 一 的 后 缀, 系 统 从 文 件 的 属 性 来 区 分 可 执 行 文 件 和 不 可 执 行 文 件 而 GCC 则 通 过 后 缀 来 区 别 输 入 文 件 的 类 别 一 般 情 况 下 gcc 认 为 预 处 理 后 的 文 件 (.i) 是 C 文 件, 并 且 设 定 c 形 式 的 连 接 ;g++ 认 为 预 处 理 后 的 文 件 (.i) 是 c++ 文 件, 并 且 设 定 c++ 形 式 的 连 接 GCC 所 遵 循 的 部 分 约 定 规 则 :.c 为 后 缀 的 文 件,C 语 言 源 文 件 ;.a 为 后 缀 的 文 件, 是 由 目 标 文 件 构 成 的 档 案 库 文 件 ;.C,.cc 或.cxx 为 后 缀 的 文 件, 是 C++ 源 代 码 文 件 ;.h 为 后 缀 的 文 件, 是 程 序 所 包 含 的 头 文 件 ;.i 为 后 缀 的 文 件, 是 已 经 预 处 理 过 的 C 源 代 码 文 件 ;.ii 为 后 缀 的 文 件, 是 已 经 预 处 理 过 的 C++ 源 代 码 文 件 ;.m 为 后 缀 的 文 件, 是 Objective-C 源 代 码 文 件 ;.o 为 后 缀 的 文 件, 是 编 译 后 的 目 标 文 件 ;.s 为 后 缀 的 文 件, 是 汇 编 语 言 源 代 码 文 件 ;.S 为 后 缀 的 文 件, 是 经 过 预 编 译 的 汇 编 语 言 源 代 码 文 件 在 gcc 的 使 用 过 程 中, 一 般 除 非 使 用 -c,-s, 或 -E 选 项 ( 或 者 因 为 其 他 的 错 误 阻 止 了 完 整 编 译 的 过 程 ), 否 则 连 接 总 是 最 后 的 步 骤 在 连 接 阶 段 中, 所 有 对 应 于 的 源 程 序 的.o 文 件,-l 库 文 件, 无 法 识 别 的 文 件 名 ( 包 括 指 定 的.o 目 标 文 件 和.a 库 文 件 ) 按 照 命 令 行 中 的 顺 序 传 递 给 连 接 器 GCC 的 执 行 过 程 GCC 是 C 语 言 的 编 译 器, 但 使 用 GCC 由 C 语 言 源 代 码 文 件 生 成 可 执 行 文 件 的 过 程 不 仅 仅 是 编 译 的 过 程, 而 是 要 经 历 四 个 相 互 关 联 的 步 骤 预 处 理 ( 也 称 预 编 译, Preprocessing) 编 译 (Compilation) 汇 编 (Assembly) 和 连 接 (Linking) 命 令 gcc 首 先 调 用 cpp 进 行 预 处 理, 在 预 处 理 过 程 中, 对 源 代 码 文 件 中 的 文 件 包 含 (include) 预 编 译 语 句 ( 如 宏 定 义 define 等 ) 进 行 分 析 接 着 调 用 cc1 进 行 编 译, 这 个 阶 段 根 据 输 入 文 件 生 成 以.o 为 后 缀 的 目 标 文 件 汇 编 过 程 是 针 对 汇 编 语 言 的 步 骤, 调 用 as 进 行 工 作 一 般 来 讲,.S 为 后 缀 的 汇 编 语 言 源 代 码 文 件 和 汇 编.s 为 后 缀 的 汇 编 语 言 文 件 经 过 预 编 译 和 汇 编 之 后 都 生 成 以.o 为 后 缀 的 目 标 文 件 当 所 有 的 目 标 文 件 都 生 成 之 后,gcc 就 调 用 ld 来 完 成 最 后 的 关 键 性 工 作, 这 个 阶 段 就 是 连 接 在 连 接 阶 段, 所 有 的 目 标 文 件 被 安 排 在 可 执 行 程 序 中 的 恰 当 的 位 置, 同 时 该 程 序 所 调 用 到 的 库 函 数 也 从 各 自 所 在 的 档 案 库 中 连 到 合 适 的 地 方 GCC 的 常 见 编 译 选 项 GCC 的 编 译 选 项 中 包 括 总 体 选 项 语 言 选 项 预 处 理 器 选 项 汇 编 器 选 项 等 等 -c 编 译 或 者 汇 编 源 文 件, 但 是 不 作 连 接 编 译 器 输 出 对 应 于 源 文 件 的 目 标 文 件 缺 省 情 况 下,GCC 通 过.o 替 换 源 文 件 名 后 缀.c,.i,.s 等 等, 产 生 目 标 文 件 名 可 以 使 用 -o 选 项 选 择 其 他 名 字 GCC 忽 略 -c 选 项 后 面 任 何 无 法 识 别 的 输 入 文 件 ( 他 们 一 般 不 需 要 编 译 或 汇 编 )

144 -S 编 译 后 即 停 止, 不 进 行 汇 编 对 于 每 个 输 入 的 非 汇 编 语 言 文 件, 输 出 文 件 是 汇 编 语 言 文 件 在 缺 省 情 况 下,GCC 通 过 用.o 替 换 源 文 件 名 后 缀.c,.i 等 等, 产 生 目 标 文 件 名 可 以 使 用 -o 选 项 选 择 其 他 名 字 GCC 忽 略 任 何 不 需 要 编 译 的 输 入 文 件 -E 预 处 理 后 即 刻 停 止, 不 进 行 编 译 预 处 理 之 后 的 代 码 送 往 标 准 输 出 GCC 忽 略 任 何 不 需 要 预 处 理 的 输 入 文 件 -o file 指 定 输 出 文 件 为 file. 该 选 项 不 在 乎 GCC 产 生 什 么 输 出, 无 论 是 可 执 行 文 件, 目 标 文 件, 汇 编 文 件 还 是 预 处 理 后 的 c 代 码 一 般 只 能 指 定 一 个 输 入 文 件, 当 编 译 多 个 输 入 文 件 时, 使 用 -o 选 项 没 有 意 义, 除 非 输 出 一 个 可 执 行 文 件 如 果 没 有 使 用 -o 选 项, 默 认 输 出 结 果 是 : 可 执 行 文 件 为 a.out, source.suffix 的 目 标 文 件 是 source.o, 汇 编 文 件 是 source.s, 而 预 处 理 后 的 c 源 代 码 送 往 标 准 输 出 -v 显 示 执 行 编 译 阶 段 的 命 令 同 时 显 示 编 译 器 驱 动 程 序, 预 处 理 器, 编 译 器 的 版 本 号 -pipe 在 编 译 过 程 的 不 通 阶 段 间 使 用 管 道 而 非 临 时 文 件 进 行 通 信 这 个 选 项 在 某 些 系 统 上 无 法 工 作, 因 为 那 些 系 统 的 汇 编 器 不 能 从 管 道 读 取 数 据 -ansi 支 持 符 合 ANSI 标 准 的 c 程 序 这 样 就 会 关 闭 GNU C 中 某 些 不 兼 容 ANSI C 的 特 性, 例 如 asm,inline 和 typeof 关 键 字, 以 及 诸 如 unix 和 vax 这 些 表 明 当 前 系 统 类 型 的 预 定 义 宏 同 时 开 启 不 受 欢 迎 和 极 少 使 用 的 ANSI trigraph 特 性, 以 及 禁 止 $ 成 为 标 识 符 的 一 部 分 如 果 是 使 用 了 -ansi 选 项, 下 面 的 这 些 可 选 的 关 键 字, asm, extension, inline 和 typeof 仍 然 有 效 当 用 在 ANSI C 程 序 当 中 的 时 候, 可 以 把 他 们 放 在 头 文 件 中 使 用 -ansi 选 项 不 会 自 动 拒 绝 编 译 非 ANSI 程 序, 除 非 增 加 -pedantic 选 项 作 为 -ansi 选 项 的 补 充 使 用 -ansi 选 项 的 时 候, 预 处 理 器 会 预 定 义 一 个 STRICT_ANSI 宏 有 些 头 文 件 关 注 此 宏, 以 避 免 声 明 某 些 函 数, 或 者 避 免 定 义 某 些 宏, 这 些 函 数 和 宏 不 被 ANSI 标 准 调 用 ; 这 样 就 不 会 干 扰 在 其 他 地 方 使 用 这 些 名 字 的 程 序 了 -fno-asm 不 把 asm,inline 或 typeof 当 作 关 键 字, 因 此 这 些 词 可 以 用 做 标 识 符 用 asm, inline 和 typeof 能 够 替 代 他 们 -ansi 隐 含 声 明 了 -fno-asm -include file 在 处 理 常 规 输 入 文 件 之 前, 首 先 处 理 文 件 file, 其 结 果 是, 文 件 file 的 内 容 先 得 到 编 译 命 令 行 上 任 何 -D 和 -U 选 项 永 远 在 -include file 之 前 处 理, 无 论 他 们 在 命 令 行 上 的 顺 序 如 何 -include 和 -imacros 选 项 按 书 写 顺 序 处 理

145 -imacros file 在 处 理 常 规 输 入 文 件 之 前, 首 先 处 理 文 件 file, 但 是 忽 略 输 出 结 果 由 于 丢 弃 了 文 件 file 的 输 出 内 容, -imacros file 选 项 的 唯 一 效 果 是 使 文 件 file 中 的 宏 定 义 生 效, 可 以 用 于 其 他 输 入 文 件 在 处 理 -imacros file 选 项 之 前, 预 处 理 器 首 先 处 理 -D 和 -U 选 项, 并 不 在 乎 他 们 在 命 令 行 上 的 顺 序 然 而 -include 和 -imacros 选 项 按 书 写 顺 序 处 理 GCC 的 常 见 优 化 选 项 gcc 默 认 提 供 了 5 级 优 化 选 项 的 集 合 : -O0: 无 优 化 ( 默 认 ) -O 和 -O1: 使 用 能 减 少 目 标 文 件 大 小 以 及 执 行 时 间 并 且 不 会 使 编 译 时 间 明 显 增 加 的 优 化 在 编 译 大 型 程 序 的 时 候 会 显 著 增 加 编 译 时 内 存 的 使 用 -O2: 包 含 -O1 的 优 化 并 增 加 了 不 需 要 在 目 标 文 件 大 小 和 执 行 速 度 上 进 行 折 衷 的 优 化 编 译 器 不 执 行 循 环 展 开 以 及 函 数 内 联 此 选 项 将 增 加 编 译 时 间 和 目 标 文 件 的 执 行 性 能 -Os: 专 门 优 化 目 标 文 件 大 小, 执 行 所 遇 的 不 增 加 目 标 文 件 大 小 的 -O2 优 化 选 项 并 且 执 行 专 门 减 小 目 标 文 件 大 小 的 优 化 选 项 -O3: 打 开 所 有 -O2 的 优 化 选 项 并 且 增 加 -finline-functions,-funswitch-loops,-fpredictive -commoning,-fgcse-after-reload and ftree-vectorize 优 化 选 项 GCC 的 常 见 编 译 命 令 实 例 对 于 在 使 用 GCC 编 译 的 时 候, 常 见 的 使 用 编 译 的 参 数 如 下, 以 hello.c 文 件 为 例 gcc o hello hello.c : 将 hello.c 文 件 编 译 成 hello 的 可 执 行 文 件 gcc c hello.c : 将 hello.c 文 件 生 成 hello.o 文 件 gcc -E hello.c : 只 是 激 活 预 处 理, 不 生 成 文 档, 需 要 把 它 重 定 向 到 另 外 一 个 文 档 里 gcc S hello.c : 将 hello.c 文 件 生 成 hello.s 文 件 的 汇 编 代 码 gcc pipe o hello hello.c : 使 用 管 道 代 替 编 译 中 临 时 文 档 gcc hello.c include /root/hello.h : 包 含 某 个 代 码, 简 单 来 说, 就 是 以 某 个 文 档, 需 要 另 外 一 个 文 档 的 时 候, 就 能 够 用 它 设 定, 功 能 就 相 当 于 在 代 码 中 使 用 #include<hello.h> 实 验 步 骤 1) 在 Ubuntu 中 单 击 菜 单 应 用 程 序 -> 附 件 -> 终 端 打 开 终 端 2) 使 用 vi 编 辑 器 编 写 hello.c 程 序 : #include <stdio.h> int main() { printf("hello! This is our embedded world!\n"); return 0; }

146 3) 执 行 如 下 命 令 编 译 生 成 可 执 行 文 件 : $ gcc -o hello hello.c 5) 运 行 hello: #./hello Hello! This is our embedded world! 10.6 Makefile 实 验 目 的 学 习 和 了 解 Makefile 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+); 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 在 Linux 的 环 境 下 面 如 果 不 会 使 用 GNU make 来 构 建 和 管 理 自 己 的 工 程, 很 难 成 为 一 名 优 秀 的 Linux 程 序 员 在 Linux 环 境 下 使 用 GNU 的 make 工 具 能 够 比 较 容 易 的 构 建 一 个 属 于 自 己 的 工 程, 整 个 工 程 当 中 的 编 译 只 需 要 一 个 命 令 就 可 以 完 成 编 译 连 接 以 至 于 最 后 的 执 行 但 是 完 成 这 些 动 作 的 前 提 条 件 是 能 够 话 费 一 定 的 时 间 去 完 成 一 个 或 者 多 个 称 之 为 Makefile 的 文 件 在 编 写 Makefile 之 前, 首 先 需 要 明 确 一 些 基 本 概 念 编 译 : 把 高 级 语 言 书 写 的 代 码 转 换 为 机 器 可 识 别 的 机 器 指 令 编 译 高 级 语 言 后 生 成 的 指 令 虽 然 可 被 机 器 识 别, 但 是 还 不 能 被 执 行 编 译 时, 编 译 器 检 查 高 级 语 言 的 语 法 函 数 与 变 量 的 声 明 是 否 正 确 只 有 所 有 的 语 法 正 确 相 关 的 变 量 定 义 正 确, 编 译 器 就 可 以 编 译 出 正 确 中 间 目 标 文 件 一 般, 一 个 高 级 语 言 的 源 文 件 都 可 对 应 一 个 目 标 文 件 在 Linux 下, 目 标 文 件 的 默 认 后 缀 为 *.o 链 接 : 将 多 个.o 文 件, 或 者.o 文 件 和 库 文 件 链 接 成 为 可 为 可 被 操 作 系 统 执 行 的 可 执 行 文 件 程 序 连 接 器 不 检 查 函 数 所 在 的 源 文 件, 一 般 只 是 检 测 所 有 的.o 文 件 中 定 义 的 符 号 将.o 文 件 中 使 用 的 函 数 和 其 他.o 或 者 库 文 件 中 的 相 关 符 号 进 行 合 并, 最 后 生 成 一 个 可 执 行 的 程 序 ld 是 GNU 的 链 接 器

147 静 态 库 : 它 是 多 个.o 文 件 的 集 合 Linux 中 静 态 库 文 件 的 后 缀 为 *.a, 静 态 库 中 的 各 个 成 员 (.o 文 件 ) 没 有 特 殊 的 存 在 格 式, 仅 仅 是 一 个.o 文 件 的 集 合 使 用 ar 工 具 维 护 和 管 理 静 态 库 共 享 库 : 在 Linux 里 面 一 般 是 以.so 文 件 结 尾, 它 也 是.o 文 件 的 集 合, 但 是 这 些.o 文 件 按 照 一 种 特 殊 的 方 式 生 成 的 对 象 模 块 的 各 个 成 员 的 地 址 ( 变 量 引 用 和 函 数 调 用 ) 都 是 相 对 地 址 当 程 序 运 行 时, 可 以 动 态 加 载 库 文 件 和 执 行 模 块 程 序 Makefile 简 介 什 么 是 makefile? 或 许 很 多 Winodws 的 程 序 员 都 不 知 道 这 个 东 西, 因 为 那 些 Windows 的 IDE 都 为 你 做 了 这 个 工 作, 但 我 觉 得 要 作 一 个 好 的 和 professional 的 程 序 员,makefile 还 是 要 懂 这 就 好 像 现 在 有 这 么 多 的 HTML 的 编 辑 器, 但 如 果 你 想 成 为 一 个 专 业 人 士, 你 还 是 要 了 解 HTML 的 标 识 的 含 义 特 别 在 Unix 下 的 软 件 编 译, 你 就 不 能 不 自 己 写 makefile 了, 会 不 会 写 makefile, 从 一 个 侧 面 说 明 了 一 个 人 是 否 具 备 完 成 大 型 工 程 的 能 力 因 为,makefile 关 系 到 了 整 个 工 程 的 编 译 规 则 一 个 工 程 中 的 源 文 件 不 计 数, 其 按 类 型 功 能 模 块 分 别 放 在 若 干 个 目 录 中,makefile 定 义 了 一 系 列 的 规 则 来 指 定, 哪 些 文 件 需 要 先 编 译, 哪 些 文 件 需 要 后 编 译, 哪 些 文 件 需 要 重 新 编 译, 甚 至 于 进 行 更 复 杂 的 功 能 操 作, 因 为 makefile 就 像 一 个 Shell 脚 本 一 样, 其 中 也 可 以 执 行 操 作 系 统 的 命 令 makefile 带 来 的 好 处 就 是 自 动 化 编 译, 一 旦 写 好, 只 需 要 一 个 make 命 令, 整 个 工 程 完 全 自 动 编 译, 极 大 的 提 高 了 软 件 开 发 的 效 率 make 是 一 个 命 令 工 具, 是 一 个 解 释 makefile 中 指 令 的 命 令 工 具, 一 般 来 说, 大 多 数 的 IDE 都 有 这 个 命 令, 比 如 :Delphi 的 make,visual C++ 的 nmake, Linux 下 GNU 的 make 可 见,makefile 都 成 为 了 一 种 在 工 程 方 面 的 编 译 方 法 Make 工 具 最 主 要 也 是 最 基 本 的 功 能 就 是 通 过 makefile 文 件 来 描 述 源 程 序 之 间 的 相 互 关 系 并 自 动 维 护 编 译 工 作 而 makefile 文 件 需 要 按 照 某 种 语 法 进 行 编 写, 文 件 中 需 要 说 明 如 何 编 译 各 个 源 文 件 并 连 接 生 成 可 执 行 文 件, 并 要 求 定 义 源 文 件 之 间 的 依 赖 关 系 当 使 用 make 工 具 进 行 编 译 时, 工 程 中 以 下 几 种 文 件 在 执 行 make 时 将 会 被 编 译 ( 重 新 编 译 ): 所 有 的 源 文 件 没 有 被 编 译 过, 则 对 各 个 C 源 文 件 进 行 编 译 并 进 行 链 接, 生 成 最 后 的 可 执 行 程 序 每 一 个 在 上 次 执 行 make 之 后 修 改 过 的 C 源 文 件 代 码 在 本 次 执 行 make 时 会 被 重 新 编 译 头 文 件 在 上 一 次 执 行 make 之 后 被 修 改 则 所 有 包 含 此 头 文 件 的 C 源 文 件 在 本 次 执 行 make 时 将 会 被 重 新 编 译 Makefile 内 容 概 述 一 般, 在 一 个 完 整 的 Makefile 中, 包 含 了 5 个 东 西 : 显 示 规 则 隐 含 规 则 变 量 的 定 义 指 示 符 和 注 释 关 于 规 则 变 量 和 Makefile 指 示 符 显 示 规 则 : 它 描 述 了 在 任 何 情 况 下 如 何 更 新 一 个 或 者 多 个 被 称 为 目 标 的 文 件 (Makefile 的 目 标 文 件 ) 在 书 写 Makefile 时 需 要 明 确 地 给 出 目 标 文 件 目 标 的 依 赖 文 件 列 表 以 及 更 新 目 标 文 件 所 需 要 的 命 令

148 隐 含 规 则 : 它 是 make 根 据 此 类 目 标 文 件 的 名 称 而 自 动 推 导 出 来 的 规 则 make 根 据 目 标 文 件 的 名 字, 可 以 自 动 产 生 目 标 的 依 赖 文 件 并 使 用 默 认 的 命 令 来 对 目 标 进 行 更 新 变 量 定 义 : 就 是 使 用 一 个 字 符 串 代 表 一 段 文 本 串, 当 定 义 了 变 量 之 后,Makefile 后 续 在 需 要 使 用 此 文 本 串 的 地 方, 通 过 引 用 这 个 变 量 来 实 现 对 文 本 串 的 使 用 Makefile 指 示 符 : 指 示 符 指 明 在 make 程 序 读 取 Makefile 文 件 过 程 中 所 要 执 行 的 一 个 动 作 其 中 包 括 : 读 取 一 个 文 件, 读 取 给 定 文 件 名 的 文 件 决 定 处 理 或 者 忽 略 Makefile 中 的 某 一 特 定 部 分 定 义 一 个 多 行 变 量 注 释 :Makefile 中 的 # 字 符 后 的 内 容 被 作 为 注 释 内 容 ( 这 个 特 点 和 shell 脚 本 一 致 ) 处 理 如 果 此 行 的 第 一 个 非 空 字 符 为 #, 那 么 此 行 为 注 释 行 注 释 行 的 结 尾 如 果 存 在 反 斜 线 (\), 那 么 下 一 行 也 被 作 为 注 释 行 一 般 在 书 写 Makefile 时 推 荐 将 注 释 作 为 一 个 独 立 的 行, 而 不 要 和 Makefile 的 有 效 行 放 在 一 行 中 书 写 当 在 Makefile 中 需 要 使 用 字 符 # 时, 可 以 使 用 反 斜 线 加 # (\#) 来 实 现, 其 表 示 将 makefile 作 为 一 字 符 而 不 是 注 释 的 开 始 标 志 注 意 :Makefile 中 的 第 一 个 规 则 之 后 的 所 有 以 Tab 字 符 开 始 的 行,make 程 序 都 会 将 其 给 系 统 的 shell 程 序 去 解 释 执 行 因 此 以 Tab 字 符 开 始 的 注 释 行 也 会 被 交 给 shell 来 处 理, 此 命 令 行 是 否 需 要 被 执 行 是 由 shell 程 序 来 判 决 的 一 般, 在 默 认 情 况 下,make 会 在 工 作 目 录 ( 执 行 make 的 目 录 ) 下 按 照 文 件 名 顺 序 寻 找 makefile 文 件 读 取 并 执 行, 查 找 的 文 件 名 顺 序 为 : GNUmakefile makefile makefile 通 常 应 该 使 用 makefile 或 者 Makefile 作 为 一 个 makefile 的 文 件 名, 不 推 荐 使 用 GNUmakefile Makefile 指 示 符 当 一 个 Makefile 中 包 含 有 其 他 的 一 个 或 者 多 个 makefile 文 件 时,Makefile 中 包 含 其 他 文 件 的 关 键 字 是 include, 和 C 语 言 对 头 文 件 的 包 含 方 式 一 致 include 指 示 符 告 诉 make 暂 停 读 取 当 前 的 Makefile, 而 转 去 读 取 include 指 定 的 一 个 或 者 多 个 文 件, 完 成 以 后 再 继 续 当 前 Makefile 的 读 取 Makefile 中 指 示 符 include 书 写 在 独 立 的 一 行, 其 形 式 如 下 : include FILENAMES. 其 中 FILENAMES 是 shell 所 支 持 的 文 件 名 ( 可 以 使 用 通 配 符 ) 指 示 符 include 所 在 的 行 可 以 一 个 或 者 多 个 空 格 (make 程 序 在 处 理 时 将 忽 略 这 些 空 格 ) 开 始, 切 忌 不 能 以 [Tab] 字 符 开 始 指 示 符 include 和 文 件 名 之 间 多 个 文 件 之 间 使 用 空 格 或 者 [Tab] 键 隔 开 行 尾 的 空 白 字 符 在 处 理 时 被 忽 略 使 用 指 示 符 包 含 进 来 的 Makefile 中, 如 果 存 在 变 量 或 者 函 数 的 引 用 它 们 将 会 在 包 含 它 们 的 Makefile 中 被 展 开 make 程 序 在 处 理 指 示 符 include 时, 将 暂 停 对 当 前 使 用 指 示 符 include 的 makefile 文 件

149 的 读 取, 而 转 去 以 此 读 取 由 include 所 在 的 makefile 文 件 通 常 指 示 符 include 用 在 以 下 场 合 : 1) 有 多 个 不 同 的 程 序, 由 不 同 目 录 下 的 几 个 独 立 的 Makefile 来 描 述 其 创 建 或 者 更 新 规 则 它 们 需 要 使 用 一 组 通 用 的 变 量 定 义 或 者 模 式 规 则 通 用 的 做 法 是 将 这 些 共 同 使 用 的 变 量 或 者 模 式 规 则 定 义 在 一 个 文 件 中 ( 没 有 具 体 的 文 件 命 名 限 制 ), 在 需 要 使 用 的 Makefie 中 使 用 指 示 符 include 来 包 含 此 文 件 2) 当 根 据 源 文 件 自 动 产 生 依 赖 文 件 时 ; 我 们 可 以 将 自 动 产 生 的 依 赖 关 系 保 存 在 另 外 一 个 文 件 中, 主 Makefile 使 用 指 示 符 include 包 含 这 些 文 件 这 样 的 做 法 比 直 接 在 主 Makefile 中 追 加 依 赖 文 件 的 方 法 要 明 智 的 多 如 果 指 示 符 include 指 定 的 文 件 不 是 以 斜 线 开 始 ( 绝 对 路 径, 如 /usr/src/makefile...), 而 且 当 前 目 录 下 也 不 存 在 此 文 件 ;make 将 根 据 文 件 名 试 图 在 以 下 几 个 目 录 下 查 找 : 首 先, 查 找 使 用 命 令 行 选 项 -I 或 者 --include-dir 指 定 的 目 录, 如 果 找 到 指 定 的 文 件, 则 使 用 这 个 文 件 ; 否 则 继 续 依 此 搜 索 以 下 几 个 目 录 ( 如 果 其 存 在 ): /usr/gnu/include /usr/local/include 和 /usr/include 当 在 这 些 目 录 下 都 没 有 找 到 include 指 定 的 文 件 时,make 将 会 提 示 一 个 包 含 文 件 未 找 到 的 告 警 提 示, 但 是 不 会 立 刻 退 出 而 是 继 续 处 理 Makefile 的 后 续 内 容 当 完 成 读 取 整 个 Makefile 后, make 将 试 图 使 用 规 则 来 创 建 通 过 指 示 符 include 指 定 的 但 未 找 到 的 文 件, 当 不 能 创 建 它 时 ( 没 有 创 建 这 个 文 件 的 规 则 ),make 将 提 示 致 命 错 误 并 退 出 会 输 出 类 似 如 下 错 误 提 示 : Makefile: 错 误 的 行 数 : 未 找 到 文 件 名 : 提 示 信 息 (No such file or directory) Make: *** No rule to make target <filename>. Stop 通 常 我 们 在 Makefile 中 可 使 用 -include 来 代 替 include, 来 忽 略 由 于 包 含 文 件 不 存 在 或 者 无 法 创 建 时 的 错 误 提 示 ( - 的 意 思 是 告 诉 make, 忽 略 此 操 作 的 错 误 make 继 续 执 行 ) 像 下 边 那 样 : -include FILENAMES... 使 用 这 种 方 式 时, 当 所 要 包 含 的 文 件 不 存 在 时 不 会 有 错 误 提 示 make 也 不 会 退 出 ; 除 此 之 外, 和 第 一 种 方 式 效 果 相 同 以 下 是 这 两 种 方 式 的 比 较 : 使 用 include FILENAMES...,make 程 序 处 理 时, 如 果 FILENAMES 列 表 中 的 任 何 一 个 文 件 不 能 正 常 读 取 而 且 不 存 在 一 个 创 建 此 文 件 的 规 则 时 make 程 序 将 会 提 示 错 误 并 退 出 使 用 -include FILENAMES... 的 情 况 是, 当 所 包 含 的 文 件 不 存 在 或 者 不 存 在 一 个 规 则 去 创 建 它,make 程 序 会 继 续 执 行, 只 有 真 正 由 于 不 能 正 确 完 成 终 极 目 标 的 重 建 时 ( 某 些 必 需 的 目 标 无 法 在 当 前 已 读 取 的 makefile 文 件 内 容 中 找 到 正 确 的 重 建 规 则 ), 才 会 提 示 致 命 错 误 并 退 出 变 量 MAKEFILES 如 果 当 前 环 境 定 义 了 一 个 MAKEFILES 的 环 境 变 量,make 执 行 时 首 先 将 此 变 量 的 值 作 为 需 要 读 入 的 Makefile 文 件, 多 个 文 件 之 间 使 用 空 格 分 开 类 似 使 用 指 示 符 include 包 含 其 它 Makefile

150 文 件 一 样, 如 果 文 件 名 非 绝 对 路 径 而 且 当 前 目 录 也 不 存 在 此 文 件,make 会 在 一 些 默 认 的 目 录 中 去 寻 找 这 样 的 使 用 方 法 和 include 的 区 别 : 环 境 变 量 指 定 的 makefile 文 件 中 的 目 标 不 会 被 作 为 make 执 行 的 终 极 目 标 也 就 是, 这 些 文 件 中 所 定 义 规 则 的 目 标,make 不 会 将 其 作 为 终 极 目 标 来 看 待 环 境 变 量 所 定 义 的 文 件 列 表, 在 执 行 make 时, 如 果 不 能 找 到 其 中 某 一 文 件 ( 不 存 在 或 者 无 法 创 建 ) make 不 会 提 示 错 误, 也 不 退 出 就 是 说 环 境 变 量 MAKEFILES 定 义 的 包 含 文 件 是 否 存 在 不 会 导 致 make 错 误 make 在 执 行 时, 首 先 读 取 的 是 环 境 变 量 MAKEFILES 所 指 定 的 文 件 列 表, 之 后 才 是 工 作 目 录 下 的 makefile 文 件, include 所 指 定 的 文 件 是 在 make 发 现 此 关 键 字 的 时 侯, 暂 停 当 前 makefile 的 执 行, 转 而 执 行 include 所 指 定 的 文 件 make 如 何 解 析 makefile 文 件 GNU make 的 执 行 过 程 分 为 两 个 阶 段 : 第 一 阶 段 : 读 取 所 有 的 makefile 文 件 ( 包 括 MAKEFILES 变 量 指 定 的 指 示 符 include 指 定 的 以 及 命 令 行 选 项 -f(--file) 指 定 的 makefile 文 件 ), 内 建 所 有 的 变 量 明 确 规 则 和 隐 含 规 则, 并 建 立 所 有 目 标 和 依 赖 之 间 的 依 赖 关 系 结 构 链 表 第 二 阶 段 : 根 据 第 一 阶 段 已 经 建 立 的 依 赖 关 系 结 构 链 表 决 定 哪 些 目 标 需 要 更 新, 并 使 用 对 应 的 规 则 来 重 建 这 些 目 标 理 解 make 执 行 过 程 的 两 个 阶 段 是 很 重 要 的 它 能 帮 助 我 们 更 深 入 的 了 解 执 行 过 程 中 变 量 以 及 函 数 是 如 何 被 展 开 的 变 量 和 函 数 的 展 开 问 题 是 书 写 Makefile 时 容 易 犯 错 和 引 起 大 家 迷 惑 的 地 方 之 一 Makefile 的 规 则 在 Makefile 中, 规 则 描 述 了 何 种 情 况 下 使 用 什 么 命 令 来 重 建 一 个 特 定 的 文 件, 此 文 件 被 称 为 规 则 目 标 ( 通 常 规 则 中 的 目 标 只 有 一 个 ) 规 则 所 罗 列 的 其 他 文 件 称 为 目 标 的 依 赖, 而 规 则 中 的 命 令 是 用 来 更 新 或 者 创 建 此 规 则 的 目 标 除 了 makefile 的 终 极 目 标 所 在 的 规 则 以 外, 其 他 规 则 的 顺 序 在 makefile 文 件 中 没 有 意 义 终 极 目 标 就 是 当 没 有 使 用 make 命 令 行 指 定 具 体 目 标 时,make 默 认 的 那 一 个 目 标 它 是 makefile 文 件 中 第 一 个 规 则 的 目 标 如 果 在 makefile 中 第 一 个 规 则 有 多 个 目 标 的 话, 那 么 多 个 目 标 中 的 第 一 个 规 则 的 目 标 终 极 目 标 是 执 行 make 的 唯 一 目 的, 其 所 在 的 规 则 作 为 第 一 个 规 则 其 他 的 规 则 是 在 完 成 重 建 终 极 目 标 的 过 程 中 被 连 带 出 来 的 这 些 目 标 所 在 的 规 则 在 Makefile 中 的 顺 序 无 关 紧 要 规 则 语 法 通 常 规 则 的 语 法 格 式 如 下 : Objects:Regulations

151 Command... 或 者 Objects:Regulations ;Command Command... 在 规 则 中 Objects 可 以 是 空 格 分 开 的 多 个 文 件 名, 也 可 以 是 一 个 标 签 ( 执 行 清 空 的 clean ) Objects 的 文 件 名 可 以 使 用 通 配 符 书 写 规 则 时 我 们 需 要 注 意 以 下 几 点 : 规 则 的 命 令 部 分 有 两 种 书 写 方 式 :a. 命 令 可 以 和 目 标 : 依 赖 描 述 放 在 同 一 行 命 令 在 依 赖 文 件 列 表 后 并 使 用 分 号 (;) 和 依 赖 文 件 列 表 分 开 b. 命 令 在 目 标 : 依 赖 的 描 述 的 下 一 行, 作 为 独 立 的 命 令 行 当 作 为 独 立 的 命 令 行 时 此 行 必 须 以 [Tab] 字 符 开 始 在 Makefile 中, 在 第 一 个 规 则 之 后 出 现 的 所 有 以 [Tab] 字 符 开 始 的 行 都 会 被 当 作 命 令 来 处 理 Makefile 中 对 $ 有 特 殊 的 含 义 ( 表 示 变 量 或 者 函 数 的 引 用 ), 如 果 我 们 的 规 则 如 果 需 要 $, 需 要 书 写 两 个 连 续 的 $$ 如 果 Makefile 有 一 个 叫 长 的 行, 可 以 使 用 反 斜 线 \ 将 其 书 写 到 几 个 独 立 的 物 理 行 上 虽 然 make 对 Makefile 文 本 行 的 最 大 长 度 是 没 有 限 制 的, 但 是 还 是 建 议 这 样 做 不 仅 书 写 方 便, 而 且 更 有 利 于 别 人 的 阅 读 ( 这 也 可 以 体 现 一 个 程 序 员 的 修 养 ) 规 则 的 中 心 思 想 是 : 目 标 文 件 的 内 容 是 由 依 赖 文 件 决 定, 依 赖 文 件 的 任 何 一 处 改 动, 将 导 致 目 前 已 经 存 在 的 目 标 文 件 的 内 容 过 期 规 则 的 命 令 为 重 建 目 标 提 供 了 方 法 这 些 命 令 运 行 在 系 统 的 shell 之 上 依 赖 类 型 GNU make 的 规 则 中 可 以 使 用 两 种 不 通 类 型 的 依 赖 :1. 在 以 前 章 节 所 提 到 的 规 则 中 使 用 的 是 常 规 依 赖, 这 也 是 在 书 写 Makefile 的 时 候 最 为 常 用 的 一 种 2. 另 外 一 种 在 我 们 书 写 Makefile 时 不 会 经 常 使 用, 它 还 比 较 特 殊 称 之 为 order-only 依 赖 一 个 规 则 的 常 规 依 赖 ( 通 常 是 多 个 依 赖 文 件 ) 表 明 了 两 件 事 : 首 先, 它 决 定 了 重 建 规 则 目 标 所 要 执 行 命 令 的 顺 序 ; 表 明 在 更 新 这 个 规 则 的 目 标 ( 执 行 此 规 则 的 命 令 行 ) 之 前 必 须 要 按 照 什 么 样 的 顺 序 执 行 那 些 命 令 来 重 建 这 些 依 赖 文 件 ( 对 所 有 依 赖 文 件 的 重 建, 使 用 明 确 或 者 隐 含 规 则, 相 当 于 X:Y Z, 在 重 建 X 之 前, 首 先 需 要 完 成 对 它 的 依 赖 文 件 Y 和 Z 的 重 建 重 建 Y 和 Z 的 过 程 就 是 执 行 Makefile 中 文 件 Y 和 Z 的 规 则 ) 其 次, 它 确 定 了 一 个 依 存 关 系 ; 规 则 中 如 果 依 赖 文 件 的 任 何 一 个 比 目 标 文 件 新, 则 被 认 为 规 则 的 目 标 已 经 过 期 同 时 需 要 重 建 目 标 一 般 情 况 下, 如 果 规 则 中 依 赖 文 件 中 的 任 何 一 个 被 更 新, 则 规 则 的 目 标 相 应 地 也 应 该 被 更 新 在 通 常 情 况 下, 如 果 我 们 需 要 定 义 一 个 这 样 的 规 则, 在 更 新 目 标 ( 目 标 文 件 已 经 存 在 ) 时 只 需 要 根 据 依 赖 文 件 中 的 部 分 来 决 定 目 标 是 否 需 要 被 重 建, 而 不 是 在 依 赖 文 件 的 任 何 一 个 被 修 改 后 都 重 建 目 标 文 件 名 使 用 通 配 符

152 Makefile 中 表 示 一 个 单 一 的 文 件 名 时 可 使 用 通 配 符 可 以 使 用 的 通 配 符 有 : *? [.] 在 Makefile 中 通 配 符 的 用 法 和 含 义 和 Linux(unix) 的 Bourne shell 完 全 相 同 例 如, *.c 代 表 了 当 前 工 作 目 录 下 所 有 的 以.c 结 尾 的 文 件 等 等 在 Makefile 中 通 配 符 一 般 只 出 现 在 以 下 两 种 场 合 : 可 以 用 在 规 则 的 目 标 依 赖 中, 此 时 make 会 自 动 将 其 展 开 ; 可 出 现 在 规 则 的 命 令 中, 其 展 开 是 在 shell 执 行 此 命 令 时 完 成 如 果 规 则 中 的 某 一 个 文 件 的 文 件 名 包 含 作 为 通 配 符 的 字 符 ( *. 字 符 ), 在 使 用 文 件 时 需 要 对 文 件 名 中 的 通 配 符 进 行 转 义 处 理, 使 用 反 斜 线 (\) 来 进 行 通 配 符 的 转 义 例 如 foo\*bar 在 Makefile 中 它 表 示 了 文 本 foo*bar 在 Makefile 当 中 的 清 空 过 程 文 件 规 则 : clean : rm -f *.o Makefile 使 用 举 例 以 hello.c 文 件 为 例 : # compile the hello.c Object=hello Depend=hello.o $(Object):$(Depend) $(CC) $(CFLAGS) -o $@ $< clean: rm -f $(Object) $(Depend) Object=hello 和 Depend=hello.o 表 示 变 量 赋 值 $(Object):$(Depend) 表 示 的 是 目 标 文 件 和 依 赖 文 件 的 关 系 $(CC) $(CFLAGS) -o $@ $< 表 示 的 是 上 面 依 赖 关 系 文 件 的 执 行 操 作 最 后 两 行, 是 当 执 行 make clean 操 作 的 时 候, 清 除 目 标 文 件 和 依 赖 文 件 实 验 步 骤 1) 在 Ubuntu 中 单 击 菜 单 应 用 程 序 -> 附 件 -> 终 端 打 开 终 端 2) 进 入 到 10.6 章 节 工 作 目 录, 编 译 hello.c 程 序 : $ make cc -c -o hello.o hello.c cc -o hello hello.o 3) 运 行 hello $./hello Hello! This is our embedded world!

153 第 十 一 章 Android&Linux 系 统 移 植 本 章 主 要 讲 解 嵌 入 式 Linux 操 作 系 统 的 移 植 及 Android 操 作 系 统 的 移 植 学 习 了 本 章 后, 读 者 能 够 掌 握 如 下 内 容 : 掌 握 Linux&Android 系 统 裁 剪 移 植 及 编 译,Linux 系 统 调 试 方 法 等 11.1 构 建 交 叉 编 译 环 境 实 验 目 的 设 置 工 作 环 境 ; 掌 握 交 叉 编 译 环 境 设 置 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 交 叉 编 译 是 嵌 入 式 开 发 过 程 中 的 一 项 重 要 技 术, 简 单 地 说, 就 是 在 一 个 平 台 上 生 成 另 一 个 平 台 上 的 可 执 行 代 码 交 叉 编 译 这 个 概 念 的 出 现 和 流 行 是 和 嵌 入 式 系 统 的 广 泛 发 展 同 步 的 我 们 常 用 的 计 算 机 软 件, 都 需 要 通 过 编 译 的 方 式, 把 使 用 高 级 计 算 机 语 言 编 写 的 代 码 ( 比 如 C 代 码 ) 编 译 (compile) 成 计 算 机 可 以 识 别 和 执 行 的 二 进 制 代 码 交 叉 编 译 的 主 要 特 征 是 某 机 器 中 执 行 的 程 序 代 码 不 是 由 本 机 编 译 生 成, 而 是 由 另 一 台 机 器 编 译 生 成, 一 般 把 前 者 称 为 目 标 机, 后 者 称 为 主 机 这 是 因 为 目 标 平 台 上 不 允 许 或 不 能 够 安 装 开 发 所 需 要 的 编 译 器, 而 又 需 要 该 编 译 器 的 某 些 特 征 ; 有 时 是 因 为 目 标 平 台 上 的 资 源 贫 乏, 无 法 运 行 开 发 所 需 要 的 编 译 器 ; 有 时 是 因 为 目 标 平 台 还 没 有 建 立, 连 操 作 系 统 都 没 有, 根 本 谈 不 上 运 行 编 译 器 本 实 验 环 境 Linux 内 核 编 译 采 用 arm-eabi 编 译 器, 并 统 一 了 工 作 环 境

154 实 验 步 骤 ZD-s210xA80 实 验 平 台 对 应 的 系 统 代 码 及 编 译 工 具 位 置 在 :DISK-S210xA80\03- 系 统 代 码, 用 户 在 使 用 前 需 要 将 光 盘 内 文 件 (android-2.3.tar.gz arm-2009q3.tar.bz2) 拷 贝 到 ubuntu 系 统 的 /tmp 目 录 下 : 1) 在 ubuntu 嵌 入 式 开 发 环 境 下 运 行 终 端, 执 行 以 下 命 令 部 署 Android 系 统 源 码 : $ sudo mkdir -p /usr/local/src/s210x $ sudo chmod -R 777 /usr/local/src/s210x $ cd /usr/local/src/s210x $ tar xvf /tmp/android-2.3.tar.gz $ tar xvf /tmp/arm-2009q3.tar.bz2 $ ls arm-2009q3 x210_android-2.3 # 源 码 都 部 署 成 功 默 认 实 验 环 境 设 置 如 下 : 工 作 目 录 : /usr/local/src/s210x 交 叉 编 译 工 具 链 路 径 : /usr/local/src/s210x/arm-2009q3 源 码 路 径 : /usr/local/src/s210x/x210_android-2.3 U-boot 源 码 路 径 : /usr/local/src/s210x/x210_android-2.3/uboot Linux 内 核 源 码 路 径 : /usr/local/src/s210x/x210_android-2.3/kernel 2) 交 叉 编 译 环 境 验 证 : 在 Ubuntu 中 单 击 菜 单 应 用 程 序 -> 附 件 -> 终 端 打 开 终 端, 输 入 以 下 命 令 查 看 交 叉 编 译 器 : $ export PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ arm-none-linux-gnueabi-gcc -v Using built-in specs. Target: arm-none-linux-gnueabi Configured with: /scratch/julian/2009q3-respin-linux-lite/src/gcc-4.4/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --enable-extra-sgxxlite-multilibs --with-arch=armv5te --with-gnu-as --with-gnu-ld --with-specs='%{funwind-tables fno-unwind-tables mabi=* ffreestanding nostdlib:;:-funwind-tables} %{O2:%{!fno-re move-local-statics: -fremove-local-statics}} %{O*:%{O O0 O1 O2 Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}' --enable-languages=c,c++ --enable-shared --disable-lto --enable-symvers=gnu --enable- cxa_atexit --with-pkgversion='sourcery G++ Lite 2009q3-67'

155 --with-bugurl= --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/libc --with-gmp=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linuxgnu/usr --with-mpfr=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linuxgnu/usr --with-ppl=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-g nu/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-cloog=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux -gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/bin Thread model: posix gcc version (Sourcery G++ Lite 2009q3-67) 如 果 打 印 消 息 为 arm-none-linux-gnueabi-gcc 找 不 到, 则 表 示 交 叉 编 译 工 具 链 没 有 设 置 成 功 11.2 编 译 脚 本 分 析 实 验 目 的 掌 握 实 验 平 台 提 供 的 编 译 脚 本 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 ZD-s210xA80 实 验 平 台 系 统 代 码 通 过 一 个 shell 脚 本 进 行 编 译 管 理, 文 件 如 下 : #!/bin/sh # # Description : Build Android Script. # Authors :

156 # Version : 0.01 # Notes : None # # 设 置 环 境 变 量 export ANDROID_JAVA_HOME=/usr/lib/jvm/java-6-sun/ SOURCE_DIR=$(cd `dirname $0` ; pwd) # JAVA JDK 路 径 # 设 置 当 前 目 录 为 源 码 路 径 RELEASE_DIR=${SOURCE_DIR}/out/release # 最 终 镜 像 文 件 释 放 目 录 TARGET_DIR=${SOURCE_DIR}/out/target/product/smdkv210/ # Android 镜 像 的 编 译 目 标 目 录 KERNEL_DIR=${SOURCE_DIR}/kernel/ # Linux 源 码 目 录 UBOOT_CONFIG=x210_sd_config # uboot 配 置 文 件 KERNEL_CONFIG=x210_android_inand_defconfig # Linux 内 核 配 置 文 件 FILESYSTEM_CONFIG=PRODUCT-full_smdkv210-eng # 指 定 Android 编 译 目 标 # 提 取 CPU 内 核 数 CPU_NUM=$(cat /proc/cpuinfo grep processor wc -l) CPU_NUM=$((CPU_NUM+1)) # 设 置 环 境 变 量 函 数, 在 Android 源 码 目 录 创 建 镜 像 释 放 目 录 和 映 像 的 目 标 目 录 setup_environment() { cd ${SOURCE_DIR}; mkdir -p ${RELEASE_DIR} return 1; mkdir -p ${TARGET_DIR} return 1; } # 清 除 整 个 源 码 包 编 译 结 果 build_clean() { # 清 除 Android 编 译 结 果 cd ${SOURCE_DIR}; make clean return 1; # 清 除 uboot 编 译 结 果 cd ${SOURCE_DIR}/uboot return 1 make distclean return 1; # 清 除 Linux 编 译 结 果

157 cd ${SOURCE_DIR}/kernel return 1 make distclean return 1 return 0 } # 编 译 uboot 源 码 build_uboot() { cd ${SOURCE_DIR}/uboot return 1 make distclean return 1; make ${UBOOT_CONFIG} return 1; make -j${cpu_num} # 使 用 默 认 的 配 置 文 件 ${UBOOT_CONFIG} 编 译 if [ -f u-boot.bin ]; then else fi cp u-boot.bin ${RELEASE_DIR}/u-boot.bin echo "^_^ u-boot.bin is finished successful!" echo "make error,cann't compile u-boot.bin!" exit # 将 编 译 的 u-boot.bin 拷 贝 到 ${RELEASE_DIR} return 0 } # 编 译 Linux 内 核 源 码 build_kernel() { cd ${SOURCE_DIR}/kernel return 1 make ${KERNEL_CONFIG} return 1 # 使 用 默 认 的 配 置 文 件 ${KERNEL_CONFIG} 编 译 make -j${threads} return 1 dd if=${source_dir}/kernel/arch/arm/boot/zimage of=${release_dir}/zimage bs=2048 count=8192 conv=sync; # 将 编 译 生 成 的 zimage 文 件 拷 贝 到 ${RELEASE_DIR} 目 录 echo "" >&2 echo "^_^ android kernel for inand path: ${RELEASE_DIR}/zImage" >&2 } return

158 # 编 译 Android 源 码, 生 成 文 件 系 统 镜 像 build_rootfs() { cd ${SOURCE_DIR} return 1 rm ${TARGET_DIR}/ramdisk.img > /dev/null rm ${TARGET_DIR}/uramdisk.img > /dev/null rm ${TARGET_DIR}/system.img >/dev/null rm ${TARGET_DIR}/obj/PACKAGING/systemimage_intermediates/system.img > /dev/null rm ${TARGET_DIR}/root -fr > /dev/null rm ${TARGET_DIR}/system -fr > /dev/null make -j${threads} ${FILESYSTEM_CONFIG} return 1 cp ${TARGET_DIR}/system.img ${RELEASE_DIR}/system.img #echo "" >&2 #echo "^_^ system path: ${RELEASE_DIR}/system.tar" >&2 ${SOURCE_DIR}/uboot/tools/mkimage -A arm -O linux -T ramdisk -C none -a 0x n "uramdisk" -d ${TARGET_DIR}/ramdisk.img ${TARGET_DIR}/uramdisk.img rm ${TARGET_DIR}/ramdisk.img > /dev/null mv ${TARGET_DIR}/uramdisk.img ${RELEASE_DIR}/ramdisk.img return 0 } # 设 置 默 认 编 译 选 项 threads=4; uboot=no; kernel=no; rootfs=no; clean=no; # 直 接 执 行 mk 脚 本 编 译, 将 默 认 编 译 uboot,kernel,android if [ -z $1 ]; then uboot=yes kernel=yes rootfs=yes fi while [ "$1" ]; do

159 case "$1" in -j=*) # 编 译 选 项 后 加 -j=* 参 数 (* 为 数 字 ), 将 设 置 编 译 线 程 数 x=$1 threads=${x#-j=} ;; -c --clean) # 编 译 选 项 后 加 -c 参 数, 将 清 除 整 个 源 码 包 编 译 结 果 clean=yes ;; -u --uboot) # 编 译 选 项 后 加 -u 参 数, 将 编 译 uboot 源 码 uboot=yes ;; -k --kernel) # 编 译 选 项 后 加 -k 参 数, 将 编 译 Linux 内 核 源 码 kernel=yes ;; -r --rootfs) # 编 译 选 项 后 加 -r 参 数, 将 编 译 Android 源 码, 生 成 文 件 系 统 镜 像 rootfs=yes ;; -a --all) # 编 译 选 项 后 加 -a 参 数, 将 编 译 所 有 源 码 :uboot,kernel,android uboot=yes kernel=yes rootfs=yes ;; -h --help) # 编 译 选 项 后 加 -h 参 数, 将 显 示 帮 助 信 息 cat >&2 <<EOF Usage: build.sh [OPTION] Build script for compile the source of telechips project. -j=n using n threads when building source project (example: -j=16) -c, --clean clean all building file -u, --uboot build uboot from source file -k, --kernel build kernel and using default config file -r, --rootfs build Root filesystem from source file -a, --all build all, include anything -h, --help display this help and exit EOF exit 0 ;; *) echo "mk: Unrecognised option $1" >&

160 exit 1 ;; esac shift done setup_environment exit 1 if [ "${uboot}" = yes ]; then fi build_uboot exit 1 if [ "${kernel}" = yes ]; then fi build_kernel exit 1 if [ "${rootfs}" = yes ]; then fi build_rootfs exit 1 if [ "${clean}" = yes ]; then fi build_clean exit 1 exit 实 验 步 骤 阅 读 理 解 编 译 脚 本 文 件, 执 行 下 面 的 步 骤 可 以 编 译 整 个 Linux&Andrid 系 统 : 1) 在 Ubuntu 中 单 击 菜 单 应 用 程 序 -> 附 件 -> 终 端 打 开 终 端 2) 在 终 端 中 输 入 以 下 命 令 开 始 编 译 系 统 : $ export PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ cd /usr/local/src/s210x/x210_android-2.3 $./mk -c # 清 除 源 代 码 编 译 结 果 $./mk -a # 编 译 所 有 源 码 :uboot,kernel,android 编 译 成 功 后, 将 会 在 /usr/local/src/s210x/s210x_android-2.3/out/release 目 录 下 看 到 编 译 生 成 的 镜 像 文 件 u-boot.bin zimage ramdisk.img system.img, 按 照 产 品 手 册 7.2 章 节 内 容 可 以 将

161 编 译 好 的 镜 像 文 件 固 化 到 实 验 平 台 中 11.3 uboot 启 动 代 码 解 析 实 验 目 的 学 习 和 掌 握 u-boot 编 译 的 基 本 步 骤 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 简 单 地 说, 本 实 验 中 u-boot 是 引 导 程 序 Bootloader, 它 是 在 操 作 系 统 内 核 运 行 之 前 运 行 的 一 段 小 程 序 通 过 这 段 小 程 序, 我 们 可 以 初 始 化 硬 件 设 备 建 立 内 存 空 间 的 映 射 图, 从 而 将 系 统 的 软 硬 件 环 境 带 到 一 个 合 适 的 状 态, 以 便 为 最 终 调 用 操 作 系 统 内 核 准 备 好 正 确 的 环 境 Bootloader( 引 导 加 载 程 序 ) 是 系 统 加 电 后 运 行 的 第 一 段 代 码, 一 般 运 行 的 时 间 非 常 短, 但 是 对 于 嵌 入 式 系 统 来 说, 这 段 代 码 非 常 重 要 在 我 们 的 台 式 电 脑 当 中, 引 导 加 载 程 序 由 BIOS( 固 件 程 序 ) 和 位 于 硬 盘 MBR 中 的 操 作 系 统 引 导 加 载 程 序 ( 比 如 NTLOADER,GRUB 和 LILO) 一 起 组 成 在 嵌 入 式 系 统 当 中 没 有 像 BIOS 这 样 的 固 件 程 序, 不 过 也 有 一 些 嵌 入 式 CPU 会 在 芯 片 内 部 嵌 入 一 小 段 程 序, 一 般 用 来 将 bootloader 装 进 RAM 中, 有 点 类 似 BIOS, 但 是 功 能 比 BIOS 弱 很 多 在 一 般 的 典 型 系 统 中, 整 个 系 统 的 加 载 启 动 任 务 全 由 bootloader 来 完 成 在 ARM 中, 系 统 上 电 或 复 位 时 通 常 从 地 址 0x 处 开 始 执 行, 而 在 这 个 位 置, 通 常 安 排 的 就 是 系 统 的 bootloader 通 过 这 小 段 程 序 可 以 初 始 化 硬 件 设 备 建 立 内 存 空 间 映 射 图, 从 而 将 系 统 的 软 硬 件 环 境 设 置 到 一 个 合 适 的 状 态! 以 为 最 终 调 用 操 作 系 统 内 核 准 备 好 正 确 的 环 境 U-Boot(UniversalBootloader ) 是 遵 循 GPL 条 款 的 开 放 源 码 项 目 它 是 从 FADSROM 8xxROM PPCBOOT 逐 步 发 展 演 化 而 来 其 源 码 目 录 编 译 形 式 与 Linux 内 核 很 相 似, 事 实 上, 不 少 U-Boot 源 码 就 是 相 应 的 Linux 内 核 源 程 序 的 简 化, 尤 其 是 一 些 设 备 的 驱 动 程 序, 这 从 U-Boot 源 码 的 注 释 中 能 体 现 这 一 点 但 是 U-Boot 不 仅 仅 支 持 嵌 入 式 Linux 系 统 的 引 导, 而 且 还 支 持 NetBSD VxWorks QNX RTEMS ARTOS LynxOS 等 嵌 入 式 操 作 系 统 其 目 前 要 支 持 的 目 标

162 操 作 系 统 是 OpenBSD NetBSD FreeBSD 4.4BSD Linux SVR4 Esix Solaris Irix SCO Dell NCR VxWorks LynxOS psos QNX RTEMS ARTOS 这 是 U-Boot 中 Universal 的 一 层 含 义, 另 外 一 层 含 义 则 是 U-Boot 除 了 支 持 PowerPC 系 列 的 处 理 器 外, 还 能 支 持 MIPS x86 ARM NIOS XScale 等 诸 多 常 用 系 列 的 处 理 器 这 两 个 特 点 正 是 U-Boot 项 目 的 开 发 目 标, 即 支 持 尽 可 能 多 的 嵌 入 式 处 理 器 和 嵌 入 式 操 作 系 统 就 目 前 为 止,U-Boot 对 PowerPC 系 列 处 理 器 支 持 最 为 丰 富, 对 Linux 的 支 持 最 完 善 实 验 步 骤 单 独 编 译 u-boot uboot 的 默 认 配 置 文 件 为 :s210x_android-2.3/uboot/include/configs/x210_sd.h, 如 果 要 修 改 配 置 选 项, 可 以 直 接 修 改 该 文 件, 然 后 在 终 端 执 行 下 面 命 令 来 编 译 uboot 源 码 : $ export PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ cd /usr/local/src/s210x/x210_android-2.3 $./mk -u # 编 译 uboot 编 译 成 功 后, 将 会 在 /usr/local/src/s210x/s210x_android-2.3/out/release 目 录 下 看 到 编 译 生 成 的 镜 像 文 件 u-boot.bin, 按 照 产 品 手 册 7.2 章 节 内 容 可 以 将 编 译 好 的 uboot 镜 像 文 件 固 化 到 实 验 平 台 中 u-boot 的 命 令 使 用 正 确 连 接 交 叉 串 口 线 (COM0), 在 终 端 输 入 minicom, 运 行 串 口 终 端, 长 按 主 板 Power 按 键 给 实 验 平 台 上 电, 在 串 口 终 端 可 以 看 到 uboot 的 启 动 信 息, 按 下 电 脑 的 空 格 键 进 入 到 uboot 的 命 令 行 模 式, 以 下 是 u-boot 的 一 些 常 用 命 令 : x210 # fdisk -c 0 # 重 建 分 区 表 x210 # fatformat mmc 0:1 # 格 式 化 MMC0 的 分 区 1 为 Fat 格 式 x210 # resetenv # 恢 复 uboot 出 厂 环 境 变 量 x210 # setenv bootargs 'console=ttysac0, lcd=8inch' # 设 置 启 动 参 数, 根 据 不 同 需 求 设 置 x210 # setenv bootcmd 'movi read kernel ; bootm ' # 设 置 启 动 命 令 x210 # saveenv # 保 存 设 置 的 环 境 变 量 x210 # reset # 复 位

163 11.4 Linux 系 统 内 核 解 析 实 验 目 的 通 过 实 验 掌 握 Linux 配 置 编 译 过 程 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 内 核 是 Linux 操 作 系 统 的 核 心, 它 管 理 所 有 的 系 统 线 程 进 程 资 源 和 资 源 分 配 与 其 它 操 作 系 统 不 同 的 是,Linux 操 作 系 统 允 许 用 户 对 内 核 进 行 重 新 设 置 用 户 可 以 对 内 核 进 行 瘦 身, 增 加 或 消 除 对 某 些 特 定 设 备 或 子 系 统 的 支 持 在 开 发 嵌 入 式 系 统 时, 开 发 人 员 经 常 会 减 少 系 统 对 一 些 无 用 设 备 的 支 持, 将 节 省 下 来 的 内 存 分 配 给 各 种 应 用 软 件 Linux 内 核 对 各 种 硬 件 和 端 口 的 支 持 要 靠 各 种 硬 件 驱 动 程 序 来 实 现 这 些 驱 动 程 序 可 以 被 直 接 写 入 内 核, 也 可 以 针 对 某 些 特 定 硬 件 在 需 要 时 自 动 加 载 通 常 情 况 下, 可 以 被 自 动 加 载 进 内 核 的 内 核 编 码 称 为 自 动 加 载 内 核 模 块 Linux 内 核 的 设 置 是 通 过 内 核 设 置 编 辑 器 完 成 的 内 核 设 置 编 辑 器 可 对 每 个 内 核 设 置 变 量 进 行 描 述, 帮 助 用 户 决 定 哪 些 变 量 需 要 被 清 除, 哪 些 需 要 写 入 内 核, 或 者 编 成 一 个 可 加 载 内 核 模 块 在 需 要 时 进 行 加 载 内 核 是 为 众 多 应 用 程 序 提 供 对 计 算 机 硬 件 的 安 全 访 问 的 一 部 分 软 件, 这 种 访 问 是 有 限 的, 并 且 内 核 决 定 一 个 程 序 在 什 么 时 候 对 某 部 分 硬 件 操 作 多 长 时 间 直 接 对 硬 件 操 作 是 非 常 复 杂 的, 所 以 内 核 通 常 提 供 一 种 硬 件 抽 象 的 方 法 来 完 成 这 些 操 作 硬 件 抽 象 隐 藏 了 复 杂 性, 为 应 用 软 件 和 硬 件 提 供 了 一 套 简 洁, 统 一 的 接 口, 使 程 序 设 计 更 为 简 单 用 户 可 以 根 据 自 己 的 需 要 编 译 内 核 实 验 步 骤 Linux 内 核 的 默 认 配 置 文 件 为 :s210x_android-2.3/kernel/arch/arm/configs/x210_android_

164 inand_defconfig, 如 果 要 修 改 配 置 选 项, 可 以 直 接 修 改 该 文 件, 然 后 在 终 端 执 行 下 面 命 令 来 编 译 Linux 内 核 源 码 : $ export PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ cd /usr/local/src/s210x/x210_android-2.3 $./mk -k # 编 译 Linux 内 核 也 可 以 进 入 到 图 形 配 置 界 面 对 内 核 进 行 配 置, 然 后 编 译 Linux 内 核 源 码 : $ export PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ cd /usr/local/src/s210x/x210_android-2.3/kernel $ cp arch/arm/configs/x210_android_inand_defconfig.config $ make menuconfig # 此 时 可 以 在 该 图 形 窗 口 进 行 选 项 的 配 置, 保 存 后 退 出 $ make zimage # 编 译 Linux 内 核 编 译 成 功 后, 将 会 在 /usr/local/src/s210x/kernel/arch/arm/boot/ 目 录 下 看 到 编 译 生 成 的 镜 像 文 件 zimage, 按 照 产 品 手 册 7.2 章 节 内 容 可 以 将 编 译 好 的 内 核 zimage 镜 像 文 件 固 化 到 实 验 平 台 中 11.5 Android 系 统 解 析 实 验 目 的 学 习 和 掌 握 Android 编 译 的 基 本 步 骤 ; 通 过 实 验 掌 握 Android 编 译 过 程 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Android 操 作 系 统 实 际 上 是 Linux 操 作 系 统 之 上 的 一 个 图 形 框 架, 它 提 供 完 整 的 开 发 机 制, 通 过 编 译 Android 源 码 可 以 生 成 文 件 系 统 镜 像

165 实 验 步 骤 单 独 编 译 Android 源 码 : 在 终 端 执 行 下 面 命 令 来 编 译 Android 源 码 并 生 成 镜 像 文 件 : $ cd /usr/local/src/s210x/x210_android-2.3 $./mk -r # 编 译 android 源 码 生 成 文 件 系 统 镜 像 编 译 成 功 后, 将 会 在 /usr/local/src/s210x/s210x_android-2.3/out/release 目 录 下 看 到 编 译 生 成 的 镜 像 文 件 ramdisk.img system.img, 按 照 产 品 手 册 7.2 章 节 内 容 可 以 将 编 译 好 的 镜 像 文 件 固 化 到 实 验 平 台 中 单 独 编 译 Android 源 码 某 个 项 目 工 程 : 重 新 编 译 一 次 Android 非 常 费 时, 对 于 只 修 改 某 个 工 程 项 目, 我 们 可 以 单 独 编 译 该 工 程, 使 用 下 面 的 参 考 命 令 : $ cd /usr/local/src/s210x/x210_android-2.3 $ source./build/envsetup.sh # 编 译 android 源 码 生 成 文 件 系 统 镜 像 $ lunch full_smdkv210-eng # 设 置 编 译 参 数 $ mmm hardware/ril/reference-ril # 单 独 编 译 reference-ril 工 程 编 译 成 功 后 镜 像 文 件 system.img 也 会 得 到 更 新, 在 /usr/local/src/s210x/ s210x_android-2.3/out/release 目 录 下 可 以 看 到, 按 照 产 品 手 册 7.2 章 节 内 容 可 以 将 编 译 好 的 内 核 zimage 镜 像 文 件 固 化 到 实 验 平 台 中 11.6 构 建 基 本 文 件 系 统 实 验 目 的 熟 悉 busybox 相 关 知 识 及 应 用 ; 学 会 使 用 交 叉 编 译 器 定 制 一 个 busybox; 利 用 该 busybox 制 作 一 个 文 件 系 统 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统

166 实 验 原 理 busybox 是 一 个 集 成 了 一 百 多 个 最 常 用 linux 命 令 和 工 具 的 软 件, 他 甚 至 还 集 成 了 一 个 http 服 务 器 和 一 个 telnet 服 务 器, 而 所 有 这 一 切 功 能 却 只 有 区 区 1M 左 右 的 大 小 我 们 平 时 用 的 那 些 linux 命 令 就 好 比 是 分 立 式 的 电 子 元 件, 而 busybox 就 好 比 是 一 个 集 成 电 路, 把 常 用 的 工 具 和 命 令 集 成 压 缩 在 一 个 可 执 行 文 件 里, 功 能 基 本 不 变, 而 大 小 却 小 很 多 倍, 在 嵌 入 式 linux 应 用 中,busybox 有 非 常 广 的 应 用 另 外, 大 多 数 linux 发 行 版 的 安 装 程 序 中 都 有 busybox 的 身 影, 安 装 linux 的 时 候 按 ctrl+alt+f2 就 能 得 到 一 个 控 制 台, 而 这 个 控 制 台 中 的 所 有 命 令 都 是 指 向 busybox 的 链 接 busybox 的 小 身 材 大 作 用 的 特 性, 给 制 作 一 张 软 盘 的 linux 带 来 了 及 大 方 便 busybox 是 标 准 Linux 工 具 的 一 个 单 个 可 执 行 实 现 busybox 包 含 了 一 些 简 单 的 工 具, 例 如 cat 和 echo, 还 包 含 了 一 些 更 大 更 复 杂 的 工 具, 例 如 grep find mount 以 及 telnet 有 些 人 将 busybox 称 为 Linux 工 具 里 的 瑞 士 军 刀 简 单 的 说 busybox 就 好 像 是 个 大 工 具 箱, 它 集 成 压 缩 了 Linux 的 许 多 工 具 和 命 令, 用 户 可 以 根 据 自 己 的 需 要 定 制 一 个 busybox Linux 根 文 件 系 统 包 含 了 除 内 核 以 外 的 所 有 linux 系 统 在 引 导 和 管 理 时 需 要 的 工 具, 做 为 启 动 引 导 驱 动, 包 含 如 下 目 录 :bin,dev,etc,home,lib,mnt,proc,sbin,usr,var 还 需 要 有 一 些 基 本 的 工 具 :sh,ls,cp,mv ( 位 于 /bin 目 录 中 ); 必 要 的 配 置 文 件 :inittab,rc,fstab 位 于 (/etc 目 录 种 ); 必 要 的 设 备 文 件 :/dev/tty*,/dev /console,/dev/men ( 位 于 /dev 目 录 中 ); sh,ls 等 工 具 必 要 的 运 行 库 :glibc 实 验 步 骤 编 译 busybox: 在 终 端 执 行 下 面 命 令 来 编 译 busybox: 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 11 章 /11.6-busybox 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 执 行 下 面 的 步 骤 来 进 行 编 译 : $ cd /usr/local/src/s210x/project/11.6-busybox $ tar xvf busybox tar.bz2 $ cd busybox $ patch -p1 <../ patch $ make menuconfig

167 // choose s210x config file. $ make $ make CONFIG_PREFIX=../root-mini install 编 译 成 功 将 生 成 一 个 root-mini 文 件 夹, 这 样 基 于 busybox 所 建 立 的 最 小 文 件 系 统 目 录 树 就 做 好 了 制 作 最 小 根 文 件 系 统 镜 像 : 在 终 端 执 行 下 面 命 令 来 编 译 busybox: $ cd /usr/local/src/s210x/project/11.6-busybox $ cd root-mini $ mkdir -p dev etc/init.d home/app mnt opt proc sys tmp var usr/lib media/sd0 media/sd1 media/usb0 media/usb1 lib/modules/ $ cp -a /usr/local/src/s210x/arm-2009q3/arm-none-linux-gnueabi/libc/lib/*./lib/ $ cp -a /usr/local/src/s210x/arm-2009q3/arm-none-linux-gnueabi/libc/usr/lib/*.so*./usr/lib/ $ cp -a../etc/*./etc/ $ cp../rz./bin/ $ cd.. $ chmod -R 777 root-mini $./make_ext4fs -l 256M -s rootfs.img root-mini 编 译 成 功 将 生 成 一 个 rootfs.img 根 文 件 系 统 镜 像 文 件 固 化 最 小 根 文 件 系 统 镜 像 : 参 考 产 品 手 册 7.2 章 节 固 化 新 镜 像 文 件 ( 将 文 件 rootfs.img 拷 贝 到 DISK-S210xA80\02- 出 厂 镜 像 \images 文 件 夹 内 ), 涉 及 到 的 修 改 如 下 : 1) 在 产 品 手 册 7.2 章 节 第 5 步 修 改 如 下 : x210 # resetenv set default env ok! x210 # setenv bootargs 'console=ttysac0, lcd=8inch root=/dev/mmcblk0p2 rootfstype=ext4 init=/linuxrc' # 8 寸 屏 执 行 此 步 操 作, 如 果 用 数 字 摄 像 头, 则 增 加 camera=ov2655 x210 # setenv bootcmd 'movi read kernel ; bootm ' x210 # saveenv # 保 存 设 置 后 的 环 境 变 量 Saving Environment to SMDK bootable device... done 2) 在 产 品 手 册 7.2 章 节 第 7 步 修 改 Flash.bat 文 件 如 下 :.\fastboot\fastboot.exe flash bootloader.\images\u-boot.bin.\fastboot\fastboot.exe flash kernel.\images\zimage.\fastboot\fastboot.exe flash system.\images\rootfs.img.\fastboot\fastboot.exe -w

168 然 后 双 击 运 行 Flash.bat 开 始 更 新 系 统 镜 像 (u-boot.bin zimage rootfs.img) 3) 固 化 成 功 后, 重 启 实 验 平 台, 在 串 口 超 级 终 端 可 以 看 到 Linux 的 启 动 打 印 消 息 11.7 NFS 网 络 文 件 系 统 实 验 目 的 掌 握 Linux 系 统 之 间 资 源 共 享 和 互 访 方 法 ; 掌 握 NFS 服 务 器 和 客 户 端 的 安 装 与 配 置 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+),s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 NFS(Network File System) 是 由 SUN 公 司 发 展, 并 于 1984 年 推 出,NFS 是 一 个 RPC service, 它 使 我 们 能 够 达 到 档 案 的 共 享, 它 的 设 计 是 为 了 在 不 同 的 系 统 间 使 用, 所 以 它 的 通 讯 协 议 设 计 与 主 机 及 作 业 系 统 无 关 当 使 用 者 想 用 远 端 档 案 时 只 要 用 mount 就 可 把 remote 档 案 系 统 挂 接 在 自 己 的 档 案 系 统 之 下, 使 得 远 端 的 档 案 使 用 和 local 机 器 的 档 案 没 两 样 NFS 至 少 包 括 两 个 主 要 的 部 分 : 一 台 服 务 器, 以 及 至 少 一 台 客 户 机, 客 户 机 远 程 地 访 问 保 存 在 服 务 器 上 的 数 据 要 让 这 一 切 运 转 起 来, 需 要 配 置 并 运 行 几 个 程 序 服 务 器 必 须 运 行 以 下 服 务 : 表 服 务 器 运 行 的 服 务 服 务 描 述 Nfsd NFS, 为 来 自 NFS 客 户 端 的 请 求 服 务 Mountd NFS 挂 载 服 务, 处 理 nfsd(8) 递 交 过 来 的 请 求 rpcbind 此 服 务 允 许 NFS 客 户 程 序 查 询 正 在 被 NFS 服 务 使 用 的 端 口 客 户 端 同 样 运 行 一 些 进 程, 比 如 nfsiod,nfsiod 处 理 来 自 NFS 的 请 求 这 是 可 选 的, 而 且 可 以 提 高 性 能, 对 于 普 通 和 正 确 的 操 作 来 说 并 不 是 必 须 的

169 实 验 步 骤 ZEmberOS 默 认 已 经 安 装 了 NFS Server, 其 设 置 的 根 目 录 为 /opt/nfs, 做 本 实 验 前 要 求 必 须 完 成 11.6 章 节 实 验 生 成 基 本 的 文 件 系 统 root-mini, 下 面 是 操 作 步 骤 : 设 置 网 卡 参 考 产 品 手 册 附 录 2, 对 ZemberOS 操 作 系 统 的 网 卡 设 置 为 准 备 文 件 系 统 1) 设 置 工 作 环 境 : $ mkdir -p /usr/local/src/s210x/project 2) 在 终 端 输 入 以 下 命 令 将 11.6 章 节 完 成 的 文 件 系 统 复 制 到 nfs 文 件 夹 : $ cd /usr/local/src/s210x/project/11.6-busybox $ cp -a./root-mini /opt/nfs/ 3) 修 改 文 件 系 统 中 对 网 卡 的 配 置 : 修 改 root-mini/etc/init.d/rcs 文 件, 将 以 下 行 注 释 : # ifconfig lo netmask # ifconfig eth netmask 修 改 启 动 参 数 正 确 连 接 交 叉 串 口 线 (COM0), 在 终 端 输 入 minicom, 运 行 串 口 终 端, 长 按 主 板 Power 按 键 给 实 验 平 台 上 电, 在 串 口 终 端 可 以 看 到 uboot 的 启 动 信 息, 按 下 电 脑 的 空 格 键 进 入 到 uboot 的 命 令 行 模 式, 输 入 以 下 命 令 修 改 启 动 参 数 : x210 # resetenv set default env ok! x210 # setenv bootargs 'console=ttysac0, lcd=8inch camera=ov2655 root=/dev/nfsroot nfsroot= :/opt/nfs/root-mini ip= : : : :x210:eth0:off init=/linuxrc' # 红 色 部 分 根 据 需 求 修 改 x210 # setenv bootcmd 'movi read kernel ; bootm ' x210 # saveenv # 保 存 设 置 后 的 环 境 变 量 Saving Environment to SMDK bootable device... done 设 置 完 成 后, 确 保 实 验 平 台 连 接 好 了 网 线 到 局 域 网 内 ( 或 者 跟 电 脑 主 机 直 接 连 接 ), 重 启 实 验 平 台, 即 可 引 导 NFS 文 件 系 统, 部 分 打 印 消 息 如 下 : [ ] eth0: link down [ ] ADDRCONF(NETDEV_UP): eth0: link is not ready [ ] IP-Config: Complete: [ ] device=eth0, addr= , mask= , gw= ,

170 [ ] host=x210, domain=, nis-domain=(none), [ ] bootserver= , rootserver= , rootpath= [ ] DBUG_PORT must not use AFC! [ ] Looking up port of RPC /2 on [ ] eth0: link up, 100Mbps, full-duplex, lpa 0x4DE1 [ ] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready [ ] eth0: IPv6 duplicate address fe80::209:c0ff:feff:ec48 detected! [ ] Looking up port of RPC /1 on [ ] VFS: Mounted root (nfs filesystem) on device 0:

171 第 十 二 章 linux 应 用 程 序 开 发 本 章 节 主 要 介 绍 嵌 入 式 Linux 应 用 程 序 的 编 写, 内 容 涵 盖 HelloWorld 入 门 操 作, 文 件 操 作, 进 程 和 线 程 控 制, 计 时 器 实 验,tcp udp 和 webserver 实 验 等, 通 过 本 章 节 的 学 习, 可 以 了 解 Linux 下 基 础 应 用 程 序 的 开 发 方 法 12.1 Helloworld 入 门 实 验 目 的 掌 握 嵌 入 式 应 用 程 序 的 编 写, 编 译 和 运 行 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Helloworld 程 序 通 过 简 单 的 printf 函 数 显 示 helloworld 打 印 信 息 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 12 章 /12.1-helloworld 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ;

172 3) 编 译 并 拷 贝 helloworld 程 序 : $ cd /usr/local/src/s210x/project/12.1-helloworld $ arm-none-linux-gnueabi-gcc -o helloworld helloworld.c $ cp helloworld /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 helloworld 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./helloworld -l./helloworld 5) 给 helloworld 添 加 可 执 行 权 限 : # chmod 777 helloworld 6) 运 行 helloworld: #./helloworld HelloWorld! HelloWorld! HelloWorld! HelloWorld! HelloWorld! 12.2 文 件 操 作 实 验 实 验 目 的 通 过 编 写 文 件 读 写 及 上 锁 的 程 序, 熟 悉 Linux 中 文 件 I/O 相 关 的 应 用 开 发 ; 熟 练 掌 握 open(),read(),write(),fcntl() 等 函 数 的 使 用

173 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 标 准 I/O 库 以 及 其 他 的 头 文 件, 提 供 了 一 个 到 底 层 I/O 系 统 调 用 的 一 个 万 能 接 口, 这 个 库 并 不 是 ANSI 标 准 C 的 一 部 分, 但 是 这 个 库 却 提 供 了 许 多 复 杂 的 函 数 用 来 处 理 格 式 化 输 出 以 及 描 述 输 入, 同 时 也 会 小 心 的 处 理 设 备 所 要 求 的 缓 冲 区 在 许 多 方 式 上, 可 以 用 使 用 低 层 文 件 描 述 符 的 方 式 来 使 用 这 个 库 当 需 要 打 开 文 件 建 立 访 问 路 径 时, 会 返 回 一 个 值, 并 会 作 为 一 个 调 用 其 他 I/O 库 函 数 的 参 数 这 个 与 低 层 文 件 描 述 符 等 同 的 被 称 之 类 流 (stream), 并 且 是 作 为 一 个 指 向 结 构 的 指 针 FILE* 来 实 现 的 当 一 个 程 序 启 动 时 会 自 动 打 开 三 个 文 件 流 他 们 是 stdin,stdout,stderr 这 些 是 在 stdio.h 中 定 义, 分 别 代 表 标 准 输 入 标 准 输 出 和 标 准 错 误 输 出 相 对 的, 他 们 分 别 与 底 层 的 文 件 描 述 符 0,1, 2 相 对 应 fopen fopen 库 函 数 是 底 层 的 open 系 统 调 用 的 模 拟 我 们 主 要 将 它 用 于 文 件 或 是 终 端 输 入 与 输 出 然 而 在 我 们 需 要 显 示 的 控 制 设 备 的 地 方, 我 们 最 好 是 使 用 底 层 的 系 统 调 用, 因 为 它 们 可 以 消 除 由 库 所 造 成 的 潜 在 的 不 良 因 素, 如 输 入 / 输 出 缓 冲 区 其 语 法 格 式 如 下 : #include <stdio.h> FILE *fopen(const char *filename, const char *mode); fopen 打 开 由 filename 参 数 所 指 定 的 文 件, 并 建 立 一 个 与 其 相 关 的 流 mode 参 数 指 出 如 何 来 打 开 这 个 文 件, 它 可 以 是 下 列 字 符 串 中 的 一 个 : r 或 rb : 以 只 读 方 式 打 开 ; w 或 wb : 以 只 写 方 式 打 开 ; a 或 ab : 以 读 方 式 打 开, 添 加 到 文 件 的 结 尾 处 ; r+ 或 rb+ 或 r+b : 打 开 更 新 ( 读 和 写 ); w+ 或 wb+ 或 w+b : 打 开 更 新, 将 其 长 度 变 为 零 ; a+ 或 ab+ 或 a+b : 打 开 更 新, 添 加 到 文 件 结 尾 处 ; b 表 明 这 个 文 件 是 二 进 制 文 件 而 不 是 文 本 文 件 在 这 里 我 们 要 注 意, 与 MS-DOS 不 同,Unix 和 Linux 并 不 会 在 文 本 文 件 与 二 进 制 文 件 之 间 进 行

174 区 别 Unix 与 Linux 将 所 有 文 件 看 成 是 一 样 的, 尤 其 是 二 进 制 文 件 另 外 要 注 意 的 一 点 就 是 mode 参 数 必 须 是 一 个 字 符 串, 而 不 是 一 个 字 符 我 们 要 使 用 r, 而 绝 不 可 以 是 r 如 果 函 数 调 用 成 功,fopen 会 返 回 一 个 非 空 的 文 件 指 针 如 果 失 败, 它 会 返 回 NULL, 这 是 在 stdio.h 中 定 义 的 fread fread 库 函 数 可 以 用 来 从 一 个 文 件 流 中 读 取 数 据 由 stream 流 中 读 取 的 数 据 将 会 放 在 由 prt 所 指 定 的 数 据 缓 冲 区 中 fread 和 fwrite 都 处 理 数 据 记 录 这 些 是 由 块 的 尺 寸 size, 读 取 的 次 数 nitems 来 指 定 要 传 送 的 记 录 块 的 如 果 成 功 则 返 回 值 为 实 际 读 入 到 数 据 缓 冲 区 中 的 块 数, 而 不 是 字 节 数 在 文 件 的 结 尾 处, 也 许 会 返 回 少 于 nitems 的 值, 包 括 零 其 语 法 格 式 如 下 : #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); 与 所 有 要 写 入 到 缓 冲 区 中 的 标 准 I/O 函 数 一 样, 程 序 员 要 负 责 分 配 数 据 空 间 以 及 检 查 错 误 fwrite fwrite 调 用 一 个 与 fread 相 类 似 的 函 数 接 口, 它 将 会 从 指 定 的 数 据 区 读 取 数 据 记 录 并 写 入 到 输 出 流 中 它 的 返 回 值 为 成 功 写 入 的 记 录 数 其 语 法 格 式 如 下 : #include <stdio.h> size_t fwrite (const void *ptr, size_t size, size_t nitems, FILE *stream); 在 这 里 我 们 要 注 意 就 是 我 们 并 不 推 荐 在 使 用 结 构 数 据 时 使 用 fread 与 fwrite 一 部 分 的 原 因 就 是 因 为 用 fwrite 写 入 的 文 件 潜 在 的 存 在 着 在 不 同 的 机 器 间 不 兼 容 的 问 题 fclose fclose 库 函 数 关 闭 指 定 的 文 件 流, 并 将 所 有 未 写 入 的 数 据 写 入 文 件 中 使 用 fclose 是 相 当 重 要 的, 因 为 stdio 库 会 缓 存 数 据 如 果 程 序 需 要 确 定 已 经 完 整 的 写 入 了 所 有 的 数 据, 这 时 就 应 调 用 fclose 然 而, 当 一 个 程 序 正 常 结 束 时,fclose 就 自 动 调 用, 从 而 关 闭 所 有 仍 然 打 开 的 文 件 流 当 然, 在 这 样 的 情 况 下, 我 们 就 没 有 机 会 来 检 查 由 fclose 报 告 的 错 误 与 文 件 描 述 符 所 有 的 限 制 一 样, 可 用 的 流 数 目 也 是 有 限 制 的 实 际 的 限 制 是 FOPEN_MAX, 这 是 在 stdio.h 中 定 义, 而 且 至 少 为 8 个 其 语 法 格 式 如 下 : #include <stdio.h> int fclose(file *stream); mkdir 可 以 使 用 mkdir 和 rmdir 来 创 建 和 移 除 目 录 其 语 法 如 下 : #include <sys/stat.h>

175 int mkdir(const char *path, mode_t mode); mkdir 系 统 调 用 可 以 用 来 创 建 目 录, 而 这 是 与 mkdir 程 序 相 等 同 的 mkdir 以 path 为 名 字 创 建 一 个 新 的 目 录 目 录 的 权 限 是 由 参 数 mode 来 指 定 的, 而 这 也 与 open 系 统 调 用 中 的 O_CREAT 的 选 项 是 一 样 的, 而 且 这 也 是 要 受 到 umask 的 影 响 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 12 章 /12.2-file 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 file 程 序 : $ cd /usr/local/src/s210x/project/12.2-file $ arm-none-linux-gnueabi-gcc -o file file.c $ cp file /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 file 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./file -l./file 5) 给 file 添 加 可 执 行 权 限 : # chmod 777 file 6) 运 行 file: #./file 17 byte data has written to linux.txt

176 Folder linux created success! # ls -l /tmp/ d x 2 root root 4096 Jan 1 12:21 linux -rw-r--r-- 1 root root 17 Jan 1 12:21 linux.txt # cat /tmp/linux.txt Hello ARM Linux! 12.3 进 程 控 制 实 验 实 验 目 的 熟 练 掌 握 fork(),exec(),wait(),waitpid() 等 函 数 的 使 用 ; 理 解 在 linux 中 多 进 程 编 程 以 及 进 程 间 通 信 的 步 骤 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Linux 进 程 基 础 知 识 进 程 作 为 构 成 系 统 的 基 本 细 胞, 不 仅 是 系 统 内 部 独 立 运 行 的 实 体, 而 且 是 独 立 竞 争 资 源 的 基 本 实 体 了 解 进 程 的 本 质, 对 于 理 解 描 述 和 设 计 操 作 系 统 有 着 极 为 重 要 的 意 义 了 解 进 程 的 活 动 状 态, 也 有 利 于 编 制 复 杂 程 序 首 先 我 们 看 进 程 的 定 义, 进 程 是 一 个 具 有 独 立 功 能 的 程 序 关 于 某 个 数 据 集 合 的 一 次 可 以 并 发 执 行 的 运 行 活 动, 是 处 于 活 动 状 态 的 计 算 机 程 序 1) 进 程 状 态 和 状 态 转 换 现 在 我 们 来 看 看, 进 程 在 生 存 周 期 中 的 各 种 状 态 及 状 态 的 转 换 下 面 是 Linux 系 统 的 进 程 状 态 模 型 的 各 种 状 态 : 用 户 状 态 : 进 程 在 用 户 状 态 下 运 行 的 状 态 ; 内 核 状 态 : 进 程 在 内 核 状 态 下 运 行 的 状 态 ; 内 存 中 就 绪 : 进 程 没 有 执 行, 但 处 于 就 绪 状 态, 只 要 内 核 调 度 它, 就 可 以 执 行 ;

177 内 存 中 睡 眠 : 进 程 正 在 睡 眠 并 且 进 程 存 储 在 内 存 中, 没 有 被 交 换 到 SWAP 设 备 ; 就 绪 且 换 出 : 进 程 处 于 就 绪 状 态, 但 是 必 须 把 它 换 入 内 存, 内 核 才 能 再 次 调 度 它 进 行 运 行 ; 睡 眠 且 换 出 : 进 程 正 在 睡 眠, 且 被 换 出 内 存 ; 被 抢 先 : 进 程 从 内 核 状 态 返 回 用 户 状 态 时, 内 核 抢 先 于 它, 做 了 上 下 文 切 换, 调 度 了 另 一 个 进 程 原 先 这 个 进 程 就 处 于 被 抢 先 状 态 ; 创 建 状 态 : 进 程 刚 被 创 建 该 进 程 存 在, 但 既 不 是 就 绪 状 态, 也 不 是 睡 眠 状 态 这 个 状 态 是 除 了 进 程 0 以 外 的 所 有 进 程 的 最 初 状 态 ; 僵 死 状 态 (zombie): 进 程 调 用 exit 结 束, 进 程 不 再 存 在, 但 在 进 程 表 项 中 仍 有 纪 录, 该 纪 录 可 由 父 进 程 收 集 现 在 我 们 从 进 程 的 创 建 到 退 出 来 看 看 进 程 的 状 态 转 化 需 要 说 明 的 是, 进 程 在 它 的 生 命 周 期 里 并 不 一 定 要 经 历 所 有 的 状 态 首 先 父 进 程 通 过 系 统 调 用 fork() 来 创 建 子 进 程, 调 用 fork() 时, 子 进 程 首 先 处 于 创 建 态,fork() 调 用 为 子 进 程 配 置 好 内 核 数 据 结 构 和 子 进 程 私 有 数 据 结 构 后, 子 进 程 就 要 进 入 就 绪 态 3 或 5, 即 在 内 存 中 就 绪, 或 者 因 为 内 存 不 够, 而 导 致 在 SWAP 设 备 中 就 绪 假 设 进 程 在 内 存 中 就 绪, 这 时 子 进 程 就 可 以 被 内 核 调 度 程 序 调 度 上 CPU 运 行 内 核 调 度 该 进 程 进 入 内 核 状 态, 再 由 内 核 状 态 返 回 用 户 状 态 执 行 该 进 程 在 用 户 状 态 运 行 一 定 时 间 后, 又 会 被 调 度 程 序 所 调 度 而 进 入 内 核 状 态, 由 此 转 入 就 绪 态 有 时 进 程 在 用 户 状 态 运 行 时, 也 会 因 为 需 要 内 核 服 务, 使 用 系 统 调 用 而 进 入 内 核 状 态, 服 务 完 毕, 会 由 内 核 状 态 转 回 用 户 状 态 要 注 意 的 是, 进 程 在 从 内 核 状 态 向 用 户 状 态 返 回 时 可 能 被 抢 占, 进 入 状 态 7, 这 是 由 于 有 优 先 级 更 高 的 进 程 急 需 使 用 CPU, 不 能 等 到 下 一 次 调 度 时 机, 从 而 造 成 抢 占 进 程 还 会 因 为 请 求 的 资 源 不 能 得 到 满 足, 进 入 睡 眠 状 态, 直 到 它 请 求 的 资 源 被 释 放, 才 会 被 内 核 唤 醒 而 进 入 就 绪 态 如 果 进 程 在 内 存 中 睡 眠 时, 内 存 不 足, 当 进 程 睡 眠 时 间 达 到 一 个 阀 值, 进 程 会 被 SWAP 出 内 存, 使 得 进 程 在 SWAP 设 备 上 睡 眠 这 种 状 况 同 样 可 能 发 生 在 就 绪 的 进 程 上 进 程 调 用 exit 系 统 调 用, 将 使 得 进 程 进 入 内 核 状 态, 执 行 exit 调 用, 进 入 僵 死 状 态 而 结 束 以 上 就 是 进 程 状 态 转 换 的 简 单 描 述 进 程 的 上 下 文 是 由 用 户 级 上 下 文 寄 存 器 上 下 文 以 及 系 统 级 上 下 文 组 成 主 要 内 容 是 该 进 程 用 户 空 间 内 容 寄 存 器 内 容 以 及 与 该 进 程 有 关 的 内 核 数 据 结 构 当 系 统 收 到 一 个 中 断, 执 行 系 统 调 用 或 内 核 做 上 下 文 切 换 时, 就 会 保 存 进 程 的 上 下 文 一 个 进 程 是 在 它 的 上 下 文 中 运 行 的, 若 要 调 度 进 程, 就 要 进 行 上 下 文 切 换 内 核 在 四 种 情 况 下 允 许 发 生 上 下 文 切 换 : 当 进 程 自 己 进 入 睡 眠 时 ; 当 进 程 执 行 完 系 统 调 用 要 返 回 用 户 状 态, 但 发 现 该 进 程 不 是 最 有 资 格 运 行 的 进 程 时 ; 当 内 核 完 成 中 断 处 理 后 要 返 回 用 户 状 态, 但 发 现 该 进 程 不 是 最 有 资 格 运 行 的 进 程 时 ; 当 进 程 退 出 ( 执 行 系 统 调 用 exit 后 ) 时

178 有 时 内 核 要 求 必 须 终 止 当 前 的 执 行, 立 即 从 先 前 保 存 的 上 下 文 处 执 行 这 可 由 setjmp 和 longjmp 实 现,setjmp 将 保 存 的 上 下 文 存 入 进 程 自 身 的 数 据 空 间 (u 区 ) 中, 并 继 续 在 当 前 的 上 下 文 中 执 行, 一 旦 碰 到 了 longjmp, 内 核 就 从 该 进 程 的 u 区, 取 出 先 前 保 存 的 上 下 文, 并 恢 复 该 进 程 的 上 下 文 为 原 先 保 存 的 这 时 内 核 将 使 得 进 程 从 setjmp 处 执 行, 并 给 setjmp 返 回 1 进 程 因 等 待 资 源 或 其 他 原 因, 进 入 睡 眠 态 是 通 过 内 核 的 sleep 算 法 该 算 法 与 本 章 后 面 要 讲 到 的 sleep 函 数 是 两 个 概 念 算 法 sleep 记 录 进 程 原 先 的 处 理 机 优 先 级, 置 进 程 为 睡 眠 态, 将 进 程 放 入 睡 眠 队 列, 记 录 睡 眠 的 原 因, 给 该 进 程 进 行 上 下 文 切 换 内 核 通 过 算 法 wakeup 来 唤 醒 进 程, 如 某 资 源 被 释 放, 则 唤 醒 所 有 因 等 待 该 资 源 而 进 入 睡 眠 的 进 程 如 果 进 程 睡 眠 在 一 个 可 以 接 收 软 中 断 信 号 (signal) 的 级 别 上, 则 进 程 的 睡 眠 可 由 软 中 断 信 号 的 到 来 而 被 唤 醒 2) 进 程 控 制 现 在 我 们 开 始 讲 述 一 下 进 程 的 控 制, 主 要 介 绍 内 核 对 fork exec wait exit 的 处 理 过 程, 为 学 习 这 些 调 用 打 下 概 念 上 的 基 础, 并 介 绍 系 统 启 动 (boot) 的 过 程 以 及 进 程 init 的 作 用 在 Linux 系 统 中, 用 户 创 建 一 个 进 程 的 唯 一 方 法 就 是 使 用 系 统 调 用 fork 内 核 为 完 成 系 统 调 用 fork 要 进 行 几 步 操 作 第 一 步, 为 新 进 程 在 进 程 表 中 分 配 一 个 表 项 系 统 对 一 个 用 户 可 以 同 时 运 行 的 进 程 数 是 有 限 制 的, 对 超 级 用 户 没 有 该 限 制, 但 也 不 能 超 过 进 程 表 的 最 大 表 项 的 数 目 第 二 步, 给 子 进 程 一 个 唯 一 的 进 程 标 识 号 (PID) 该 进 程 标 识 号 其 实 就 是 该 表 项 在 进 程 表 中 的 索 引 号 第 三 步, 复 制 一 个 父 进 程 的 进 程 表 项 的 副 本 给 子 进 程 内 核 初 始 化 子 进 程 的 进 程 表 项 时, 是 从 父 进 程 处 拷 贝 的 所 以 子 进 程 拥 有 与 父 进 程 一 样 的 uid euid gid 用 于 计 算 优 先 权 的 nice 值 当 前 目 录 当 前 根 用 户 文 件 描 述 符 表 等 第 四 步, 把 与 父 进 程 相 连 的 文 件 表 和 索 引 节 点 表 的 引 用 数 加 1 这 些 文 件 自 动 地 与 该 子 进 程 相 连 第 五 步, 内 核 为 子 进 程 创 建 用 户 级 上 下 文 内 核 为 子 进 程 的 u 区 及 辅 助 页 表 分 配 内 存, 并 复 制 父 进 程 的 区 内 容 这 样 生 成 的 是 进 程 的 静 态 部 分 第 六 步, 生 成 进 程 的 动 态 部 分, 内 核 复 制 父 进 程 的 上 下 文 的 第 一 层, 即 寄 存 器 上 下 文 和 内 核 栈, 内 核 再 为 子 进 程 虚 设 一 个 上 下 文 层, 这 是 为 了 子 进 程 能 恢 复 它 的 上 下 文 这 时, 该 调 用 会 对 父 进 程 返 回 子 进 程 的 pid, 对 子 进 程 返 回 0 Linux 系 统 的 系 统 调 用 exit, 是 进 程 用 来 终 止 执 行 时 调 用 的 进 程 发 出 该 调 用, 内 核 就 会 释 放 该 进 程 所 占 的 资 源, 释 放 进 程 上 下 文 所 占 的 内 存 空 间, 保 留 进 程 表 项, 将 进 程 表 项 中 纪 录 进 程 状 态 的 字 段 设 为 僵 死 状 态 内 核 在 进 程 收 到 不 可 捕 捉 的 信 号 时, 会 从 内 核 内 部 调 用 exit, 使 得 进 程 退 出 父 进 程 通 过 wait 得 到 其 子 进 程 的 进 程 表 项 中 纪 录 的 计 时 数 据, 并 释 放 进 程 表 项 最 后, 内 核 使 得 进 程 1(init 进 程 ) 接 收 终 止 执 行 的 进 程 的 所 有 子 进 程 如 果 有 子 进 程 僵 死, 就 向 init 进 程 发 出 一 个 SIGCHLD 的 软 中 断 信 号 一 个 进 程 通 过 调 用 wait 来 与 它 的 子 进 程 同 步, 如 果 发 出 调 用 的 进 程 没 有 子 进 程 则 返 回 一 个 错 误, 如 果 找 到 一 个 僵 死 的 子 进 程 就 取 子 进 程 的 PID 及 退 出 时 提 供 给 父 进 程 的 参 数 如 果 有 子 进 程, 但 没 有 僵 死 的 子 进 程, 发 出 调 用 的 进 程 就 睡 眠 在 一 个 可 中 断 的 级 别 上, 直 到 收 到 一 个 子 进 程 僵 死

179 (SIGCLD) 的 信 号 或 其 他 信 号 进 程 控 制 的 另 一 个 主 要 内 容 就 是 对 其 他 程 序 引 用 该 功 能 是 通 过 系 统 调 用 exec 来 实 现 的, 该 调 用 将 一 个 可 执 行 的 程 序 文 件 读 入, 代 替 发 出 调 用 的 进 程 执 行 内 核 读 入 程 序 文 件 的 正 文, 清 除 原 先 进 程 的 数 据 区, 清 除 原 先 用 户 软 中 断 信 号 处 理 函 数 的 地 址, 当 exec 调 用 返 回 时, 进 程 执 行 新 的 正 文 一 个 系 统 启 动 的 过 程, 也 称 作 是 自 举 的 过 程 该 过 程 因 机 器 的 不 同 而 有 所 差 异 但 该 过 程 的 目 的 对 所 有 机 器 都 相 同 : 将 操 作 系 统 装 入 内 存 并 开 始 执 行 计 算 机 先 由 硬 件 将 引 导 块 的 内 容 读 到 内 存 并 执 行, 自 举 块 的 程 序 将 内 核 从 文 件 系 统 中 装 入 内 存, 并 将 控 制 转 入 内 核 的 入 口, 内 核 开 始 运 行 内 核 首 先 初 始 化 它 的 数 据 结 构, 并 将 根 文 件 系 统 安 装 到 根 /, 为 进 程 0 形 成 执 行 环 境 设 置 好 进 程 0 的 环 境 后, 内 核 便 作 为 进 程 0 开 始 执 行, 并 调 用 系 统 调 用 fork 因 为 这 时 进 程 0 运 行 在 内 核 状 态, 所 以 新 的 进 程 也 运 行 在 内 核 状 态 新 的 进 程 ( 进 程 1) 创 建 自 己 的 用 户 级 上 下 文, 设 置 并 保 存 好 用 户 寄 存 器 上 下 文 这 时, 进 程 1 就 从 内 核 状 态 返 回 用 户 状 态 执 行 从 内 核 拷 贝 的 代 码 (exec), 并 调 用 exec 执 行 /sbin/init 程 序 进 程 1 通 常 称 为 初 始 化 进 程, 它 负 责 初 始 化 新 的 进 程 进 程 init 除 了 产 生 新 的 进 程 外, 还 负 责 一 些 使 用 户 在 系 统 上 注 册 的 进 程 例 如, 进 程 init 一 般 要 产 生 一 些 getty 的 子 进 程 来 监 视 终 端 如 果 一 个 终 端 被 打 开,getty 子 进 程 就 要 求 在 这 个 终 端 上 执 行 一 个 注 册 的 过 程, 当 成 功 注 册 后, 执 行 一 个 shell 程 序, 来 使 得 用 户 与 系 统 交 互 同 时, 进 程 init 执 行 系 统 调 用 wait 来 监 视 子 进 程 的 死 亡, 以 及 由 于 父 进 程 的 退 出 而 产 生 的 孤 儿 进 程 的 移 交 以 上 是 系 统 启 动 和 进 程 init 的 一 个 粗 略 的 模 型 3) 进 程 调 度 的 概 念 Linux 系 统 是 一 个 分 时 系 统, 内 核 给 每 个 进 程 分 一 个 时 间 片, 该 进 程 的 时 间 片 用 完 就 会 调 度 另 一 个 进 程 执 行 Linux 系 统 上 的 调 度 程 序 属 于 多 级 反 馈 循 环 调 度 该 调 度 方 法 是, 给 一 个 进 程 分 一 个 时 间 片, 抢 先 一 个 运 行 超 过 时 间 片 的 进 程, 并 把 进 程 反 馈 到 若 干 优 先 级 队 列 中 的 一 个 队 列 进 程 在 执 行 完 之 前, 要 经 过 这 样 多 次 反 馈 循 环 进 程 调 度 分 成 两 个 部 分, 一 个 是 调 度 的 时 机, 即 什 么 时 候 调 度 ; 一 个 是 调 度 的 算 法, 即 如 何 调 度 和 调 度 哪 个 进 程 我 们 先 来 看 看 调 度 的 算 法, 假 设 目 前 内 核 要 求 进 行 调 度, 调 度 程 序 从 在 内 存 中 就 绪 和 被 抢 先 状 态 的 进 程 中 选 择 一 个 优 先 权 最 高 的 进 程, 如 果 有 若 干 优 先 4) 多 进 程 编 程 在 传 统 的 Unix 环 境 下, 有 两 个 基 本 的 操 作 用 于 创 建 和 修 改 进 程 : 函 数 fork() 用 来 创 建 一 个 新 的 进 程, 该 进 程 几 乎 是 当 前 进 程 的 一 个 完 全 拷 贝 ; 函 数 族 exec() 用 来 启 动 另 外 的 进 程 以 取 代 当 前 运 行 的 进 程 Linux 的 进 程 控 制 和 传 统 的 Unix 进 程 控 制 基 本 一 致, 只 在 一 些 细 节 的 地 方 有 些 区 别, 例 如 在 Linux 系 统 中 调 用 vfork 和 fork 完 全 相 同, 而 在 有 些 版 本 的 Unix 系 统 中,vfork 调 用 有 不 同 的 功 能 由 于 这 些 差 别 几 乎 不 影 响 我 们 大 多 数 的 编 程, 在 这 里 我 们 不 予 考 虑 fork 在 英 文 中 是 分 叉 的 意 思 为 什 么 取 这 个 名 字 呢? 因 为 一 个 进 程 在 运 行 中, 如 果 使 用 了 fork, 就 产 生 了 另 一 个 进 程, 于 是 进 程 就 分 叉 了, 所 以 这 个 名 字 取 得 很 形 象 下 面 就 看 看 如 何 具

180 体 使 用 fork, 这 段 程 序 演 示 了 使 用 fork 的 基 本 框 架 : void main() { int i; if ( fork() == 0 ) { // 子 进 程 程 序 for ( i = 1; i <1000; i ++ ) printf("this is child process\n"); } else { // 父 进 程 程 序 for ( i = 1; i <1000; i ++ ) printf("this is process process\n"); } } 程 序 运 行 后, 你 就 能 看 到 屏 幕 上 交 替 出 现 子 进 程 与 父 进 程 各 打 印 出 的 一 千 条 信 息 了 如 果 程 序 还 在 运 行 中, 你 用 ps 命 令 就 能 看 到 系 统 中 有 两 个 它 在 运 行 了 那 么 调 用 这 个 fork 函 数 时 发 生 了 什 么 呢?fork 函 数 启 动 一 个 新 的 进 程, 前 面 我 们 说 过, 这 个 进 程 几 乎 是 当 前 进 程 的 一 个 拷 贝 : 子 进 程 和 父 进 程 使 用 相 同 的 代 码 段 ; 子 进 程 复 制 父 进 程 的 堆 栈 段 和 数 据 段 这 样, 父 进 程 的 所 有 数 据 都 可 以 留 给 子 进 程 但 是, 子 进 程 一 旦 开 始 运 行, 虽 然 它 继 承 了 父 进 程 的 一 切 数 据, 但 实 际 上 数 据 却 已 经 分 开, 相 互 之 间 不 再 有 影 响 了, 也 就 是 说, 它 们 之 间 不 再 共 享 任 何 数 据 了 它 们 再 要 交 互 信 息 时, 只 有 通 过 进 程 间 通 信 来 实 现, 这 将 是 我 们 下 面 的 内 容 既 然 它 们 如 此 相 象, 系 统 如 何 来 区 分 它 们 呢? 这 是 由 函 数 的 返 回 值 来 决 定 的 对 于 父 进 程,fork 函 数 返 回 了 子 程 序 的 进 程 号, 而 对 于 子 程 序,fork 函 数 则 返 回 零 在 操 作 系 统 中, 我 们 用 ps 函 数 就 可 以 看 到 不 同 的 进 程 号, 对 父 进 程 而 言, 它 的 进 程 号 是 由 比 它 更 低 层 的 系 统 调 用 赋 予 的, 而 对 于 子 进 程 而 言, 它 的 进 程 号 即 是 fork 函 数 对 父 进 程 的 返 回 值 在 程 序 设 计 中, 父 进 程 和 子 进 程 都 要 调 用 函 数 fork() 下 面 的 代 码, 而 我 们 就 是 利 用 fork() 函 数 对 父 子 进 程 的 不 同 返 回 值 用 if...else... 语 句 来 实 现 让 父 子 进 程 完 成 不 同 的 功 能, 正 如 我 们 上 面 举 的 例 子 一 样 我 们 看 到, 上 面 例 子 执 行 时 两 条 信 息 是 交 互 无 规 则 的 打 印 出 来 的, 这 是 父 子 进 程 独 立 执 行 的 结 果, 虽 然 我 们 的 代 码 似 乎 和 串 行 的 代 码 没 有 什 么 区 别 读 者 也 许 会 问, 如 果 一 个 大 程 序 在 运 行 中, 它 的 数 据 段 和 堆 栈 都 很 大, 一 次 fork 就 要 复 制 一 次, 那 么 fork 的 系 统 开 销 不 是 很 大 吗? 其 实 UNIX 自 有 其 解 决 的 办 法, 大 家 知 道, 一 般 CPU 都 是 以 页 为 单 位 来 分 配 内 存 空 间 的, 每 一 个 页 都 是 实 际 物 理 内 存 的 一 个 映 像, 像 Intel 的 CPU, 其 一 页 在 通 常 情 况 下 是 4086 字 节 大 小, 而 无 论 是 数 据 段 还 是 堆 栈 段 都 是 由 许 多 页 构 成 的,fork 函 数 复 制 这 两 个 段, 只 是 逻 辑 上 的, 并 非 物 理 上 的, 也 就 是 说, 实 际 执 行 fork 时, 物 理 空 间 上 两 个 进

181 程 的 数 据 段 和 堆 栈 段 都 还 是 共 享 着 的, 当 有 一 个 进 程 写 了 某 个 数 据 时, 这 时 两 个 进 程 之 间 的 数 据 才 有 了 区 别, 系 统 就 将 有 区 别 的 页 从 物 理 上 也 分 开 系 统 在 空 间 上 的 开 销 就 可 以 达 到 最 小 下 面 演 示 一 个 足 以 搞 死 Linux 的 小 程 序, 其 源 代 码 非 常 简 单 : void main() { for( ; ; ) fork(); } 这 个 程 序 什 么 也 不 做, 就 是 死 循 环 地 fork, 其 结 果 是 程 序 不 断 产 生 进 程, 而 这 些 进 程 又 不 断 产 生 新 的 进 程, 很 快, 系 统 的 进 程 就 满 了, 系 统 就 被 这 么 多 不 断 产 生 的 进 程 撑 死 了 当 然 只 要 系 统 管 理 员 预 先 给 每 个 用 户 设 置 可 运 行 的 最 大 进 程 数, 这 个 恶 意 的 程 序 就 完 成 不 了 企 图 了 5) 进 程 间 通 信 首 先, 进 程 间 通 信 至 少 可 以 通 过 传 送 打 开 文 件 来 实 现, 不 同 的 进 程 通 过 一 个 或 多 个 文 件 来 传 递 信 息 事 实 上, 在 很 多 应 用 系 统 里, 都 使 用 了 这 种 方 法 但 一 般 说 来, 进 程 间 通 信 (IPC:Inter Process Communication) 不 包 括 这 种 似 乎 比 较 低 级 的 通 信 方 法 Unix 系 统 中 实 现 进 程 间 通 信 的 方 法 很 多, 而 且 不 幸 的 是, 极 少 方 法 能 在 所 有 的 Unix 系 统 中 进 行 移 植 ( 唯 一 一 种 是 半 双 工 的 管 道, 这 也 是 最 原 始 的 一 种 通 信 方 式 ) 而 Linux 作 为 一 种 新 兴 的 操 作 系 统, 几 乎 支 持 所 有 的 Unix 下 常 用 的 进 程 间 通 信 方 法 : 管 道 消 息 队 列 共 享 内 存 信 号 量 套 接 口 等 等 下 面 我 们 将 逐 一 介 绍 管 道 管 道 是 进 程 间 通 信 中 最 古 老 的 方 式, 它 包 括 无 名 管 道 和 有 名 管 道 两 种, 前 者 用 于 父 进 程 和 子 进 程 间 的 通 信, 后 者 用 于 运 行 于 同 一 台 机 器 上 的 任 意 两 个 进 程 间 的 通 信 无 名 管 道 由 pipe() 函 数 创 建 : #include <unistd.h> int pipe(int filedes[2]); 参 数 filedes 返 回 两 个 文 件 描 述 符 :filedes[0] 为 读 而 打 开,filedes[1] 为 写 而 打 开 filedes[1] 的 输 出 是 filedes[0] 的 输 入 下 面 的 例 子 示 范 了 如 何 在 父 进 程 和 子 进 程 间 实 现 通 信 #define INPUT 0 #define OUTPUT 1 void main() { int file_descriptors[2]; // 定 义 子 进 程 号 pid_t pid; char buf[256]; int returned_count; // 创 建 无 名 管 道

182 pipe(file_descriptors); // 创 建 子 进 程 if((pid = fork()) == -1) { printf("error in fork\n"); exit(1); } // 执 行 子 进 程 if(pid == 0) { printf("in the spawned (child) process...\n"); // 子 进 程 向 父 进 程 写 数 据, 关 闭 管 道 的 读 端 close(file_descriptors[input]); write(file_descriptors[output], "test data", strlen("test data")); exit(0); } else { // 执 行 父 进 程 printf("in the spawning (parent) process...\n"); // 父 进 程 从 管 道 读 取 子 进 程 写 的 数 据, 关 闭 管 道 的 写 端 close(file_descriptors[output]); returned_count = read(file_descriptors[input], buf, sizeof(buf)); printf("%d bytes of data received from spawned process: %s\n", returned_count, buf); } } 在 Linux 系 统 下, 有 名 管 道 可 由 两 种 方 式 创 建 : 命 令 行 方 式 mknod 系 统 调 用 和 函 数 mkfifo 下 面 的 两 种 途 径 都 在 当 前 目 录 下 生 成 了 一 个 名 为 myfifo 的 有 名 管 道 : 方 式 一 :mkfifo("myfifo","rw"); 方 式 二 :mknod myfifo p 生 成 了 有 名 管 道 后, 就 可 以 使 用 一 般 的 文 件 I/O 函 数 如 open close read write 等 来 对 它 进 行 操 作 消 息 队 列 消 息 队 列 用 于 运 行 于 同 一 台 机 器 上 的 进 程 间 通 信, 它 和 管 道 很 相 似 事 实 上, 它 是 一 种 正 逐 渐 被 淘 汰 的 通 信 方 式, 我 们 可 以 用 流 管 道 或 者 套 接 口 的 方 式 来 取 代 它 所 以, 我 们 对 此 方 式 也 不 再 解 释, 也 建 议 读 者 忽 略 这 种 方 式 共 享 内 存

183 共 享 内 存 是 运 行 在 同 一 台 机 器 上 的 进 程 间 通 信 最 快 的 方 式, 因 为 数 据 不 需 要 在 不 同 的 进 程 间 复 制 通 常 由 一 个 进 程 创 建 一 块 共 享 内 存 区, 其 余 进 程 对 这 块 内 存 区 进 行 读 写 共 享 内 存 有 两 种 方 式 : 映 射 /dev/mem 设 备 和 内 存 映 像 文 件 前 一 种 方 式 不 给 系 统 带 来 额 外 的 开 销, 但 在 现 实 中 并 不 常 用, 因 为 它 控 制 存 取 的 将 是 实 际 的 物 理 内 存, 在 Linux 系 统 下, 这 只 有 通 过 限 制 Linux 系 统 存 取 的 内 存 才 可 以 做 到, 这 当 然 不 太 实 际 常 用 的 方 式 是 通 过 shmxxx 函 数 族 来 实 现 利 用 共 享 内 存 进 行 存 储 的 首 先 要 用 的 函 数 是 shmget, 它 获 得 一 个 共 享 存 储 标 识 符 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int flag); 这 个 函 数 有 点 类 似 大 家 熟 悉 的 malloc 函 数, 系 统 按 照 请 求 分 配 size 大 小 的 内 存 用 作 共 享 内 存 Linux 系 统 内 核 中 每 个 IPC 结 构 都 有 一 个 非 负 整 数 的 标 识 符, 这 样 对 一 个 消 息 队 列 发 送 消 息 时 只 要 引 用 标 识 符 就 可 以 了 这 个 标 识 符 是 内 核 由 IPC 结 构 的 关 键 字 得 到 的, 这 个 关 键 字, 就 是 上 面 第 一 个 函 数 的 key 数 据 类 型 key_t 是 在 头 文 件 sys/types.h 中 定 义 的, 它 是 一 个 长 整 形 的 数 据 在 我 们 后 面 的 章 节 中, 还 会 碰 到 这 个 关 键 字 当 共 享 内 存 创 建 后, 其 余 进 程 可 以 调 用 shmat() 将 其 连 接 到 自 身 的 地 址 空 间 中 void *shmat(int shmid, void *addr, int flag) ; shmid 为 shmget 函 数 返 回 的 共 享 存 储 标 识 符,addr 和 flag 参 数 决 定 了 以 什 么 方 式 来 确 定 连 接 的 地 址, 函 数 的 返 回 值 即 是 该 进 程 数 据 段 所 连 接 的 实 际 地 址, 进 程 可 以 对 此 进 程 进 行 读 写 操 作 使 用 共 享 存 储 来 实 现 进 程 间 通 信 的 注 意 点 是 对 数 据 存 取 的 同 步, 必 须 确 保 当 一 个 进 程 去 读 取 数 据 时, 它 所 想 要 的 数 据 已 经 写 好 了 通 常, 信 号 量 被 用 来 实 现 对 共 享 存 储 数 据 存 取 的 同 步, 另 外, 可 以 通 过 使 用 shmctl 函 数 设 置 共 享 存 储 内 存 的 某 些 标 志 位 如 SHM_LOCK SHM_UNLOCK 等 来 实 现 信 号 量 信 号 量 又 称 为 信 号 灯, 它 是 用 来 协 调 不 同 进 程 间 的 数 据 对 象 的, 而 最 主 要 的 应 用 是 前 一 节 的 共 享 内 存 方 式 的 进 程 间 通 信 本 质 上, 信 号 量 是 一 个 计 数 器, 它 用 来 记 录 对 某 个 资 源 ( 如 共 享 内 存 ) 的 存 取 状 况 一 般 说 来, 为 了 获 得 共 享 资 源, 进 程 需 要 执 行 下 列 操 作 : (1) 测 试 控 制 该 资 源 的 信 号 量 ; (2) 若 此 信 号 量 的 值 为 正, 则 允 许 进 行 使 用 该 资 源, 进 程 将 信 号 量 减 1; (3) 若 此 信 号 量 为 0, 则 该 资 源 目 前 不 可 用, 进 程 进 入 睡 眠 状 态, 直 至 信 号 量 值 大 于 0, 进 程 被 唤 醒, 转 入 步 骤 (1); (4) 当 进 程 不 再 使 用 一 个 信 号 量 控 制 的 资 源 时, 信 号 量 值 加 1 如 果 此 时 有 进 程 正 在 睡 眠 等 待 此 信 号 量, 则 唤 醒 此 进 程 维 护 信 号 量 状 态 的 是 Linux 内 核 操 作 系 统 而 不 是 用 户 进 程 我 们 可 以 从 头 文 件

184 /usr/src/linux/include/linux/sem.h 中 看 到 内 核 用 来 维 护 信 号 量 状 态 的 各 个 结 构 的 定 义 信 号 量 是 一 个 数 据 集 合, 用 户 可 以 单 独 使 用 这 一 集 合 的 每 个 元 素 要 调 用 的 第 一 个 函 数 是 semget, 用 以 获 得 一 个 信 号 量 ID #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int flag); key 是 前 面 讲 过 的 IPC 结 构 的 关 键 字, 它 将 来 决 定 是 创 建 新 的 信 号 量 集 合, 还 是 引 用 一 个 现 有 的 信 号 量 集 合 nsems 是 该 集 合 中 的 信 号 量 数 如 果 是 创 建 新 集 合 ( 一 般 在 服 务 器 中 ), 则 必 须 指 定 nsems; 如 果 是 引 用 一 个 现 有 的 信 号 量 集 合 ( 一 般 在 客 户 机 中 ) 则 将 nsems 指 定 为 0 semctl 函 数 用 来 对 信 号 量 进 行 操 作 int semctl(int semid, int semnum, int cmd, union semun arg); 不 同 的 操 作 是 通 过 cmd 参 数 来 实 现 的, 在 头 文 件 sem.h 中 定 义 了 7 种 不 同 的 操 作, 实 际 编 程 时 可 以 参 照 使 用 semop 函 数 自 动 执 行 信 号 量 集 合 上 的 操 作 数 组 int semop(int semid, struct sembuf semoparray[], size_t nops); semoparray 是 一 个 指 针, 它 指 向 一 个 信 号 量 操 作 数 组 nops 规 定 该 数 组 中 操 作 的 数 量 下 面, 我 们 看 一 个 具 体 的 例 子, 它 创 建 一 个 特 定 的 IPC 结 构 的 关 键 字 和 一 个 信 号 量, 建 立 此 信 号 量 的 索 引, 修 改 索 引 指 向 的 信 号 量 的 值, 最 后 我 们 清 除 信 号 量 在 下 面 的 代 码 中, 函 数 ftok 生 成 我 们 上 文 所 说 的 唯 一 的 IPC 关 键 字 #include <stdio.h> #include <sys/types.h> #include <sys/sem.h> #include <sys/ipc.h> void main() { key_t unique_key; // 定 义 一 个 IPC 关 键 字 int id; struct sembuf lock_it; union semun options; int i; unique_key = ftok(".", 'a'); // 生 成 关 键 字, 字 符 'a' 是 一 个 随 机 种 子 // 创 建 一 个 新 的 信 号 量 集 合 id = semget(unique_key, 1, IPC_CREAT IPC_EXCL 0666);

185 printf("semaphore id=%d\n", id); options.val = 1; semctl(id, 0, SETVAL, options); // 设 置 变 量 值 // 设 置 索 引 0 的 信 号 量 // 打 印 出 信 号 量 的 值 i = semctl(id, 0, GETVAL, 0); printf("value of semaphore at index 0 is %d\n", i); // 下 面 重 新 设 置 信 号 量 lock_it.sem_num = 0; // 设 置 哪 个 信 号 量 lock_it.sem_op = -1; // 定 义 操 作 lock_it.sem_flg = IPC_NOWAIT; // 操 作 方 式 if (semop(id, &lock_it, 1) == -1) { printf("can not lock semaphore.\n"); exit(1); } i = semctl(id, 0, GETVAL, 0); printf("value of semaphore at index 0 is %d\n", i); // 清 除 信 号 量 semctl(id, 0, IPC_RMID, 0); } 套 接 口 套 接 口 (socket) 编 程 是 实 现 Linux 系 统 和 其 他 大 多 数 操 作 系 统 中 进 程 间 通 信 的 主 要 方 式 之 一 我 们 熟 知 的 WWW 服 务 FTP 服 务 TELNET 服 务 等 都 是 基 于 套 接 口 编 程 来 实 现 的 除 了 在 异 地 的 计 算 机 进 程 间 以 外, 套 接 口 同 样 适 用 于 本 地 同 一 台 计 算 机 内 部 的 进 程 间 通 信 Linux 的 进 程 和 Win32 的 进 程 / 线 程 比 较 熟 悉 WIN32 编 程 的 人 一 定 知 道,WIN32 的 进 程 管 理 方 式 与 Linux 上 有 着 很 大 区 别, 那 么 Linux 和 WIN32 在 这 里 究 竟 有 着 什 么 区 别 呢? WIN32 里 的 进 程 / 线 程 是 继 承 自 OS/2 的 在 WIN32 里, 进 程 是 指 一 个 程 序, 而 线 程 是 一 个 进 程 里 的 一 个 执 行 线 索 从 核 心 上 讲,WIN32 的 多 进 程 与 Linux 并 无 多 大 的 区 别, 在 WIN32 里 的 线 程 才 相 当 于 Linux 的 进 程, 是 一 个 实 际 正 在 执 行 的 代 码 但 是,WIN32 里 同 一 个 进 程 里 各 个 线 程 之 间 是 共 享 数 据 段 的 这 才 是 与 Linux 的 进 程 最 大 的 不 同 在 WIN32 下, 使 用 CreateThread 函 数 创 建 线 程, 与 Linux 下 创 建 进 程 不 同,WIN32 线 程 不 是 从 创 建 处 开 始 运 行 的, 而 是 由 CreateThread 指 定 一 个 函 数, 线 程 就 从 那 个 函 数 处 开 始 运 行 此 程 序

186 同 前 面 的 UNIX 程 序 一 样, 由 两 个 线 程 各 打 印 1000 条 信 息 threadid 是 子 线 程 的 线 程 号, 另 外, 全 局 变 量 g 是 子 线 程 与 父 线 程 共 享 的, 这 就 是 与 Linux 最 大 的 不 同 之 处 大 家 可 以 看 出,WIN32 的 进 程 / 线 程 要 比 Linux 复 杂, 在 Linux 要 实 现 类 似 WIN32 的 线 程 并 不 难, 只 要 fork 以 后, 让 子 进 程 调 用 ThreadProc 函 数, 并 且 为 全 局 变 量 开 设 共 享 数 据 区 就 行 了, 但 在 WIN32 下 就 无 法 实 现 类 似 fork 的 功 能 了 所 以 现 在 WIN32 下 的 C 语 言 编 译 器 所 提 供 的 库 函 数 虽 然 已 经 能 兼 容 大 多 数 Linux/UNIX 的 库 函 数, 但 却 仍 无 法 实 现 fork 对 于 多 任 务 系 统, 共 享 数 据 区 是 必 要 的, 但 也 是 一 个 容 易 引 起 混 乱 的 问 题, 在 WIN32 下, 一 个 程 序 员 很 容 易 忘 记 线 程 之 间 的 数 据 是 共 享 的 这 一 情 况, 一 个 线 程 修 改 过 一 个 变 量 后, 另 一 个 线 程 却 又 修 改 了 它, 结 果 引 起 程 序 出 问 题 但 在 Linux 下, 由 于 变 量 本 来 并 不 共 享, 而 由 程 序 员 来 显 式 地 指 定 要 共 享 的 数 据, 使 程 序 变 得 更 清 晰 与 安 全 至 于 WIN32 的 进 程 概 念, 其 含 义 则 是 应 用 程 序, 也 就 是 相 当 于 UNIX 下 的 exec 了 Linux 也 有 自 己 的 多 线 程 函 数 pthread, 它 既 不 同 于 Linux 的 进 程, 也 不 同 于 WIN32 下 的 进 程, 关 于 pthread 的 介 绍 请 看 其 线 程 相 关 分 析 与 介 绍 关 键 函 数 分 析 : child = fork(); 创 建 新 进 程, 如 果 返 回 为 0 表 示 子 进 程, 否 则 为 父 进 程 printf("\tchild pid is %d\n", getpid()); printf("\tchild ppid is %d\n", getppid()); getpid 返 回 当 前 进 程 标 识,getppid 返 回 父 进 程 标 识 waitpid 函 数 原 型 : #include<sys/types.h> #include<sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options); 从 本 质 上 讲, 系 统 调 用 waitpid 和 wait 的 作 用 是 完 全 相 同 的, 但 waitpid 多 出 了 两 个 可 由 用 户 控 制 的 参 数 pid 和 options, 从 而 为 我 们 编 程 提 供 了 另 一 种 更 灵 活 的 方 式 下 面 我 们 就 来 详 细 介 绍 一 下 这 两 个 参 数 : pid 从 参 数 的 名 字 pid 和 类 型 pid_t 中 就 可 以 看 出, 这 里 需 要 的 是 一 个 进 程 ID 但 当 pid 取 不 同 的 值 时, 在 这 里 有 不 同 的 意 义 1)pid>0 时, 只 等 待 进 程 ID 等 于 pid 的 子 进 程, 不 管 其 它 已 经 有 多 少 子 进 程 运 行 结 束 退 出 了, 只 要 指 定 的 子 进 程 还 没 有 结 束,waitpid 就 会 一 直 等 下 去 2)pid=-1 时, 等 待 任 何 一 个 子 进 程 退 出, 没 有 任 何 限 制, 此 时 waitpid 和 wait 的 作 用 一 模 一 样 3)pid=0 时, 等 待 同 一 个 进 程 组 中 的 任 何 子 进 程, 如 果 子 进 程 已 经 加 入 了 别 的 进 程 组,waitpid 不 会 对 它 做 任 何 理 睬

187 4)pid<-1 时, 等 待 一 个 指 定 进 程 组 中 的 任 何 子 进 程, 这 个 进 程 组 的 ID 等 于 pid 的 绝 对 值 options options 提 供 了 一 些 额 外 的 选 项 来 控 制 waitpid, 目 前 在 Linux 中 只 支 持 WNOHANG 和 WUNTRACED 两 个 选 项, 这 是 两 个 常 数, 可 以 用 运 算 符 把 它 们 连 接 起 来 使 用, 比 如 : ret=waitpid(-1,null,wnohang WUNTRACED); 如 果 我 们 不 想 使 用 它 们, 也 可 以 把 options 设 为 0, 如 : ret=waitpid(-1,null,0); 如 果 使 用 了 WNOHANG 参 数 调 用 waitpid, 即 使 没 有 子 进 程 退 出, 它 也 会 立 即 返 回, 不 会 像 wait 那 样 永 远 等 下 去 waitpid 的 返 回 值 比 wait 稍 微 复 杂 一 些, 一 共 有 3 种 情 况 : 1) 当 正 常 返 回 的 时 候,waitpid 返 回 收 集 到 的 子 进 程 的 进 程 ID; 2) 如 果 设 置 了 选 项 WNOHANG, 而 调 用 中 waitpid 发 现 没 有 已 退 出 的 子 进 程 可 收 集, 返 回 0; 3) 如 果 调 用 中 出 错, 则 返 回 -1, 这 时 errno 会 被 设 置 成 相 应 的 值 以 指 示 错 误 所 在 当 pid 所 指 示 的 子 进 程 不 存 在, 或 此 进 程 存 在, 但 不 是 调 用 进 程 的 子 进 程,waitpid 就 会 出 错 返 回, 这 时 errno 被 设 置 为 ECHILD 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 12 章 /12.3-process 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 process 程 序 : $ cd /usr/local/src/s210x/project/12.3-process $ arm-none-linux-gnueabi-gcc -o process process.c $ cp process /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为

188 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 process 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./process -l./process 5) 给 process 添 加 可 执 行 权 限 : # chmod 777 process 6) 运 行 process: #./process Try to create new process. This is child. child pid is 156 child ppid is 155 This is parent. parent pid is 155 parent ppid is 82 child exited with 线 程 控 制 实 验 实 验 目 的 掌 握 pthread_create() 函 数 的 使 用 以 及 linux 中 线 程 的 基 本 编 程 ; 理 解 线 程 之 间 的 同 步 与 互 斥 以 及 线 程 属 性 的 含 义 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统

189 实 验 原 理 Linux 线 程 基 础 知 识 线 程 (thread) 技 术 早 在 60 年 代 就 被 提 出, 但 真 正 应 用 多 线 程 到 操 作 系 统 中 去, 是 在 80 年 代 中 期,solaris 是 这 方 面 的 佼 佼 者 传 统 的 Unix 也 支 持 线 程 的 概 念, 但 是 在 一 个 进 程 (process) 中 只 允 许 有 一 个 线 程, 这 样 多 线 程 就 意 味 着 多 进 程 现 在, 多 线 程 技 术 已 经 被 许 多 操 作 系 统 所 支 持, 包 括 Windows/NT, 当 然, 也 包 括 Linux 为 什 么 有 了 进 程 的 概 念 后, 还 要 再 引 入 线 程 呢? 使 用 多 线 程 到 底 有 哪 些 好 处? 什 么 样 的 系 统 应 该 选 用 多 线 程? 我 们 首 先 必 须 回 答 这 些 问 题 使 用 多 线 程 的 理 由 之 一 是 和 进 程 相 比, 它 是 一 种 非 常 节 俭 的 多 任 务 操 作 方 式 我 们 知 道, 在 Linux 系 统 下, 启 动 一 个 新 的 进 程 必 须 分 配 给 它 独 立 的 地 址 空 间, 建 立 众 多 的 数 据 表 来 维 护 它 的 代 码 段 堆 栈 段 和 数 据 段, 这 是 一 种 昂 贵 的 多 任 务 工 作 方 式 而 运 行 于 一 个 进 程 中 的 多 个 线 程, 它 们 彼 此 之 间 使 用 相 同 的 地 址 空 间, 共 享 大 部 分 数 据, 启 动 一 个 线 程 所 花 费 的 空 间 远 远 小 于 启 动 一 个 进 程 所 花 费 的 空 间, 而 且, 线 程 间 彼 此 切 换 所 需 的 时 间 也 远 远 小 于 进 程 间 切 换 所 需 要 的 时 间 据 统 计, 总 的 说 来, 一 个 进 程 的 开 销 大 约 是 一 个 线 程 开 销 的 30 倍 左 右, 当 然, 在 具 体 的 系 统 上, 这 个 数 据 可 能 会 有 较 大 的 区 别 使 用 多 线 程 的 理 由 之 二 是 线 程 间 方 便 的 通 信 机 制 对 不 同 进 程 来 说, 它 们 具 有 独 立 的 数 据 空 间, 要 进 行 数 据 的 传 递 只 能 通 过 通 信 的 方 式 进 行, 这 种 方 式 不 仅 费 时, 而 且 很 不 方 便 线 程 则 不 然, 由 于 同 一 进 程 下 的 线 程 之 间 共 享 数 据 空 间, 所 以 一 个 线 程 的 数 据 可 以 直 接 为 其 它 线 程 所 用, 这 不 仅 快 捷, 而 且 方 便 当 然, 数 据 的 共 享 也 带 来 其 他 一 些 问 题, 有 的 变 量 不 能 同 时 被 两 个 线 程 所 修 改, 有 的 子 程 序 中 声 明 为 static 的 数 据 更 有 可 能 给 多 线 程 程 序 带 来 灾 难 性 的 打 击, 这 些 正 是 编 写 多 线 程 程 序 时 最 需 要 注 意 的 地 方 除 了 以 上 所 说 的 优 点 外, 不 和 进 程 比 较, 多 线 程 程 序 作 为 一 种 多 任 务 并 发 的 工 作 方 式, 当 然 有 以 下 的 优 点 : 1) 提 高 应 用 程 序 响 应 这 对 图 形 界 面 的 程 序 尤 其 有 意 义, 当 一 个 操 作 耗 时 很 长 时, 整 个 系 统 都 会 等 待 这 个 操 作, 此 时 程 序 不 会 响 应 键 盘 鼠 标 菜 单 的 操 作, 而 使 用 多 线 程 技 术, 将 耗 时 长 的 操 作 (time consuming) 置 于 一 个 新 的 线 程, 可 以 避 免 这 种 尴 尬 的 情 况 2) 使 多 CPU 系 统 更 加 有 效 操 作 系 统 会 保 证 当 线 程 数 不 大 于 CPU 数 目 时, 不 同 的 线 程 运 行 于 不 同 的 CPU 上 3) 改 善 程 序 结 构 一 个 既 长 又 复 杂 的 进 程 可 以 考 虑 分 为 多 个 线 程, 成 为 几 个 独 立 或 半 独 立 的 运 行 部 分, 这 样 的 程 序 会 利 于 理 解 和 修 改 下 面 我 们 先 来 尝 试 编 写 一 个 简 单 的 多 线 程 程 序 Linux 系 统 下 的 多 线 程 遵 循 POSIX 线 程 接 口, 称 为 pthread 编 写 Linux 下 的 多 线 程 程 序, 需

190 要 使 用 头 文 件 pthread.h, 连 接 时 需 要 使 用 库 libpthread.a 顺 便 说 一 下,Linux 下 pthread 的 实 现 是 通 过 系 统 调 用 clone() 来 实 现 的 clone() 是 Linux 所 特 有 的 系 统 调 用, 它 的 使 用 方 式 类 似 fork, 关 于 clone() 的 详 细 情 况, 有 兴 趣 的 读 者 可 以 去 查 看 有 关 文 档 说 明 下 面 我 们 展 示 一 个 最 简 单 的 多 线 程 程 序 example.c #include <stdio.h> #include <pthread.h> void thread(void) { int i; for(i=0;i<3;i++) printf("this is a pthread.\n"); } int main(void) { pthread_t id; int i,ret; ret=pthread_create(&id,null,(void *) thread,null); if(ret!=0) { printf ("Create pthread error!\n"); exit (1); } for(i=0;i<3;i++) printf("this is the main process.\n"); pthread_join(id,null); return (0); } 我 们 编 译 此 程 序 : $ gcc example.c -lpthread -o example 运 行 example, 我 们 得 到 如 下 结 果 : This is the main process. This is a pthread. This is the main process. This is the main process. This is a pthread. This is a pthread. 再 次 运 行, 我 们 可 能 得 到 如 下 结 果 : This is a pthread

191 This is the main process. This is a pthread. This is the main process. This is a pthread. This is the main process. 前 后 两 次 结 果 不 一 样, 这 是 两 个 线 程 争 夺 CPU 资 源 的 结 果 上 面 的 示 例 中, 我 们 使 用 到 了 两 个 函 数,pthread_create 和 pthread_join, 并 声 明 了 一 个 pthread_t 型 的 变 量 pthread_t 在 头 文 件 /usr/include/bits/pthreadtypes.h 中 定 义 : typedef unsigned long int pthread_t; 它 是 一 个 线 程 的 标 识 符 函 数 pthread_create 用 来 创 建 一 个 线 程, 它 的 原 型 为 : extern int pthread_create P ((pthread_t * thread, const pthread_attr_t * attr, void *(* start_routine) (void *), void * arg)); 第 一 个 参 数 为 指 向 线 程 标 识 符 的 指 针, 第 二 个 参 数 用 来 设 置 线 程 属 性, 第 三 个 参 数 是 线 程 运 行 函 数 的 起 始 地 址, 最 后 一 个 参 数 是 运 行 函 数 的 参 数 这 里, 我 们 的 函 数 thread 不 需 要 参 数, 所 以 最 后 一 个 参 数 设 为 空 指 针 第 二 个 参 数 我 们 也 设 为 空 指 针, 这 样 将 生 成 默 认 属 性 的 线 程 当 创 建 线 程 成 功 时, 函 数 返 回 0, 若 不 为 0 则 说 明 创 建 线 程 失 败, 常 见 的 错 误 返 回 代 码 为 EAGAIN 和 EINVAL 前 者 表 示 系 统 限 制 创 建 新 的 线 程, 例 如 线 程 数 目 过 多 了 ; 后 者 表 示 第 二 个 参 数 代 表 的 线 程 属 性 值 非 法 创 建 线 程 成 功 后, 新 创 建 的 线 程 则 运 行 参 数 三 和 参 数 四 确 定 的 函 数, 原 来 的 线 程 则 继 续 运 行 下 一 行 代 码 下 面 介 绍 线 程 创 建 属 性 : pthread_create() 中 的 attr 参 数 是 一 个 结 构 指 针, 结 构 中 的 元 素 分 别 对 应 着 新 线 程 的 运 行 属 性 如 果 创 建 线 程 时 使 用 该 参 数, 则 必 须 先 初 始 化 该 参 数 pthread_attr_init(&attr); 然 后 再 设 置 参 数 中 各 元 素 该 结 构 中 定 义 在 /usr/include/bits/pthreadtypes.h 中 : typedef struct pthread_attr_s { int detachstate; int schedpolicy; struct sched_param schedparam; int inheritsched; int scope; size_t guardsize; int stackaddr_set; void * stackaddr; size_t stacksize; } pthread_attr_t; 其 中 各 元 素 含 义 : detachstate, 表 示 新 线 程 是 否 与 进 程 中 其 他 线 程 脱 离 同 步, 如 果 置 位 则 新 线 程 不 能 用

192 pthread_join() 来 同 步, 且 在 退 出 时 自 行 释 放 所 占 用 的 资 源 缺 省 为 PTHREAD_CREATE_JOINABLE 状 态 这 个 属 性 也 可 以 在 线 程 创 建 并 运 行 以 后 用 pthread_detach() 来 设 置, 而 一 旦 设 置 为 PTHREAD_CREATE_DETACH 状 态 ( 不 论 是 创 建 时 设 置 还 是 运 行 时 设 置 ) 则 不 能 再 恢 复 到 PTHREAD_CREATE_JOINABLE 状 态 该 参 数 涉 及 函 数 : int pthread_attr_setdetachstate (pthread_attr_t * attr,int detachstate); int pthread_attr_getdetachstate ( const pthread_attr_t * attr,int * detachstate); detachstate 可 取 值 :PTHREAD_CREATE_JOINABLE, PTHREAD_CREATE_DETACH schedpolicy, 表 示 新 线 程 的 调 度 策 略, 主 要 包 括 SCHED_OTHER( 正 常 非 实 时 ) SCHED_RR( 实 时 轮 转 法 ) 和 SCHED_FIFO( 实 时 先 入 先 出 ) 三 种, 缺 省 为 SCHED_OTHER, 后 两 种 调 度 策 略 仅 对 超 级 用 户 有 效 运 行 时 可 以 用 过 pthread_setschedparam() 来 改 变 该 参 数 涉 及 函 数 : int pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy); int pthread_attr_getschedpolicy ( const pthread_attr_t * restrict attr, int * restrict policy); schedparam, 一 个 struct sched_param 结 构, 其 中 有 一 个 sched_priority 整 型 变 量 表 示 线 程 的 运 行 优 先 级 这 个 参 数 仅 当 调 度 策 略 为 实 时 ( 即 SCHED_RR 或 SCHED_FIFO) 时 才 有 效, 并 可 以 在 运 行 时 通 过 pthread_setschedparam() 函 数 来 改 变, 缺 省 为 0 该 参 数 涉 及 函 数 : nt pthread_attr_setschedparam (pthread_attr_t * restrict attr, const struct sched_param * restrict param); int pthread_attr_getschedparam ( const pthread_attr_t * restrict attr,struct sched_param * restrict param); inheritsched, 有 两 种 值 可 供 选 择 : PTHREAD_EXPLICIT_SCHED 和 PTHREAD_INHERIT_SCHED, 前 者 表 示 新 线 程 使 用 显 式 指 定 调 度 策 略 和 调 度 参 数 ( 即 attr 中 的 值 ), 而 后 者 表 示 继 承 调 用 者 线 程 的 值 缺 省 为 PTHREAD_EXPLICIT_SCHED int pthread_attr_setinheritsched (pthread_attr_t * attr,int inherit); int pthread_attr_getinheritsched ( const pthread_attr_t * restrict attr, int * restrict inherit); scope, 表 示 线 程 间 竞 争 CPU 的 范 围, 也 就 是 说 线 程 优 先 级 的 有 效 范 围 POSIX 的 标 准 中 定 义 了 两 个 值 :PTHREAD_SCOPE_SYSTEM 和 PTHREAD_SCOPE_PROCESS, 前 者 表 示 与 系 统 中 所 有 线 程 一 起 竞 争 CPU 时 间, 后 者 表 示 仅 与 同 进 程 中 的 线 程 竞 争 CPU 该 参 数 涉 及 函 数 : int pthread_attr_setscope (pthread_attr_t * attr, int scope); int pthread_attr_getscope ( const pthread_attr_t * restrict attr,int * restrict scope); pthread_attr_t 结 构 中 还 有 一 些 值, 但 不 使 用 pthread_create() 来 设 置 函 数 pthread_join 用 来 等 待 一 个 线 程 的 结 束 函 数 原 型 为 : extern int pthread_join P ((pthread_t th, void ** thread_return)); 第 一 个 参 数 为 被 等 待 的 线 程 标 识 符, 第 二 个 参 数 为 一 个 用 户 定 义 的 指 针, 它 可 以 用 来 存 储 被 等

193 待 线 程 的 返 回 值 这 个 函 数 是 一 个 线 程 阻 塞 的 函 数, 调 用 它 的 函 数 将 一 直 等 待 到 被 等 待 的 线 程 结 束 为 止, 当 函 数 返 回 时, 被 等 待 线 程 的 资 源 被 收 回 一 个 线 程 的 结 束 有 两 种 途 径, 一 种 是 象 我 们 上 面 的 例 子 一 样, 函 数 结 束 了, 调 用 它 的 线 程 也 就 结 束 了 ; 另 一 种 方 式 是 通 过 函 数 pthread_exit 来 实 现 它 的 函 数 原 型 为 : extern void pthread_exit P ((void * retval)) attribute (( noreturn )); 唯 一 的 参 数 是 函 数 的 返 回 代 码, 只 要 pthread_join 中 的 第 二 个 参 数 thread_return 不 是 NULL, 这 个 值 将 被 传 递 给 thread_return 最 后 要 说 明 的 是, 一 个 线 程 不 能 被 多 个 线 程 等 待, 否 则 第 一 个 接 收 到 信 号 的 线 程 成 功 返 回, 其 余 调 用 pthread_join 的 线 程 则 返 回 错 误 代 码 ESRCH 关 键 函 数 分 析 result = pthread_create(&thread1, PTHREAD_CREATE_JOINABLE, (void *)task1, (void *)&t1); 创 建 新 线 程, 其 中 参 数 thread1 为 线 程 标 识 号,PTHREAD_CREATE_JOINABLE 为 线 程 属 性, task1 为 函 数 名,t1 传 递 参 数 pthread_join(thread1, (void *)&rt1); 函 数 pthread_join 用 来 等 待 一 个 线 程 的 结 束, 参 数 thread1 为 线 程 标 识, 表 示 等 待 这 个 线 程 结 束,rt1 用 来 保 存 被 等 待 线 程 的 返 回 值 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.4-thread 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 thread 程 序 : $ cd /usr/local/src/s210x/project/12.4-thread $ arm-none-linux-gnueabi-gcc -o thread thread.c -lpthread $ cp thread /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为

194 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 thread 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./thread -l./thread 5) 给 thread 添 加 可 执 行 权 限 : # chmod 777 thread 6) 运 行 thread: #./thread task1 cnt = 1. task2 cnt = 1. task1 cnt = 2. task1 cnt = 3. task2 cnt = 2. task1 cnt = 4. task1 cnt = 5. task2 cnt = 3. task2 cnt = 4. task2 cnt = 5. total 10 times. return value of task1: 5. return value of task2: 计 时 器 实 验 实 验 目 的 掌 握 linux 下 的 计 时 器 编 程 方 法 ; 掌 握 linux 下 的 常 用 时 间 函 数 编 程 方 法 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ;

195 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 在 程 序 当 中, 我 们 经 常 要 输 出 系 统 当 前 的 时 间, 比 如 我 们 使 用 date 命 令 的 输 出 结 果 这 个 时 候 我 们 可 以 使 用 下 面 两 个 函 数 : #include <sys/time.h> time_t time(time_t *tloc); char *ctime(const time_t *clock); time 函 数 返 回 从 1970 年 1 月 1 日 0 点 以 来 的 秒 数 存 储 在 time_t 结 构 之 中 不 过 这 个 函 数 的 返 回 值 对 于 我 们 来 说 没 有 什 么 实 际 意 义 这 个 时 候 我 们 使 用 第 二 个 函 数 将 秒 数 转 化 为 字 符 串 这 个 函 数 的 返 回 类 型 是 固 定 的 : 一 个 可 能 值 为 Thu Dec 7 14:58: , 这 个 字 符 串 的 长 度 是 固 定 的 为 26 有 时 候 我 们 要 计 算 程 序 执 行 的 时 间, 比 如 我 们 要 对 算 法 进 行 时 间 分 析 这 个 时 候 可 以 使 用 下 面 这 些 函 数 : void init_time(void) 该 函 数 设 定 间 歇 计 时 器 的 值 系 统 为 进 程 提 供 三 种 类 型 的 计 时 器, 每 一 类 以 不 同 的 时 间 域 递 减 其 值 当 计 时 器 超 时, 信 号 被 发 送 到 进 程, 之 后 计 时 器 重 新 启 动 // 初 始 化 定 时 器 void init_time(void) { struct itimerval val; val.it_value.tv_sec = 1; val.it_value.tv_usec = 0; val.it_interval = val.it_value; setitimer(itimer_prof, &val, NULL); } itimerval 结 构 体 struct itimerval { struct timeval it_interval; // 计 时 器 重 启 动 的 间 歇 值 struct timeval it_value; // 计 时 器 安 装 后 首 先 启 动 的 初 始 值 }; struct timeval { time_t tv_sec; // 秒

196 suseconds_t tv_usec; // 微 秒 }; int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); which: 间 歇 计 时 器 类 型, 有 三 种 选 择 : ITIMER_REAL: 数 值 为 0, 计 时 器 的 值 实 时 递 减, 发 送 的 信 号 是 SIGALRM ITIMER_VIRTUAL: 数 值 为 1, 进 程 执 行 时 递 减 计 时 器 的 值, 发 送 的 信 号 是 SIGVTALRM ITIMER_PROF: 数 值 为 2, 进 程 和 系 统 执 行 时 都 递 减 计 时 器 的 值, 发 送 的 信 号 是 SIGPROF value: 指 向 的 结 构 体 设 为 计 时 器 的 当 前 值 ovalue: 如 果 不 是 NULL, 将 返 回 计 时 器 的 原 有 值 void init_sigaction(void) 该 函 数 用 作 检 查 / 修 改 与 指 定 信 号 相 关 联 的 处 理 动 作 : // 初 始 化 sigaction void init_sigaction(void) { struct sigaction act; act.sa_handler = timeout_info; act.sa_flags = 0; } sigemptyset(&act.sa_mask); // 将 信 号 集 合 设 置 为 空 sigaction(sigprof, &act, NULL); // 检 查 / 修 改 与 指 定 信 号 相 关 联 的 处 理 动 作 sigaction 结 构 体 struct sigaction { sighandler_t sa_handler; // 一 个 带 有 int 参 数 的 函 数 指 针, 或 者 SIG_IGN( 忽 略 ), 或 者 SIG_DFL( 默 认 ). unsigned long sa_flags; // 信 号 操 作 sigset_t sa_mask; // 信 号 屏 蔽 字 ( 集 ). 当 该 信 号 处 理 函 数 返 回 时, 屏 蔽 字 恢 复 }; int sigemptyset (sigset_t *set); 函 数 初 始 化 信 号 集 合 set, 将 set 设 置 为 空 int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact); 函 数 原 型 : #include <signal.h> int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact); 成 功 则 返 回 0, 出 错 则 返 回

197 void timeout_info(int signo) void timeout_info(int signo) { if(limit == 0) { printf("sorry, time limit reached.\n"); exit(0); } printf("only %d senconds left.\n", limit--); } 用 于 处 理 计 时 器 到 时 的 操 作 通 过 结 构 体 &act 被 调 用 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 12 章 /12.5-timer 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 timer 程 序 : $ cd /usr/local/src/s210x/project/12.5-timer $ arm-none-linux-gnueabi-gcc -o timer timer.c $ cp timer /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 timer 下 载 到 s210x 实 验 平 台 : # cd /home/app

198 # tftp -g r./timer -l./timer 5) 给 timer 添 加 可 执 行 权 限 : # chmod 777 timer 6) 运 行 timer: #./timer You have only 10 seconds for thinking. only 10 senconds left. only 9 senconds left. only 8 senconds left. only 7 senconds left. only 6 senconds left. only 5 senconds left. only 4 senconds left. only 3 senconds left. only 2 senconds left. only 1 senconds left. Sorry, time limit reached TCP 实 验 实 验 目 的 理 解 linux 中 TCP 的 通 信 过 程 以 及 实 现 方 法 ; 掌 握 linux 下 socket() 函 数 在 TCP 通 信 中 的 使 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 TCP 基 础 知 识 TCP 是 Transmission Control Protocol 的 简 写, 中 文 译 名 为 传 输 控 制 协 议 TCP 和 UDP 处

199 在 同 一 层 运 输 层, 但 是 TCP 和 UDP 最 不 同 的 地 方 是,TCP 提 供 了 一 种 可 靠 的 数 据 传 输 服 务, TCP 是 面 向 连 接 的, 也 就 是 说, 利 用 TCP 通 信 的 两 台 主 机 首 先 要 经 历 一 个 拨 打 电 话 的 过 程, 等 到 通 信 准 备 结 束 才 开 始 传 输 数 据, 最 后 结 束 通 话 所 以 TCP 要 比 UDP 可 靠 的 多,UDP 是 把 数 据 直 接 发 出 去, 而 不 管 对 方 是 不 是 在 收 信, 就 算 是 UDP 无 法 送 达, 也 不 会 产 生 ICMP 差 错 报 文 TCP 保 证 可 靠 性 的 简 单 工 作 原 理 如 下 : 应 用 数 据 被 分 割 成 TCP 认 为 最 适 合 发 送 的 数 据 块 这 和 UDP 完 全 不 同, 应 用 程 序 产 生 的 数 据 报 长 度 将 保 持 不 变 由 TCP 传 递 给 IP 的 信 息 单 位 称 为 报 文 段 或 段 (segment) 当 TCP 发 出 一 个 段 后, 它 启 动 一 个 定 时 器, 等 待 目 的 端 确 认 收 到 这 个 报 文 段 如 果 不 能 及 时 收 到 一 个 确 认, 将 重 发 这 个 报 文 段 当 TCP 收 到 发 自 TCP 连 接 另 一 端 的 数 据, 它 将 发 送 一 个 确 认 这 个 确 认 不 是 立 即 发 送, 通 常 将 推 迟 一 段 时 间 TCP 将 保 持 它 首 部 和 数 据 的 检 验 和 这 是 一 个 端 到 端 的 检 验 和, 目 的 是 检 测 数 据 在 传 输 过 程 中 的 任 何 变 化 如 果 收 到 段 的 检 验 和 有 差 错,TCP 将 丢 弃 这 个 报 文 段 和 不 确 认 收 到 此 报 文 段 ( 希 望 发 端 超 时 并 重 发 ) 既 然 TCP 报 文 段 作 为 IP 数 据 报 来 传 输, 而 IP 数 据 报 的 到 达 可 能 会 失 序, 因 此 TCP 报 文 段 的 到 达 也 可 能 会 失 序 如 果 必 要,TCP 将 对 收 到 的 数 据 进 行 重 新 排 序, 将 收 到 的 数 据 以 正 确 的 顺 序 交 给 应 用 层 TCP 还 能 提 供 流 量 控 制 TCP 连 接 的 每 一 方 都 有 固 定 大 小 的 缓 冲 空 间 TCP 的 接 收 端 只 允 许 另 一 端 发 送 接 收 端 缓 冲 区 所 能 接 纳 的 数 据 这 将 防 止 较 快 主 机 致 使 较 慢 主 机 的 缓 冲 区 溢 出 从 这 段 话 中 可 以 看 到,TCP 中 保 持 可 靠 性 的 方 式 就 是 超 时 重 发, 这 是 有 道 理 的, 虽 然 TCP 也 可 以 用 各 种 各 样 的 ICMP 报 文 来 处 理 这 些, 但 是 这 也 不 是 可 靠 的, 最 可 靠 的 方 式 就 是 只 要 不 得 到 确 认, 就 重 新 发 送 数 据 报, 直 到 得 到 对 方 的 确 认 为 止 TCP 的 首 部 和 UDP 首 部 一 样, 都 有 发 送 端 口 号 和 接 收 端 口 号 但 是 显 然,TCP 的 首 部 信 息 要 比 UDP 的 多, 可 以 看 到,TCP 协 议 提 供 了 发 送 和 确 认 所 需 要 的 所 有 必 要 的 信 息 可 以 想 象 一 个 TCP 数 据 的 发 送 应 该 是 如 下 的 一 个 过 程 双 方 建 立 连 接 发 送 方 给 接 收 方 TCP 数 据 报, 然 后 等 待 对 方 的 确 认 TCP 数 据 报, 如 果 没 有, 就 重 新 发, 如 果 有, 就 发 送 下 一 个 数 据 报 接 收 方 等 待 发 送 方 的 数 据 报, 如 果 得 到 数 据 报 并 检 验 无 误, 就 发 送 ACK( 确 认 ) 数 据 报, 并 等 待 下 一 个 TCP 数 据 报 的 到 来 直 到 接 收 到 FIN( 发 送 完 成 数 据 报 ) 中 止 连 接 可 以 想 见, 为 了 建 立 一 个 TCP 连 接, 系 统 可 能 会 建 立 一 个 新 的 进 程 来 进 行 数 据 的 传 送 目 前 建 立 在 TCP 协 议 上 的 网 络 协 议 特 别 多, 有 telnet,ssh, 有 ftp, 有 http 等 等 这 些 协 议 又 可 以 根 据 数 据 吞 吐 量 来 大 致 分 成 两 大 类 :(1) 交 互 数 据 类 型, 例 如 telnet,ssh, 这 种 类 型 的 协 议 在

200 大 多 数 情 况 下 只 是 做 小 流 量 的 数 据 交 换, 比 如 说 按 一 下 键 盘, 回 显 一 些 文 字 等 等 (2) 数 据 成 块 类 型, 例 如 ftp, 这 种 类 型 的 协 议 要 求 TCP 能 尽 量 的 运 载 数 据, 把 数 据 的 吞 吐 量 做 到 最 大, 并 尽 可 能 的 提 高 效 率 针 对 这 两 种 情 况,TCP 给 出 了 两 种 不 同 的 策 略 来 进 行 数 据 传 输 1)TCP 的 交 互 数 据 流 对 于 交 互 性 要 求 比 较 高 的 应 用,TCP 给 出 两 个 策 略 来 提 高 发 送 效 率 和 减 低 网 络 负 担 :(1) 捎 带 ACK (2)Nagle 算 法 ( 一 次 尽 量 多 的 发 数 据 ) 通 常, 在 网 络 速 度 很 快 的 情 况 下, 比 如 用 IO 接 口 进 行 telnet 通 信, 当 按 下 字 母 键 并 要 求 回 显 的 时 候, 客 户 端 和 服 务 器 将 经 历 发 送 按 键 数 据 -> 服 务 器 发 送 按 键 数 据 的 ack-> 服 务 器 端 发 送 回 显 数 据 -> 客 户 端 发 送 回 显 数 据 的 ACK 的 过 程, 而 其 中 的 数 据 流 量 将 是 40bit + 41bit+41bit+40bit = 162bit, 如 果 在 广 域 网 里 面, 这 种 小 分 组 的 TCP 流 量 将 会 造 成 很 大 的 网 络 负 担 捎 带 ACK 的 发 送 方 式 这 个 策 略 是 说, 当 主 机 收 到 远 程 主 机 的 TCP 数 据 报 之 后, 通 常 不 马 上 发 送 ACK 数 据 报, 而 是 等 上 一 个 短 暂 的 时 间, 如 果 这 段 时 间 里 面 主 机 还 有 发 送 到 远 程 主 机 的 TCP 数 据 报, 那 么 就 把 这 个 ACK 数 据 报 捎 带 着 发 送 出 去, 把 本 来 两 个 TCP 数 据 报 整 合 成 一 个 发 送 一 般 的, 这 个 时 间 是 200ms 可 以 明 显 地 看 到 这 个 策 略 可 以 把 TCP 数 据 报 的 利 用 率 提 高 很 多 Nagle 算 法 上 过 bbs 的 人 应 该 都 会 有 感 受, 就 是 在 网 络 慢 的 时 候 发 贴, 有 时 键 入 一 串 字 符 串 以 后, 经 过 一 段 时 间, 客 户 端 发 疯 一 样 突 然 回 显 出 很 多 内 容, 就 好 像 数 据 一 下 子 传 过 来 了 一 样, 这 就 是 Nagle 算 法 的 作 用 Nagle 算 法 是 说, 当 主 机 A 给 主 机 B 发 送 了 一 个 TCP 数 据 报 并 进 入 等 待 主 机 B 的 ACK 数 据 报 的 状 态 时,TCP 的 输 出 缓 冲 区 里 面 只 能 有 一 个 TCP 数 据 报, 并 且, 这 个 数 据 报 不 断 地 收 集 后 来 的 数 据, 整 合 成 一 个 大 的 数 据 报, 等 到 B 主 机 的 ACK 包 一 到, 就 把 这 些 数 据 一 股 脑 的 发 送 出 去 虽 然 这 样 的 描 述 有 些 不 准 确, 但 还 算 形 象 和 易 于 理 解, 我 们 同 样 可 以 体 会 到 这 个 策 略 对 于 减 低 网 络 负 担 的 好 处 在 编 写 插 口 程 序 的 时 候, 可 以 通 过 TCP_NODELAY 来 关 闭 这 个 算 法 并 且, 使 用 这 个 算 法 看 情 况 的, 比 如 基 于 TCP 的 X 窗 口 协 议, 如 果 处 理 鼠 标 事 件 时 还 是 用 这 个 算 法, 那 么 延 迟 可 就 非 常 大 了 2)TCP 的 成 块 数 据 流 对 于 FTP 这 样 对 于 数 据 吞 吐 量 有 较 高 要 求 的 要 求, 将 总 是 希 望 每 次 尽 量 多 的 发 送 数 据 到 对 方 主 机, 就 算 是 有 点 延 迟 也 无 所 谓 TCP 也 提 供 了 一 整 套 的 策 略 来 支 持 这 样 的 需 求 TCP 协 议 中 有 16 个 bit 表 示 窗 口 的 大 小, 这 是 这 些 策 略 的 核 心 3) 传 输 数 据 时 ACK 的 问 题 在 解 释 滑 动 窗 口 前, 需 要 看 看 ACK 的 应 答 策 略, 一 般 来 说, 发 送 端 发 送 一 个 TCP 数 据 报, 那

201 么 接 收 端 就 应 该 发 送 一 个 ACK 数 据 报 但 是 事 实 上 却 不 是 这 样, 发 送 端 将 会 连 续 发 送 数 据 尽 量 填 满 接 收 方 的 缓 冲 区, 而 接 收 方 对 这 些 数 据 只 要 发 送 一 个 ACK 报 文 来 回 应 就 可 以 了, 这 就 是 ACK 的 累 积 特 性, 这 个 特 性 大 大 减 少 了 发 送 端 和 接 收 端 的 负 担 4) 滑 动 窗 口 滑 动 窗 口 本 质 上 是 描 述 接 收 方 的 TCP 数 据 报 缓 冲 区 大 小 的 数 据, 发 送 方 根 据 这 个 数 据 来 计 算 自 己 最 多 能 发 送 多 长 的 数 据 如 果 发 送 方 收 到 接 收 方 的 窗 口 大 小 为 0 的 TCP 数 据 报, 那 么 发 送 方 将 停 止 发 送 数 据, 等 到 接 收 方 发 送 窗 口 大 小 不 为 0 的 数 据 报 的 到 来 TCP 就 是 用 这 个 窗 口, 慢 慢 的 从 数 据 的 左 边 移 动 到 右 边, 把 处 于 窗 口 范 围 内 的 数 据 发 送 出 去 ( 但 不 用 发 送 所 有, 只 是 处 于 窗 口 内 的 数 据 可 以 发 送 ) 这 就 是 窗 口 的 意 义 窗 口 的 大 小 是 可 以 通 过 socket 来 制 定 的,4096 并 不 是 最 理 想 的 窗 口 大 小, 而 则 可 以 使 吞 吐 量 大 大 的 增 加 5) 数 据 拥 塞 上 面 的 策 略 用 于 局 域 网 内 传 输 还 可 以, 但 是 用 在 广 域 网 中 就 可 能 会 出 现 问 题, 最 大 的 问 题 就 是 当 传 输 时 出 现 了 瓶 颈 ( 比 如 说 一 定 要 经 过 一 个 slip 低 速 链 路 ) 所 产 生 的 大 量 数 据 堵 塞 问 题 ( 拥 塞 ), 为 了 解 决 这 个 问 题,TCP 发 送 方 需 要 确 认 连 接 双 方 的 线 路 的 数 据 最 大 吞 吐 量 是 多 少 这 就 是 所 谓 的 拥 塞 窗 口 拥 塞 窗 口 的 原 理 很 简 单,TCP 发 送 方 首 先 发 送 一 个 数 据 报, 然 后 等 待 对 方 的 回 应, 得 到 回 应 后 就 把 这 个 窗 口 的 大 小 加 倍, 然 后 连 续 发 送 两 个 数 据 报, 等 到 对 方 回 应 以 后, 再 把 这 个 窗 口 加 倍 ( 先 是 2 的 指 数 倍, 到 一 定 程 度 后 就 变 成 线 性 增 长, 这 就 是 所 谓 的 慢 启 动 ), 发 送 更 多 的 数 据 报, 直 到 出 现 超 时 错 误, 这 样, 发 送 端 就 了 解 到 了 通 信 双 方 的 线 路 承 载 能 力, 也 就 确 定 了 拥 塞 窗 口 的 大 小, 发 送 方 就 用 这 个 拥 塞 窗 口 的 大 小 发 送 数 据 要 观 察 这 个 现 象 是 非 常 容 易 的, 我 们 一 般 在 下 载 数 据 的 时 候, 速 度 都 是 慢 慢 冲 起 来 的 关 键 函 数 分 析 该 例 程 是 基 于 Linux 下 socket 编 程, 所 以 有 必 要 先 介 绍 一 下 socket 的 相 关 知 识 1) 什 么 是 Socket Socket 接 口 是 TCP/IP 网 络 的 API,Socket 接 口 定 义 了 许 多 函 数 或 例 程, 程 序 员 可 以 用 它 们 来 开 发 TCP/IP 网 络 上 的 应 用 程 序 要 学 Internet 上 的 TCP/IP 网 络 编 程, 必 须 理 解 Socket 接 口 Socket 接 口 设 计 者 最 先 是 将 接 口 放 在 Unix 操 作 系 统 里 面 的 如 果 了 解 Unix 系 统 的 输 入 和 输 出 的 话, 就 很 容 易 了 解 Socket 了 网 络 的 Socket 数 据 传 输 是 一 种 特 殊 的 I/O,Socket 也 是 一 种 文 件 描 述 符 Socket 也 具 有 一 个 类 似 于 打 开 文 件 的 函 数 调 用 Socket(), 该 函 数 返 回 一 个 整 型 的 Socket 描 述 符, 随 后 的 连 接 建 立 数 据 传 输 等 操 作 都 是 通 过 该 Socket 实 现 的 常 用 的 Socket 类 型 有 两 种 : 流 式 Socket(SOCK_STREAM) 和 数 据 报 式 Socket(SOCK_DGRAM) 流 式 是 一 种 面 向 连 接 的 Socket, 针 对 于 面 向 连 接 的 TCP 服 务 应 用 ; 数 据 报 式 Socket 是 一 种 无 连 接 的 Socket, 对 应 于 无 连 接 的 UDP 服 务 应 用

202 2)Socket 建 立 为 了 建 立 Socket, 程 序 可 以 调 用 Socket 函 数, 该 函 数 返 回 一 个 类 似 于 文 件 描 述 符 的 句 柄 socket 函 数 原 型 为 : int socket(int domain, int type, int protocol); domain 指 明 所 使 用 的 协 议 族, 通 常 为 PF_INET, 表 示 互 联 网 协 议 族 (TCP/IP 协 议 族 );type 参 数 指 定 socket 的 类 型 :SOCK_STREAM 或 SOCK_DGRAM,Socket 接 口 还 定 义 了 原 始 Socket (SOCK_RAW), 允 许 程 序 使 用 低 层 协 议 ;protocol 通 常 赋 值 0 Socket() 调 用 返 回 一 个 整 型 socket 描 述 符, 你 可 以 在 后 面 的 调 用 使 用 它 Socket 描 述 符 是 一 个 指 向 内 部 数 据 结 构 的 指 针, 它 指 向 描 述 符 表 入 口 调 用 Socket 函 数 时, socket 执 行 体 将 建 立 一 个 Socket, 实 际 上 建 立 一 个 Socket 意 味 着 为 一 个 Socket 数 据 结 构 分 配 存 储 空 间 Socket 执 行 体 为 你 管 理 描 述 符 表 两 个 网 络 程 序 之 间 的 一 个 网 络 连 接 包 括 五 种 信 息 : 通 信 协 议 本 地 协 议 地 址 本 地 主 机 端 口 远 端 主 机 地 址 和 远 端 协 议 端 口 Socket 数 据 结 构 中 包 含 这 五 种 信 息 3)Socket 配 置 通 过 socket 调 用 返 回 一 个 socket 描 述 符 后, 在 使 用 socket 进 行 网 络 传 输 以 前, 必 须 配 置 该 socket 面 向 连 接 的 socket 客 户 端 通 过 调 用 connect 函 数 在 socket 数 据 结 构 中 保 存 本 地 和 远 端 信 息 无 连 接 socket 的 客 户 端 和 服 务 端 以 及 面 向 连 接 socket 的 服 务 端 通 过 调 用 bind 函 数 来 配 置 本 地 信 息 bind 函 数 将 socket 与 本 机 上 的 一 个 端 口 相 关 联, 随 后 你 就 可 以 在 该 端 口 监 听 服 务 请 求 Bind 函 数 原 型 为 : int bind(int sockfd,struct sockaddr *my_addr, int addrlen); sockfd 是 调 用 socket 函 数 返 回 的 socket 描 述 符,my_addr 是 一 个 指 向 包 含 有 本 机 IP 地 址 及 端 口 号 等 信 息 的 sockaddr 类 型 的 指 针 ;addrlen 常 被 设 置 为 sizeof(struct sockaddr) struct sockaddr 结 构 类 型 是 用 来 保 存 socket 信 息 的 : struct sockaddr { unsigned short sa_family; // 地 址 族, AF_xxx char sa_data[14]; // 14 字 节 的 协 议 地 址 }; sa_family 一 般 为 AF_INET, 代 表 Internet(TCP/IP) 地 址 族 ;sa_data 则 包 含 该 socket 的 IP 地 址 和 端 口 号 另 外 还 有 一 种 结 构 类 型 : struct sockaddr_in { short int sin_family; unsigned short int sin_port; // 地 址 族 // 端 口 号

203 }; struct in_addr sin_addr; unsigned char sin_zero[8]; // IP 地 址 // 填 充 0 以 保 持 与 struct sockaddr 同 样 大 小 这 个 结 构 更 方 便 使 用 sin_zero 用 来 将 sockaddr_in 结 构 填 充 到 与 struct sockaddr 同 样 的 长 度, 可 以 用 bzero() 或 memset() 函 数 将 其 置 为 零 指 向 sockaddr_in 的 指 针 和 指 向 sockaddr 的 指 针 可 以 相 互 转 换, 这 意 味 着 如 果 一 个 函 数 所 需 参 数 类 型 是 sockaddr 时, 你 可 以 在 函 数 调 用 的 时 候 将 一 个 指 向 sockaddr_in 的 指 针 转 换 为 指 向 sockaddr 的 指 针 ; 或 者 相 反 使 用 bind 函 数 时, 可 以 用 下 面 的 赋 值 实 现 自 动 获 得 本 机 IP 地 址 和 随 机 获 取 一 个 没 有 被 占 用 的 端 口 号 : my_addr.sin_port = 0; // 系 统 随 机 选 择 一 个 未 被 使 用 的 端 口 号 my_addr.sin_addr.s_addr = INADDR_ANY; // 填 入 本 机 IP 地 址 通 过 将 my_addr.sin_port 置 为 0, 函 数 会 自 动 为 你 选 择 一 个 未 占 用 的 端 口 来 使 用 同 样, 通 过 将 my_addr.sin_addr.s_addr 置 为 INADDR_ANY, 系 统 会 自 动 填 入 本 机 IP 地 址 注 意 使 用 bind 函 数 需 要 将 sin_port 转 换 成 为 网 络 字 节 优 先 顺 序 ; 而 sin_addr 则 不 需 要 转 换 计 算 机 数 据 存 储 有 两 种 字 节 优 先 顺 序 : 高 位 字 节 优 先 和 低 位 字 节 优 先 Internet 上 数 据 以 高 位 字 节 优 先 顺 序 在 网 络 上 传 输, 所 以 对 于 在 内 部 是 以 低 位 字 节 优 先 方 式 存 储 数 据 的 机 器, 在 Internet 上 传 输 数 据 时 就 需 要 进 行 转 换, 否 则 就 会 出 现 数 据 不 一 致 下 面 是 几 个 字 节 顺 序 转 换 函 数 : h tonl(): 把 32 位 值 从 主 机 字 节 序 转 换 成 网 络 字 节 序 ; htons(): 把 16 位 值 从 主 机 字 节 序 转 换 成 网 络 字 节 序 ; ntohl(): 把 32 位 值 从 网 络 字 节 序 转 换 成 主 机 字 节 序 ; ntohs(): 把 16 位 值 从 网 络 字 节 序 转 换 成 主 机 字 节 序 bind() 函 数 在 成 功 被 调 用 时 返 回 0; 出 现 错 误 时 返 回 -1 并 将 errno 置 为 相 应 的 错 误 号 需 要 注 意 的 是, 在 调 用 bind 函 数 时 一 般 不 要 将 端 口 号 置 为 小 于 1024 的 值, 因 为 1 到 1024 是 保 留 端 口 号, 你 可 以 选 择 大 于 1024 中 的 任 何 一 个 没 有 被 占 用 的 端 口 号 4) 连 接 建 立 面 向 连 接 的 客 户 程 序 使 用 connect 函 数 来 配 置 socket 并 与 远 端 服 务 器 建 立 一 个 TCP 连 接, 其 函 数 原 型 为 : int connect(int sockfd, struct sockaddr *serv_addr,int addrlen); sockfd 是 socket 函 数 返 回 的 socket 描 述 符 ;serv_addr 是 包 含 远 端 主 机 IP 地 址 和 端 口 号 的 指 针 ;addrlen 是 远 端 地 址 结 构 的 长 度 connect 函 数 在 出 现 错 误 时 返 回 -1, 并 且 设 置 errno 为 相 应 的 错 误 码 进 行 客 户 端 程 序 设 计 无 须 调 用 bind(), 因 为 这 种 情 况 下 只 需 知 道 目 的 机 器 的 IP 地 址, 而 客 户 通 过 哪 个 端 口 与 服 务 器 建 立 连 接 并 不 需 要 关 心,socket 执 行 体 为 你 的 程 序 自 动 选 择 一 个 未 被 占 用 的 端 口, 并 通 知 你 的 程 序, 数 据 什 么 时 候 到 达 端 口

204 connect 函 数 启 动 和 远 端 主 机 的 直 接 连 接 只 有 面 向 连 接 的 客 户 程 序 使 用 socket 时 才 需 要 将 此 socket 与 远 端 主 机 相 连 无 连 接 协 议 从 不 建 立 直 接 连 接 面 向 连 接 的 服 务 器 也 从 不 启 动 一 个 连 接, 它 只 是 被 动 的 在 协 议 端 口 监 听 客 户 的 请 求 listen 函 数 使 socket 处 于 被 动 的 监 听 模 式, 并 为 该 socket 建 立 一 个 输 入 数 据 队 列, 将 到 达 的 服 务 请 求 保 存 在 此 队 列 中, 直 到 程 序 处 理 它 们 int listen(int sockfd, int backlog); sockfd 是 Socket 系 统 调 用 返 回 的 socket 描 述 符 ;backlog 指 定 在 请 求 队 列 中 允 许 的 最 大 请 求 数, 进 入 的 连 接 请 求 将 在 队 列 中 等 待 accept() 它 们 ( 参 考 下 文 ) backlog 对 队 列 中 等 待 服 务 的 请 求 的 数 目 进 行 了 限 制, 大 多 数 系 统 缺 省 值 为 20 如 果 一 个 服 务 请 求 到 来 时, 输 入 队 列 已 满, 该 socket 将 拒 绝 连 接 请 求, 客 户 将 收 到 一 个 出 错 信 息 当 出 现 错 误 时 listen 函 数 返 回 -1, 并 置 相 应 的 errno 错 误 码 accept() 函 数 让 服 务 器 接 收 客 户 的 连 接 请 求 在 建 立 好 输 入 队 列 后, 服 务 器 就 调 用 accept 函 数, 然 后 睡 眠 并 等 待 客 户 的 连 接 请 求 int accept(int sockfd, void *addr, int *addrlen); sockfd 是 被 监 听 的 socket 描 述 符,addr 通 常 是 一 个 指 向 sockaddr_in 变 量 的 指 针, 该 变 量 用 来 存 放 提 出 连 接 请 求 服 务 的 主 机 的 信 息 ( 某 台 主 机 从 某 个 端 口 发 出 该 请 求 );addrten 通 常 为 一 个 指 向 值 为 sizeof(struct sockaddr_in) 的 整 型 指 针 变 量 出 现 错 误 时 accept 函 数 返 回 -1 并 置 相 应 的 errno 值 首 先, 当 accept 函 数 监 视 的 socket 收 到 连 接 请 求 时,socket 执 行 体 将 建 立 一 个 新 的 socket, 执 行 体 将 这 个 新 socket 和 请 求 连 接 进 程 的 地 址 联 系 起 来, 收 到 服 务 请 求 的 初 始 socket 仍 可 以 继 续 在 以 前 的 socket 上 监 听, 同 时 可 以 在 新 的 socket 描 述 符 上 进 行 数 据 传 输 操 作 5) 数 据 传 输 send() 和 recv() 这 两 个 函 数 用 于 面 向 连 接 的 socket 上 进 行 数 据 传 输 send() 函 数 原 型 为 : int send(int sockfd, const void *msg, int len, int flags); sockfd 是 你 想 用 来 传 输 数 据 的 socket 描 述 符 ;msg 是 一 个 指 向 要 发 送 数 据 的 指 针 ;len 是 以 字 节 为 单 位 的 数 据 的 长 度 ;flags 一 般 情 况 下 置 为 0( 关 于 该 参 数 的 用 法 可 参 照 man 手 册 ) send() 函 数 返 回 实 际 上 发 送 出 的 字 节 数, 可 能 会 少 于 你 希 望 发 送 的 数 据 在 程 序 中 应 该 将 send() 的 返 回 值 与 欲 发 送 的 字 节 数 进 行 比 较 当 send() 返 回 值 与 len 不 匹 配 时, 应 该 对 这 种 情 况 进 行 处 理 char *msg = "Hello!"; int len, bytes_sent; len = strlen(msg); bytes_sent = send(sockfd, msg,len,0);

205 recv() 函 数 原 型 为 : int recv(int sockfd,void *buf,int len,unsigned int flags); sockfd 是 接 收 数 据 的 socket 描 述 符 ;buf 是 存 放 接 收 数 据 的 缓 冲 区 ;len 是 缓 冲 的 长 度 flags 也 被 置 为 0 recv() 返 回 实 际 上 接 收 的 字 节 数, 当 出 现 错 误 时, 返 回 -1 并 置 相 应 的 errno 值 sendto() 和 recvfrom() 用 于 在 无 连 接 的 数 据 报 socket 方 式 下 进 行 数 据 传 输 由 于 本 地 socket 并 没 有 与 远 端 机 器 建 立 连 接, 所 以 在 发 送 数 据 时 应 指 明 目 的 地 址 sendto() 函 数 原 型 为 : int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen); 该 函 数 比 send() 函 数 多 了 两 个 参 数,to 表 示 目 地 机 的 IP 地 址 和 端 口 号 信 息, 而 tolen 常 常 被 赋 值 为 sizeof (struct sockaddr) sendto 函 数 也 返 回 实 际 发 送 的 数 据 字 节 长 度 或 在 出 现 发 送 错 误 时 返 回 -1 recvfrom() 函 数 原 型 为 : int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); from 是 一 个 struct sockaddr 类 型 的 变 量, 该 变 量 保 存 源 机 的 IP 地 址 及 端 口 号 fromlen 常 置 为 sizeof (struct sockaddr) 当 recvfrom() 返 回 时,fromlen 包 含 实 际 存 入 from 中 的 数 据 字 节 数 recvfrom() 函 数 返 回 接 收 到 的 字 节 数 或 当 出 现 错 误 时 返 回 -1, 并 置 相 应 的 errno 如 果 你 对 数 据 报 socket 调 用 了 connect() 函 数 时, 你 也 可 以 利 用 send() 和 recv() 进 行 数 据 传 输, 但 该 socket 仍 然 是 数 据 报 socket, 并 且 利 用 传 输 层 的 UDP 服 务 但 在 发 送 或 接 收 数 据 报 时, 内 核 会 自 动 为 之 加 上 目 地 和 源 地 址 信 息 6) 结 束 传 输 当 所 有 的 数 据 操 作 结 束 以 后, 你 可 以 调 用 close() 函 数 来 释 放 该 socket, 从 而 停 止 在 该 socket 上 的 任 何 数 据 操 作 : close(sockfd); 你 也 可 以 调 用 shutdown() 函 数 来 关 闭 该 socket 该 函 数 允 许 你 只 停 止 在 某 个 方 向 上 的 数 据 传 输, 而 一 个 方 向 上 的 数 据 传 输 继 续 进 行 如 你 可 以 关 闭 某 socket 的 写 操 作 而 允 许 继 续 在 该 socket 上 接 收 数 据, 直 至 读 入 所 有 数 据 int shutdown(int sockfd,int how); Sockfd 是 需 要 关 闭 的 socket 的 描 述 符 参 数 how 允 许 为 shutdown 操 作 选 择 以 下 几 种 方 式 : 不 允 许 继 续 接 收 数 据 ; 不 允 许 继 续 发 送 数 据 ; 不 允 许 继 续 发 送 和 接 收 数 据 ; 均 为 允 许 则 调 用 close ()

206 数 shutdown 在 操 作 成 功 时 返 回 0, 在 出 现 错 误 时 返 回 -1 并 置 相 应 errno 有 了 上 面 的 基 础, 就 可 以 读 懂 一 般 的 socket 编 程 了, 该 例 程 中 只 用 到 上 面 TCP 通 信 常 用 的 函 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.6-tcp 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 tcp 服 务 端 程 序 : $ cd /usr/local/src/s210x/project/12.6-tcp/server $ gcc -o server server.c 4) 在 终 端 中 输 入 以 下 命 令 进 入 uclient 工 作 目 录 编 译 客 户 端 程 序 ; $ cd /usr/local/src/s210x/project/12.6-tcp/uclient $ arm-none-linux-gnueabi-gcc -o client client.c $ cp client /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 在 ubuntu 终 端 中 输 入 命 令 运 行 主 机 端 server 程 序 : $ cd /usr/local/src/s210x/project/12.6-tcp/server $./server OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 5000 sucessfully. OK: Listening the Port 5000 sucessfully. 4) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息

207 5) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 client 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./client -l./client 6) 给 client 添 加 可 执 行 权 限 : # chmod 777 client 7) 运 行 client: #./client OK: Have connected to the )client 正 常 运 行 时,PC 端 正 在 运 行 的 server 将 打 印 以 下 信 息, 并 提 示 输 入 字 符 信 息 : OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 5000 sucessfully. OK: Listening the Port 5000 sucessfully. OK: Server has got connect from You can enter string, and press 'exit' to end the connect. 在 PC 端 输 入 后 回 车, 将 打 印 以 下 信 息 : OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 5000 sucessfully. OK: Listening the Port 5000 sucessfully. OK: Server has got connect from You can enter string, and press 'exit' to end the connect OK: Sent 9 bytes sucessful, please enter again. 同 时 实 验 平 台 端 client 程 序 会 接 收 到 传 送 的 数 据, 并 在 minicom 串 口 终 端 上 打 印 出 来 : OK: Have connected to the OK: Receviced numbytes = 9 OK: Receviced string is: 在 PC 端 输 入 exit 字 符 将 退 出 程 序 12.7 Webserver 实 验 实 验 目 的 理 解 linux 中 TCP 的 通 信 过 程 以 及 实 现 方 法 ; 掌 握 linux 下 socket() 函 数 在 TCP 通 信 中 的 使 用

208 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 TCP 基 础 知 识 TCP 是 Transmission Control Protocol 的 简 写, 中 文 译 名 为 传 输 控 制 协 议 TCP 和 UDP 处 在 同 一 层 运 输 层, 但 是 TCP 和 UDP 最 不 同 的 地 方 是,TCP 提 供 了 一 种 可 靠 的 数 据 传 输 服 务, TCP 是 面 向 连 接 的, 也 就 是 说, 利 用 TCP 通 信 的 两 台 主 机 首 先 要 经 历 一 个 拨 打 电 话 的 过 程, 等 到 通 信 准 备 结 束 才 开 始 传 输 数 据, 最 后 结 束 通 话 所 以 TCP 要 比 UDP 可 靠 的 多,UDP 是 把 数 据 直 接 发 出 去, 而 不 管 对 方 是 不 是 在 收 信, 就 算 是 UDP 无 法 送 达, 也 不 会 产 生 ICMP 差 错 报 文 TCP 保 证 可 靠 性 的 简 单 工 作 原 理 如 下 : 应 用 数 据 被 分 割 成 TCP 认 为 最 适 合 发 送 的 数 据 块 这 和 UDP 完 全 不 同, 应 用 程 序 产 生 的 数 据 报 长 度 将 保 持 不 变 由 TCP 传 递 给 IP 的 信 息 单 位 称 为 报 文 段 或 段 (segment) 当 TCP 发 出 一 个 段 后, 它 启 动 一 个 定 时 器, 等 待 目 的 端 确 认 收 到 这 个 报 文 段 如 果 不 能 及 时 收 到 一 个 确 认, 将 重 发 这 个 报 文 段 当 TCP 收 到 发 自 TCP 连 接 另 一 端 的 数 据, 它 将 发 送 一 个 确 认 这 个 确 认 不 是 立 即 发 送, 通 常 将 推 迟 一 段 时 间 TCP 将 保 持 它 首 部 和 数 据 的 检 验 和 这 是 一 个 端 到 端 的 检 验 和, 目 的 是 检 测 数 据 在 传 输 过 程 中 的 任 何 变 化 如 果 收 到 段 的 检 验 和 有 差 错,TCP 将 丢 弃 这 个 报 文 段 和 不 确 认 收 到 此 报 文 段 ( 希 望 发 端 超 时 并 重 发 ) 既 然 TCP 报 文 段 作 为 IP 数 据 报 来 传 输, 而 IP 数 据 报 的 到 达 可 能 会 失 序, 因 此 TCP 报 文 段 的 到 达 也 可 能 会 失 序 如 果 必 要,TCP 将 对 收 到 的 数 据 进 行 重 新 排 序, 将 收 到 的 数 据 以 正 确 的 顺 序 交 给 应 用 层 TCP 还 能 提 供 流 量 控 制 TCP 连 接 的 每 一 方 都 有 固 定 大 小 的 缓 冲 空 间 TCP 的 接 收 端 只 允 许 另 一 端 发 送 接 收 端 缓 冲 区 所 能 接 纳 的 数 据 这 将 防 止 较 快 主 机 致 使 较 慢 主 机 的 缓 冲 区 溢 出 从 这 段 话 中 可 以 看 到,TCP 中 保 持 可 靠 性 的 方 式 就 是 超 时 重 发, 这 是 有 道 理 的, 虽 然 TCP 也 可 以 用 各 种 各 样 的 ICMP 报 文 来 处 理 这 些, 但 是 这 也 不 是 可 靠 的, 最 可 靠 的 方 式 就 是 只 要 不 得 到 确 认, 就 重 新 发 送 数 据 报, 直 到 得 到 对 方 的 确 认 为 止 TCP 的 首 部 和 UDP 首 部 一 样, 都 有 发 送 端 口 号 和 接 收 端 口 号 但 是 显 然,TCP 的 首 部 信 息 要 比 UDP 的 多, 可 以 看 到,TCP 协 议 提 供 了 发 送 和 确 认 所 需 要 的 所 有 必 要 的 信 息 可 以 想 象 一 个 TCP 数 据 的 发 送 应 该 是 如 下 的 一 个 过 程

209 双 方 建 立 连 接 发 送 方 给 接 收 方 TCP 数 据 报, 然 后 等 待 对 方 的 确 认 TCP 数 据 报, 如 果 没 有, 就 重 新 发, 如 果 有, 就 发 送 下 一 个 数 据 报 接 收 方 等 待 发 送 方 的 数 据 报, 如 果 得 到 数 据 报 并 检 验 无 误, 就 发 送 ACK( 确 认 ) 数 据 报, 并 等 待 下 一 个 TCP 数 据 报 的 到 来 直 到 接 收 到 FIN( 发 送 完 成 数 据 报 ) 中 止 连 接 可 以 想 见, 为 了 建 立 一 个 TCP 连 接, 系 统 可 能 会 建 立 一 个 新 的 进 程 来 进 行 数 据 的 传 送 目 前 建 立 在 TCP 协 议 上 的 网 络 协 议 特 别 多, 有 telnet,ssh, 有 ftp, 有 http 等 等 这 些 协 议 又 可 以 根 据 数 据 吞 吐 量 来 大 致 分 成 两 大 类 :(1) 交 互 数 据 类 型, 例 如 telnet,ssh, 这 种 类 型 的 协 议 在 大 多 数 情 况 下 只 是 做 小 流 量 的 数 据 交 换, 比 如 说 按 一 下 键 盘, 回 显 一 些 文 字 等 等 (2) 数 据 成 块 类 型, 例 如 ftp, 这 种 类 型 的 协 议 要 求 TCP 能 尽 量 的 运 载 数 据, 把 数 据 的 吞 吐 量 做 到 最 大, 并 尽 可 能 的 提 高 效 率 针 对 这 两 种 情 况,TCP 给 出 了 两 种 不 同 的 策 略 来 进 行 数 据 传 输 1)TCP 的 交 互 数 据 流 对 于 交 互 性 要 求 比 较 高 的 应 用,TCP 给 出 两 个 策 略 来 提 高 发 送 效 率 和 减 低 网 络 负 担 :(1) 捎 带 ACK (2)Nagle 算 法 ( 一 次 尽 量 多 的 发 数 据 ) 通 常, 在 网 络 速 度 很 快 的 情 况 下, 比 如 用 IO 接 口 进 行 telnet 通 信, 当 按 下 字 母 键 并 要 求 回 显 的 时 候, 客 户 端 和 服 务 器 将 经 历 发 送 按 键 数 据 -> 服 务 器 发 送 按 键 数 据 的 ack-> 服 务 器 端 发 送 回 显 数 据 -> 客 户 端 发 送 回 显 数 据 的 ACK 的 过 程, 而 其 中 的 数 据 流 量 将 是 40bit + 41bit+41bit+40bit = 162bit, 如 果 在 广 域 网 里 面, 这 种 小 分 组 的 TCP 流 量 将 会 造 成 很 大 的 网 络 负 担 捎 带 ACK 的 发 送 方 式 这 个 策 略 是 说, 当 主 机 收 到 远 程 主 机 的 TCP 数 据 报 之 后, 通 常 不 马 上 发 送 ACK 数 据 报, 而 是 等 上 一 个 短 暂 的 时 间, 如 果 这 段 时 间 里 面 主 机 还 有 发 送 到 远 程 主 机 的 TCP 数 据 报, 那 么 就 把 这 个 ACK 数 据 报 捎 带 着 发 送 出 去, 把 本 来 两 个 TCP 数 据 报 整 合 成 一 个 发 送 一 般 的, 这 个 时 间 是 200ms 可 以 明 显 地 看 到 这 个 策 略 可 以 把 TCP 数 据 报 的 利 用 率 提 高 很 多 Nagle 算 法 上 过 bbs 的 人 应 该 都 会 有 感 受, 就 是 在 网 络 慢 的 时 候 发 贴, 有 时 键 入 一 串 字 符 串 以 后, 经 过 一 段 时 间, 客 户 端 发 疯 一 样 突 然 回 显 出 很 多 内 容, 就 好 像 数 据 一 下 子 传 过 来 了 一 样, 这 就 是 Nagle 算 法 的 作 用 Nagle 算 法 是 说, 当 主 机 A 给 主 机 B 发 送 了 一 个 TCP 数 据 报 并 进 入 等 待 主 机 B 的 ACK 数 据 报 的 状 态 时,TCP 的 输 出 缓 冲 区 里 面 只 能 有 一 个 TCP 数 据 报, 并 且, 这 个 数 据 报 不 断 地 收 集 后 来 的 数 据, 整 合 成 一 个 大 的 数 据 报, 等 到 B 主 机 的 ACK 包 一 到, 就 把 这 些 数 据 一 股 脑 的 发 送 出 去 虽 然 这 样 的 描 述 有 些 不 准 确, 但 还 算 形 象 和 易 于 理 解, 我 们 同 样 可 以 体 会 到 这 个 策 略 对 于 减 低 网 络 负 担 的 好 处

210 在 编 写 插 口 程 序 的 时 候, 可 以 通 过 TCP_NODELAY 来 关 闭 这 个 算 法 并 且, 使 用 这 个 算 法 看 情 况 的, 比 如 基 于 TCP 的 X 窗 口 协 议, 如 果 处 理 鼠 标 事 件 时 还 是 用 这 个 算 法, 那 么 延 迟 可 就 非 常 大 了 2)TCP 的 成 块 数 据 流 对 于 FTP 这 样 对 于 数 据 吞 吐 量 有 较 高 要 求 的 要 求, 将 总 是 希 望 每 次 尽 量 多 的 发 送 数 据 到 对 方 主 机, 就 算 是 有 点 延 迟 也 无 所 谓 TCP 也 提 供 了 一 整 套 的 策 略 来 支 持 这 样 的 需 求 TCP 协 议 中 有 16 个 bit 表 示 窗 口 的 大 小, 这 是 这 些 策 略 的 核 心 传 输 数 据 时 ACK 的 问 题 在 解 释 滑 动 窗 口 前, 需 要 看 看 ACK 的 应 答 策 略, 一 般 来 说, 发 送 端 发 送 一 个 TCP 数 据 报, 那 么 接 收 端 就 应 该 发 送 一 个 ACK 数 据 报 但 是 事 实 上 却 不 是 这 样, 发 送 端 将 会 连 续 发 送 数 据 尽 量 填 满 接 收 方 的 缓 冲 区, 而 接 收 方 对 这 些 数 据 只 要 发 送 一 个 ACK 报 文 来 回 应 就 可 以 了, 这 就 是 ACK 的 累 积 特 性, 这 个 特 性 大 大 减 少 了 发 送 端 和 接 收 端 的 负 担 滑 动 窗 口 滑 动 窗 口 本 质 上 是 描 述 接 收 方 的 TCP 数 据 报 缓 冲 区 大 小 的 数 据, 发 送 方 根 据 这 个 数 据 来 计 算 自 己 最 多 能 发 送 多 长 的 数 据 如 果 发 送 方 收 到 接 收 方 的 窗 口 大 小 为 0 的 TCP 数 据 报, 那 么 发 送 方 将 停 止 发 送 数 据, 等 到 接 收 方 发 送 窗 口 大 小 不 为 0 的 数 据 报 的 到 来 TCP 就 是 用 这 个 窗 口, 慢 慢 的 从 数 据 的 左 边 移 动 到 右 边, 把 处 于 窗 口 范 围 内 的 数 据 发 送 出 去 ( 但 不 用 发 送 所 有, 只 是 处 于 窗 口 内 的 数 据 可 以 发 送 ) 这 就 是 窗 口 的 意 义 窗 口 的 大 小 是 可 以 通 过 socket 来 制 定 的,4096 并 不 是 最 理 想 的 窗 口 大 小, 而 则 可 以 使 吞 吐 量 大 大 的 增 加 数 据 拥 塞 上 面 的 策 略 用 于 局 域 网 内 传 输 还 可 以, 但 是 用 在 广 域 网 中 就 可 能 会 出 现 问 题, 最 大 的 问 题 就 是 当 传 输 时 出 现 了 瓶 颈 ( 比 如 说 一 定 要 经 过 一 个 slip 低 速 链 路 ) 所 产 生 的 大 量 数 据 堵 塞 问 题 ( 拥 塞 ), 为 了 解 决 这 个 问 题,TCP 发 送 方 需 要 确 认 连 接 双 方 的 线 路 的 数 据 最 大 吞 吐 量 是 多 少 这 就 是 所 谓 的 拥 塞 窗 口 拥 塞 窗 口 的 原 理 很 简 单,TCP 发 送 方 首 先 发 送 一 个 数 据 报, 然 后 等 待 对 方 的 回 应, 得 到 回 应 后 就 把 这 个 窗 口 的 大 小 加 倍, 然 后 连 续 发 送 两 个 数 据 报, 等 到 对 方 回 应 以 后, 再 把 这 个 窗 口 加 倍 ( 先 是 2 的 指 数 倍, 到 一 定 程 度 后 就 变 成 线 性 增 长, 这 就 是 所 谓 的 慢 启 动 ), 发 送 更 多 的 数 据 报, 直 到 出 现 超 时 错 误, 这 样, 发 送 端 就 了 解 到 了 通 信 双 方 的 线 路 承 载 能 力, 也 就 确 定 了 拥 塞 窗 口 的 大 小, 发 送 方 就 用 这 个 拥 塞 窗 口 的 大 小 发 送 数 据 要 观 察 这 个 现 象 是 非 常 容 易 的, 我 们 一 般 在 下 载 数 据 的 时 候, 速 度 都 是 慢 慢 冲 起 来 的 关 键 函 数 分 析 该 例 程 是 基 于 Linux 下 socket 编 程, 所 以 有 必 要 先 介 绍 一 下 socket 的 相 关 知 识 1) 什 么 是 Socket

211 Socket 接 口 是 TCP/IP 网 络 的 API,Socket 接 口 定 义 了 许 多 函 数 或 例 程, 程 序 员 可 以 用 它 们 来 开 发 TCP/IP 网 络 上 的 应 用 程 序 要 学 Internet 上 的 TCP/IP 网 络 编 程, 必 须 理 解 Socket 接 口 Socket 接 口 设 计 者 最 先 是 将 接 口 放 在 Unix 操 作 系 统 里 面 的 如 果 了 解 Unix 系 统 的 输 入 和 输 出 的 话, 就 很 容 易 了 解 Socket 了 网 络 的 Socket 数 据 传 输 是 一 种 特 殊 的 I/O,Socket 也 是 一 种 文 件 描 述 符 Socket 也 具 有 一 个 类 似 于 打 开 文 件 的 函 数 调 用 Socket(), 该 函 数 返 回 一 个 整 型 的 Socket 描 述 符, 随 后 的 连 接 建 立 数 据 传 输 等 操 作 都 是 通 过 该 Socket 实 现 的 常 用 的 Socket 类 型 有 两 种 : 流 式 Socket(SOCK_STREAM) 和 数 据 报 式 Socket(SOCK_DGRAM) 流 式 是 一 种 面 向 连 接 的 Socket, 针 对 于 面 向 连 接 的 TCP 服 务 应 用 ; 数 据 报 式 Socket 是 一 种 无 连 接 的 Socket, 对 应 于 无 连 接 的 UDP 服 务 应 用 2)Socket 建 立 为 了 建 立 Socket, 程 序 可 以 调 用 Socket 函 数, 该 函 数 返 回 一 个 类 似 于 文 件 描 述 符 的 句 柄 socket 函 数 原 型 为 : int socket(int domain, int type, int protocol); domain 指 明 所 使 用 的 协 议 族, 通 常 为 PF_INET, 表 示 互 联 网 协 议 族 (TCP/IP 协 议 族 );type 参 数 指 定 socket 的 类 型 :SOCK_STREAM 或 SOCK_DGRAM,Socket 接 口 还 定 义 了 原 始 Socket (SOCK_RAW), 允 许 程 序 使 用 低 层 协 议 ;protocol 通 常 赋 值 0 Socket() 调 用 返 回 一 个 整 型 socket 描 述 符, 你 可 以 在 后 面 的 调 用 使 用 它 Socket 描 述 符 是 一 个 指 向 内 部 数 据 结 构 的 指 针, 它 指 向 描 述 符 表 入 口 调 用 Socket 函 数 时, socket 执 行 体 将 建 立 一 个 Socket, 实 际 上 建 立 一 个 Socket 意 味 着 为 一 个 Socket 数 据 结 构 分 配 存 储 空 间 Socket 执 行 体 为 你 管 理 描 述 符 表 两 个 网 络 程 序 之 间 的 一 个 网 络 连 接 包 括 五 种 信 息 : 通 信 协 议 本 地 协 议 地 址 本 地 主 机 端 口 远 端 主 机 地 址 和 远 端 协 议 端 口 Socket 数 据 结 构 中 包 含 这 五 种 信 息 3)Socket 配 置 通 过 socket 调 用 返 回 一 个 socket 描 述 符 后, 在 使 用 socket 进 行 网 络 传 输 以 前, 必 须 配 置 该 socket 面 向 连 接 的 socket 客 户 端 通 过 调 用 connect 函 数 在 socket 数 据 结 构 中 保 存 本 地 和 远 端 信 息 无 连 接 socket 的 客 户 端 和 服 务 端 以 及 面 向 连 接 socket 的 服 务 端 通 过 调 用 bind 函 数 来 配 置 本 地 信 息 bind 函 数 将 socket 与 本 机 上 的 一 个 端 口 相 关 联, 随 后 你 就 可 以 在 该 端 口 监 听 服 务 请 求 Bind 函 数 原 型 为 : int bind(int sockfd,struct sockaddr *my_addr, int addrlen); sockfd 是 调 用 socket 函 数 返 回 的 socket 描 述 符,my_addr 是 一 个 指 向 包 含 有 本 机 IP 地 址 及 端 口 号 等 信 息 的 sockaddr 类 型 的 指 针 ;addrlen 常 被 设 置 为 sizeof(struct sockaddr) struct sockaddr 结 构 类 型 是 用 来 保 存 socket 信 息 的 :

212 struct sockaddr { }; unsigned short sa_family; char sa_data[14]; // 地 址 族, AF_xxx // 14 字 节 的 协 议 地 址 sa_family 一 般 为 AF_INET, 代 表 Internet(TCP/IP) 地 址 族 ;sa_data 则 包 含 该 socket 的 IP 地 址 和 端 口 号 另 外 还 有 一 种 结 构 类 型 : struct sockaddr_in { short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; // 地 址 族 // 端 口 号 // IP 地 址 // 填 充 0 以 保 持 与 struct sockaddr 同 样 大 小 这 个 结 构 更 方 便 使 用 sin_zero 用 来 将 sockaddr_in 结 构 填 充 到 与 struct sockaddr 同 样 的 长 度, 可 以 用 bzero() 或 memset() 函 数 将 其 置 为 零 指 向 sockaddr_in 的 指 针 和 指 向 sockaddr 的 指 针 可 以 相 互 转 换, 这 意 味 着 如 果 一 个 函 数 所 需 参 数 类 型 是 sockaddr 时, 你 可 以 在 函 数 调 用 的 时 候 将 一 个 指 向 sockaddr_in 的 指 针 转 换 为 指 向 sockaddr 的 指 针 ; 或 者 相 反 使 用 bind 函 数 时, 可 以 用 下 面 的 赋 值 实 现 自 动 获 得 本 机 IP 地 址 和 随 机 获 取 一 个 没 有 被 占 用 的 端 口 号 : my_addr.sin_port = 0; // 系 统 随 机 选 择 一 个 未 被 使 用 的 端 口 号 my_addr.sin_addr.s_addr = INADDR_ANY; // 填 入 本 机 IP 地 址 通 过 将 my_addr.sin_port 置 为 0, 函 数 会 自 动 为 你 选 择 一 个 未 占 用 的 端 口 来 使 用 同 样, 通 过 将 my_addr.sin_addr.s_addr 置 为 INADDR_ANY, 系 统 会 自 动 填 入 本 机 IP 地 址 注 意 使 用 bind 函 数 需 要 将 sin_port 转 换 成 为 网 络 字 节 优 先 顺 序 ; 而 sin_addr 则 不 需 要 转 换 计 算 机 数 据 存 储 有 两 种 字 节 优 先 顺 序 : 高 位 字 节 优 先 和 低 位 字 节 优 先 Internet 上 数 据 以 高 位 字 节 优 先 顺 序 在 网 络 上 传 输, 所 以 对 于 在 内 部 是 以 低 位 字 节 优 先 方 式 存 储 数 据 的 机 器, 在 Internet 上 传 输 数 据 时 就 需 要 进 行 转 换, 否 则 就 会 出 现 数 据 不 一 致 下 面 是 几 个 字 节 顺 序 转 换 函 数 : htonl(): 把 32 位 值 从 主 机 字 节 序 转 换 成 网 络 字 节 序 ; htons(): 把 16 位 值 从 主 机 字 节 序 转 换 成 网 络 字 节 序 ; ntohl(): 把 32 位 值 从 网 络 字 节 序 转 换 成 主 机 字 节 序 ; ntohs(): 把 16 位 值 从 网 络 字 节 序 转 换 成 主 机 字 节 序 bind() 函 数 在 成 功 被 调 用 时 返 回 0; 出 现 错 误 时 返 回 -1 并 将 errno 置 为 相 应 的 错 误 号 需 要 注 意 的 是, 在 调 用 bind 函 数 时 一 般 不 要 将 端 口 号 置 为 小 于 1024 的 值, 因 为 1 到 1024 是 保 留 端 口 号, 你 可 以 选 择 大 于 1024 中 的 任 何 一 个 没 有 被 占 用 的 端 口 号

213 4) 连 接 建 立 面 向 连 接 的 客 户 程 序 使 用 connect 函 数 来 配 置 socket 并 与 远 端 服 务 器 建 立 一 个 TCP 连 接, 其 函 数 原 型 为 : int connect(int sockfd, struct sockaddr *serv_addr,int addrlen); sockfd 是 socket 函 数 返 回 的 socket 描 述 符 ;serv_addr 是 包 含 远 端 主 机 IP 地 址 和 端 口 号 的 指 针 ;addrlen 是 远 端 地 址 结 构 的 长 度 connect 函 数 在 出 现 错 误 时 返 回 -1, 并 且 设 置 errno 为 相 应 的 错 误 码 进 行 客 户 端 程 序 设 计 无 须 调 用 bind(), 因 为 这 种 情 况 下 只 需 知 道 目 的 机 器 的 IP 地 址, 而 客 户 通 过 哪 个 端 口 与 服 务 器 建 立 连 接 并 不 需 要 关 心,socket 执 行 体 为 你 的 程 序 自 动 选 择 一 个 未 被 占 用 的 端 口, 并 通 知 你 的 程 序, 数 据 什 么 时 候 到 达 端 口 connect 函 数 启 动 和 远 端 主 机 的 直 接 连 接 只 有 面 向 连 接 的 客 户 程 序 使 用 socket 时 才 需 要 将 此 socket 与 远 端 主 机 相 连 无 连 接 协 议 从 不 建 立 直 接 连 接 面 向 连 接 的 服 务 器 也 从 不 启 动 一 个 连 接, 它 只 是 被 动 的 在 协 议 端 口 监 听 客 户 的 请 求 listen 函 数 使 socket 处 于 被 动 的 监 听 模 式, 并 为 该 socket 建 立 一 个 输 入 数 据 队 列, 将 到 达 的 服 务 请 求 保 存 在 此 队 列 中, 直 到 程 序 处 理 它 们 int listen(int sockfd, int backlog); sockfd 是 Socket 系 统 调 用 返 回 的 socket 描 述 符 ;backlog 指 定 在 请 求 队 列 中 允 许 的 最 大 请 求 数, 进 入 的 连 接 请 求 将 在 队 列 中 等 待 accept() 它 们 ( 参 考 下 文 ) backlog 对 队 列 中 等 待 服 务 的 请 求 的 数 目 进 行 了 限 制, 大 多 数 系 统 缺 省 值 为 20 如 果 一 个 服 务 请 求 到 来 时, 输 入 队 列 已 满, 该 socket 将 拒 绝 连 接 请 求, 客 户 将 收 到 一 个 出 错 信 息 当 出 现 错 误 时 listen 函 数 返 回 -1, 并 置 相 应 的 errno 错 误 码 accept() 函 数 让 服 务 器 接 收 客 户 的 连 接 请 求 在 建 立 好 输 入 队 列 后, 服 务 器 就 调 用 accept 函 数, 然 后 睡 眠 并 等 待 客 户 的 连 接 请 求 int accept(int sockfd, void *addr, int *addrlen); sockfd 是 被 监 听 的 socket 描 述 符,addr 通 常 是 一 个 指 向 sockaddr_in 变 量 的 指 针, 该 变 量 用 来 存 放 提 出 连 接 请 求 服 务 的 主 机 的 信 息 ( 某 台 主 机 从 某 个 端 口 发 出 该 请 求 );addrten 通 常 为 一 个 指 向 值 为 sizeof(struct sockaddr_in) 的 整 型 指 针 变 量 出 现 错 误 时 accept 函 数 返 回 -1 并 置 相 应 的 errno 值 首 先, 当 accept 函 数 监 视 的 socket 收 到 连 接 请 求 时,socket 执 行 体 将 建 立 一 个 新 的 socket, 执 行 体 将 这 个 新 socket 和 请 求 连 接 进 程 的 地 址 联 系 起 来, 收 到 服 务 请 求 的 初 始 socket 仍 可 以 继 续 在 以 前 的 socket 上 监 听, 同 时 可 以 在 新 的 socket 描 述 符 上 进 行 数 据 传 输 操 作 5) 数 据 传 输 send() 和 recv() 这 两 个 函 数 用 于 面 向 连 接 的 socket 上 进 行 数 据 传 输 send() 函 数 原 型 为 :

214 int send(int sockfd, const void *msg, int len, int flags); sockfd 是 你 想 用 来 传 输 数 据 的 socket 描 述 符 ;msg 是 一 个 指 向 要 发 送 数 据 的 指 针 ;len 是 以 字 节 为 单 位 的 数 据 的 长 度 ;flags 一 般 情 况 下 置 为 0( 关 于 该 参 数 的 用 法 可 参 照 man 手 册 ) send() 函 数 返 回 实 际 上 发 送 出 的 字 节 数, 可 能 会 少 于 你 希 望 发 送 的 数 据 在 程 序 中 应 该 将 send() 的 返 回 值 与 欲 发 送 的 字 节 数 进 行 比 较 当 send() 返 回 值 与 len 不 匹 配 时, 应 该 对 这 种 情 况 进 行 处 理 char *msg = "Hello!"; int len, bytes_sent; len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); recv() 函 数 原 型 为 : int recv(int sockfd,void *buf,int len,unsigned int flags); sockfd 是 接 收 数 据 的 socket 描 述 符 ;buf 是 存 放 接 收 数 据 的 缓 冲 区 ;len 是 缓 冲 的 长 度 flags 也 被 置 为 0 recv() 返 回 实 际 上 接 收 的 字 节 数, 当 出 现 错 误 时, 返 回 -1 并 置 相 应 的 errno 值 sendto() 和 recvfrom() 用 于 在 无 连 接 的 数 据 报 socket 方 式 下 进 行 数 据 传 输 由 于 本 地 socket 并 没 有 与 远 端 机 器 建 立 连 接, 所 以 在 发 送 数 据 时 应 指 明 目 的 地 址 sendto() 函 数 原 型 为 : int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen); 该 函 数 比 send() 函 数 多 了 两 个 参 数,to 表 示 目 地 机 的 IP 地 址 和 端 口 号 信 息, 而 tolen 常 常 被 赋 值 为 sizeof (struct sockaddr) sendto 函 数 也 返 回 实 际 发 送 的 数 据 字 节 长 度 或 在 出 现 发 送 错 误 时 返 回 -1 recvfrom() 函 数 原 型 为 : int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); from 是 一 个 struct sockaddr 类 型 的 变 量, 该 变 量 保 存 源 机 的 IP 地 址 及 端 口 号 fromlen 常 置 为 sizeof (struct sockaddr) 当 recvfrom() 返 回 时,fromlen 包 含 实 际 存 入 from 中 的 数 据 字 节 数 recvfrom() 函 数 返 回 接 收 到 的 字 节 数 或 当 出 现 错 误 时 返 回 -1, 并 置 相 应 的 errno 如 果 你 对 数 据 报 socket 调 用 了 connect() 函 数 时, 你 也 可 以 利 用 send() 和 recv() 进 行 数 据 传 输, 但 该 socket 仍 然 是 数 据 报 socket, 并 且 利 用 传 输 层 的 UDP 服 务 但 在 发 送 或 接 收 数 据 报 时, 内 核 会 自 动 为 之 加 上 目 地 和 源 地 址 信 息 6) 结 束 传 输 当 所 有 的 数 据 操 作 结 束 以 后, 你 可 以 调 用 close() 函 数 来 释 放 该 socket, 从 而 停 止 在 该 socket 上 的 任 何 数 据 操 作 : close(sockfd);

215 你 也 可 以 调 用 shutdown() 函 数 来 关 闭 该 socket 该 函 数 允 许 你 只 停 止 在 某 个 方 向 上 的 数 据 传 输, 而 一 个 方 向 上 的 数 据 传 输 继 续 进 行 如 你 可 以 关 闭 某 socket 的 写 操 作 而 允 许 继 续 在 该 socket 上 接 收 数 据, 直 至 读 入 所 有 数 据 int shutdown(int sockfd,int how); Sockfd 是 需 要 关 闭 的 socket 的 描 述 符 参 数 how 允 许 为 shutdown 操 作 选 择 以 下 几 种 方 式 : 不 允 许 继 续 接 收 数 据 ; 不 允 许 继 续 发 送 数 据 ; 不 允 许 继 续 发 送 和 接 收 数 据 ; 均 为 允 许 则 调 用 close () shutdown 在 操 作 成 功 时 返 回 0, 在 出 现 错 误 时 返 回 -1 并 置 相 应 errno 有 了 上 面 的 基 础, 就 可 以 读 懂 一 般 的 socket 编 程 了, 该 例 程 中 只 用 到 上 面 TCP 通 信 常 用 的 函 数 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.7-webserver 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 webserver 程 序 : $ cd /usr/local/src/s210x/project/12.7-webserver $ arm-none-linux-gnueabi-gcc -o webserver webserver.c $ cp webserver /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息

216 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 webserver 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./webserver -l./webserver 5) 给 webserver 添 加 可 执 行 权 限 : # chmod 777 webserver 6) 运 行 webserver #./webserver OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 81 sucessfully. OK: Listening the Port 81 sucessfully. 正 常 运 行 时, 在 PC 端 打 开 浏 览 器, 在 地 址 栏 输 入 回 车, 即 可 在 浏 览 器 中 看 到 以 下 信 息, 为 实 验 平 台 的 主 板 网 卡 的 IP 地 址 Welcome To zonesion s210x Platform s210x Android 3G 移 动 互 联 网 开 发 平 台 12.8 UDP 实 验 实 验 目 的 掌 握 linux 下 UDP 的 通 信 原 理 与 实 现 ; 掌 握 linux 下 的 socket 函 数 编 程 方 法 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 UDP 基 础 知 识 UDP 协 议 是 英 文 User Datagram Protocol 的 缩 写, 即 用 户 数 据 报 协 议, 主 要 用 来 支 持 那 些 需 要 在 计 算 机 之 间 传 输 数 据 的 网 络 应 用 包 括 网 络 视 频 会 议 系 统 在 内 的 众 多 的 客 户 / 服 务 器 模 式 的 网 络 应

217 用 都 需 要 使 用 UDP 协 议 UDP 协 议 从 问 世 至 今 已 经 被 使 用 了 很 多 年, 虽 然 其 最 初 的 光 彩 已 经 被 一 些 类 似 协 议 所 掩 盖, 但 是 即 使 是 在 今 天,UDP 仍 然 不 失 为 一 项 非 常 实 用 和 可 行 的 网 络 传 输 层 协 议 与 我 们 所 熟 知 的 TCP( 传 输 控 制 协 议 ) 协 议 一 样,UDP 协 议 直 接 位 于 IP( 网 际 协 议 ) 协 议 的 顶 层 根 据 OSI( 开 放 系 统 互 连 ) 参 考 模 型,UDP 和 TCP 都 属 于 传 输 层 协 议 UDP 协 议 的 主 要 作 用 是 将 网 络 数 据 流 量 压 缩 成 数 据 报 的 形 式 一 个 典 型 的 数 据 报 就 是 一 个 二 进 制 数 据 的 传 输 单 位 每 一 个 数 据 报 的 前 8 个 字 节 用 来 包 含 报 头 信 息, 剩 余 字 节 则 用 来 包 含 具 体 的 传 输 数 据 UDP 协 议 使 用 端 口 号 为 不 同 的 应 用, 并 保 留 其 各 自 的 数 据 传 输 通 道 UDP 和 TCP 协 议 正 是 采 用 这 一 机 制 实 现 对 同 一 时 刻 内 多 项 应 用 同 时 发 送 和 接 收 数 据 的 支 持 数 据 发 送 一 方 ( 可 以 是 客 户 端 或 服 务 器 端 ) 将 UDP 数 据 报 通 过 原 端 口 发 送 出 去, 而 数 据 接 收 一 方 则 通 过 目 标 端 口 接 收 数 据 有 的 网 络 应 用 只 能 使 用 预 先 为 其 预 留 或 注 册 的 静 态 端 口 ; 而 另 外 一 些 网 络 应 用 则 可 以 使 用 未 被 注 册 的 动 态 端 口 因 为 UDP 报 头 使 用 两 个 字 节 存 放 端 口 号, 所 以 端 口 号 的 有 效 范 围 是 从 0 到 一 般 来 说, 大 于 的 端 口 号 都 代 表 动 态 端 口 数 据 报 的 长 度 是 指 包 括 报 头 和 数 据 部 分 在 内 的 总 的 字 节 数 因 为 报 头 的 长 度 是 固 定 的, 所 以 该 域 主 要 被 用 来 计 算 可 变 长 度 的 数 据 部 分 ( 又 称 为 数 据 负 载 ) 数 据 报 的 最 大 长 度 根 据 操 作 环 境 的 不 同 而 各 异 从 理 论 上 说, 包 含 报 头 在 内 的 数 据 报 的 最 大 长 度 为 字 节 不 过, 一 些 实 际 应 用 往 往 会 限 制 数 据 报 的 大 小, 有 时 会 降 低 到 8192 字 节 UDP 协 议 使 用 报 头 中 的 校 验 值 来 保 证 数 据 的 安 全 校 验 值 首 先 在 数 据 发 送 方 通 过 特 殊 的 算 法 计 算 得 出, 在 传 递 到 接 收 方 之 后, 还 需 要 再 重 新 计 算 如 果 某 个 数 据 报 在 传 输 过 程 中 被 第 三 方 篡 改 或 者 由 于 线 路 噪 音 等 原 因 受 到 损 坏, 发 送 和 接 收 方 的 校 验 计 算 值 将 不 会 相 符, 由 此 UDP 协 议 可 以 检 测 是 否 出 错 这 与 TCP 协 议 是 不 同 的, 后 者 要 求 必 须 具 有 校 验 值 UDP 和 TCP 协 议 的 主 要 区 别 是 两 者 在 如 何 实 现 信 息 的 可 靠 传 递 方 面 不 同 TCP 协 议 中 包 含 了 专 门 的 传 递 保 证 机 制, 当 数 据 接 收 方 收 到 发 送 方 传 来 的 信 息 时, 会 自 动 向 发 送 方 发 出 确 认 消 息 ; 发 送 方 只 有 在 接 收 到 该 确 认 消 息 之 后 才 继 续 传 送 其 它 信 息, 否 则 将 一 直 等 待 直 到 收 到 确 认 信 息 为 止 与 TCP 不 同,UDP 协 议 并 不 提 供 数 据 传 送 的 保 证 机 制 如 果 在 从 发 送 方 到 接 收 方 的 传 递 过 程 中 出 现 数 据 报 的 丢 失, 协 议 本 身 并 不 能 做 出 任 何 检 测 或 提 示 因 此, 通 常 人 们 把 UDP 协 议 称 为 不 可 靠 的 传 输 协 议 相 对 于 TCP 协 议,UDP 协 议 的 另 外 一 个 不 同 之 处 在 于 如 何 接 收 突 发 性 的 多 个 数 据 报 不 同 于 TCP,UDP 并 不 能 确 保 数 据 的 发 送 和 接 收 顺 序 也 许 有 的 读 者 会 问, 既 然 UDP 是 一 种 不 可 靠 的 网 络 协 议, 那 么 还 有 什 么 使 用 价 值 或 必 要 呢? 其 实 不 然, 在 有 些 情 况 下 UDP 协 议 可 能 会 变 得 非 常 有 用 因 为 UDP 具 有 TCP 所 望 尘 莫 及 的 速 度 优 势 虽 然 TCP 协 议 中 植 入 了 各 种 安 全 保 障 功 能, 但 是 在 实 际 执 行 的 过 程 中 会 占 用 大 量 的 系 统 开 销, 无 疑 使 速 度 受 到 严 重 的 影 响 反 观 UDP 由 于 排 除 了 信 息 可 靠 传 递 机 制, 将 安 全 和 排 序 等 功 能 移 交 给

218 上 层 应 用 来 完 成, 极 大 降 低 了 执 行 时 间, 使 速 度 得 到 了 保 证 关 于 UDP 协 议 的 最 早 规 范 是 RFC768,1980 年 发 布 尽 管 时 间 已 经 很 长, 但 是 UDP 协 议 仍 然 继 续 在 主 流 应 用 中 发 挥 着 作 用 包 括 视 频 电 话 会 议 系 统 在 内 的 许 多 应 用 都 证 明 了 UDP 协 议 的 存 在 价 值 因 为 相 对 于 可 靠 性 来 说, 这 些 应 用 更 加 注 重 实 际 性 能, 所 以 为 了 获 得 更 好 的 使 用 效 果 ( 例 如, 更 高 的 画 面 帧 刷 新 速 率 ) 往 往 可 以 牺 牲 一 定 的 可 靠 性 ( 例 如, 会 面 质 量 ) 这 就 是 UDP 和 TCP 两 种 协 议 的 权 衡 之 处 根 据 不 同 的 环 境 和 特 点, 两 种 传 输 协 议 都 将 在 今 后 的 网 络 世 界 中 发 挥 更 加 重 要 的 作 用 关 键 函 数 分 析 该 例 程 是 基 于 Linux 下 socket 编 程, 关 于 socket 相 关 知 识 的 介 绍 详 见 12.6 节 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.8-udp 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 listener 程 序 : $ cd /usr/local/src/s210x/project/12.8-udp/listener $ gcc -o listener listener.c 4) 在 终 端 中 输 入 以 下 命 令 进 入 utalker 工 作 目 录 编 译 talker 程 序 ; $ cd /usr/local/src/s210x/project/12.8-udp/utalker $ arm-none-linux-gnueabi-gcc -o talker talker.c $ cp talker /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 在 ubuntu 终 端 中 输 入 命 令 运 行 主 机 端 listener 程 序 : $ cd /usr/local/src/s210x/project/12.8-udp/listener

219 $./listener OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 5000 sucessfully. 4) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 5) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 talker 下 载 到 s210x 实 验 平 台 : # cd /home/app # tftp -g r./talker -l./talker 6) 给 talker 添 加 可 执 行 权 限 : # chmod 777 talker 7) 运 行 talker #./talker OK: Sent to total 31 bytes! 8)talker 正 常 运 行 时,PC 端 正 在 运 行 的 listener 将 打 印 以 下 信 息, 并 提 示 输 入 字 符 信 息 : OK: Obtain Socket Despcritor sucessfully. OK: Bind the Port 5000 sucessfully. OK: Welcom to zonesion s210x ^_^ 网 络 服 务 器 Boa 实 验 实 验 目 的 掌 握 linux 下 Boa 的 特 点, 功 能 以 及 实 现 ; 掌 握 linux 下 的 嵌 入 式 Web 服 务 器 移 植 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 随 着 Internet 技 术 的 兴 起, 在 嵌 入 式 设 备 的 管 理 与 交 互 中, 基 于 Web 方 式 的 应 用 成 为 目 前 的 主

220 流, 这 种 程 序 结 构 也 就 是 大 家 非 常 熟 悉 的 B/S 结 构, 即 在 嵌 入 式 设 备 上 运 行 一 个 支 持 脚 本 或 CGI 功 能 的 Web 服 务 器, 能 够 生 成 动 态 页 面, 在 用 户 端 只 需 要 通 过 Web 浏 览 器 就 可 以 对 嵌 入 式 设 备 进 行 管 理 和 监 控, 非 常 方 便 实 用 本 节 主 要 介 绍 这 种 应 用 的 开 发 和 移 植 工 作 用 户 首 先 需 要 在 嵌 入 式 设 备 上 成 功 移 植 支 持 脚 本 或 CGI 功 能 的 Web 服 务 器, 然 后 才 能 进 行 应 用 程 序 的 开 发 嵌 入 式 Web 服 务 器 Boa 的 特 点 Boa 是 一 款 单 任 务 的 HTTP 服 务 器, 与 其 他 传 统 的 Web 服 务 器 不 同 的 是 当 有 连 接 请 求 到 来 时, 它 并 不 为 每 个 连 接 单 独 创 建 进 程, 也 不 通 过 复 制 自 身 进 程 来 处 理 多 连 接, 而 是 通 过 建 立 HTTP 请 求 列 表 来 处 理 多 路 HTTP 连 接 请 求, 同 时 它 只 为 CGI 程 序 创 建 新 的 进 程, 这 样 就 在 最 大 程 度 上 节 省 了 系 统 资 源, 这 对 嵌 入 式 系 统 来 说 至 关 重 要 同 时 它 还 具 有 自 动 生 成 目 录 自 动 解 压 文 件 等 功 能, 因 此,Boa 具 有 很 高 的 HTTP 请 求 处 理 速 度 和 效 率, 在 嵌 入 式 系 统 中 具 有 很 高 的 应 用 价 值 Boa 的 功 能 实 现 嵌 入 式 Web 服 务 器 Boa 和 普 通 Web 服 务 器 一 样, 能 够 完 成 接 收 客 户 端 请 求 分 析 请 求 响 应 请 求 向 客 户 端 返 回 请 求 结 果 等 任 务 它 的 工 作 过 程 主 要 包 括 : 1) 完 成 Web 服 务 器 的 初 始 化 工 作, 如 创 建 环 境 变 量 创 建 TCP 套 接 字 绑 定 端 口 开 始 侦 听 进 入 循 环 结 构, 以 及 等 待 接 收 客 户 浏 览 器 的 连 接 请 求 ; 2) 当 有 客 户 端 连 接 请 求 时,Web 服 务 器 负 责 接 收 客 户 端 请 求, 并 保 存 相 关 请 求 信 息 ; 3) 在 接 收 到 客 户 端 的 连 接 请 求 之 后, 分 析 客 户 端 请 求, 解 析 出 请 求 的 方 法 URL 目 标 可 选 的 查 询 信 息 及 表 单 信 息, 同 时 根 据 请 求 做 出 相 应 的 处 理 ; 4)Web 服 务 器 完 成 相 应 处 理 后, 向 客 户 端 浏 览 器 发 送 响 应 信 息, 关 闭 与 客 户 机 的 TCP 连 接 嵌 入 式 Web 服 务 器 Boa 根 据 请 求 方 法 的 不 同, 做 出 不 同 的 响 应 如 果 请 求 方 法 为 HEAD, 则 直 接 向 浏 览 器 返 回 响 应 首 部 ; 如 果 请 求 方 法 为 GET, 则 在 返 回 响 应 首 部 的 同 时, 将 客 户 端 请 求 的 URL 目 标 文 件 从 服 务 器 上 读 出, 并 且 发 送 给 客 户 端 浏 览 器 ; 如 果 请 求 方 法 为 POST, 则 将 客 户 发 送 过 来 的 表 单 信 息 传 送 给 相 应 的 CGI 程 序, 作 为 CGI 的 参 数 来 执 行 CGI 程 序, 并 将 执 行 结 果 发 送 给 客 户 端 浏 览 器 Boa 的 功 能 实 现 也 是 通 过 建 立 连 接 绑 定 端 口 进 行 侦 听 请 求 处 理 等 来 实 现 的 其 初 始 化 部 分 的 源 代 码 如 下 : int server_s; server_s = socket( SERVER_PF,SOCK_STREAM,IPPROTO_TCP) ; if( server_s == - 1) { DIE( unable to create socket) ; } if( set_nonblock_fd( server_s) == - 1) {

221 DIE( unable to set server socket to nonblocking) ; } if( fcntl( server_s,f_setfd,1) == - 1) { DIE( can t set close! on! exec on server socket! ) ; } if( ( setsockopt( server_s, SOL_SOCKET,SO_REUSEADDR,( void*)&sock_opt, sizeof( sock_opt) ) ) == - 1) { DIE( setsockopt) ; } if( bind_server( server_s, server_ip, server_port) == - 1) { DIE( unable to bind) ; } if( listen( server_s, backlog) == - 1) { DIE( unable to listen) ; } 上 述 代 码 主 要 用 于 打 开 一 个 有 效 的 socket 描 述 符, 然 后 将 其 转 换 为 无 阻 塞 套 接 字 函 数 bind() 用 于 建 立 套 接 字 描 述 符 与 指 定 端 口 间 的 关 联, 并 通 过 函 数 listen() 在 该 指 定 端 口 侦 听, 等 待 远 程 连 接 请 求 当 侦 听 到 连 接 请 求 时,Boa 调 用 函 数 get_request( int server_sock) 获 取 请 求 信 息, 通 过 调 用 函 数 accept() 为 该 请 求 建 立 一 个 连 接 在 建 立 连 接 之 后, 接 收 请 求 信 息, 同 时 对 请 求 进 行 分 析 当 有 CGI 请 求 时, 为 CGI 程 序 创 建 进 程, 并 将 结 果 通 过 管 道 发 送 输 出 嵌 入 式 Web 服 务 器 移 植 由 于 嵌 入 式 设 备 资 源 一 般 都 比 较 有 限, 并 且 也 不 需 要 能 同 时 处 理 很 多 用 户 的 请 求, 因 此 不 会 使 用 Linux 下 最 常 用 的 如 Apache 等 服 务 器, 而 需 要 使 用 一 些 专 门 为 嵌 入 式 设 备 设 计 的 Web 服 务 器, 这 些 Web 服 务 器 在 存 贮 空 间 和 运 行 时 所 占 有 的 内 存 空 间 上 都 会 非 常 适 合 于 嵌 入 式 应 用 场 合 典 型 的 嵌 入 式 Web 服 务 器 有 Boa( 和 thttpd( 等, 它 们 和 Apache 等 高 性 能 的 Web 服 务 器 主 要 的 区 别 在 于 它 们 一 般 是 单 进 程 服 务 器, 只 有 在 完 成 一 个 用 户 请 求 后 才 能 响 应 另 一 个 用 户 的 请 求, 而 无 法 并 发 响 应, 但 这 在 嵌 入 式 设 备 的 应 用 场 合 里 已 经 足 够 了 我 们 介 绍 比 较 常 用 的 Boa 服 务 器 的 移 植

222 Boa 是 一 个 非 常 小 巧 的 Web 服 务 器, 可 执 行 代 码 只 有 约 60KB 它 是 一 个 单 任 务 Web 服 务 器, 只 能 依 次 完 成 用 户 的 请 求, 而 不 会 fork 出 新 的 进 程 来 处 理 并 发 连 接 请 求 但 Boa 支 持 CGI, 能 够 为 CGI 程 序 fork 出 一 个 进 程 来 执 行 Boa 的 设 计 目 标 是 速 度 和 安 全, 在 其 站 点 公 布 的 性 能 测 试 中,Boa 的 性 能 要 好 于 Apache 服 务 器 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.9-boa 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 进 入 到 boa 实 验 目 录, 并 解 压 相 应 工 具 包 及 库 : $ cd /usr/local/src/s210x/project/12.9-boa $ tar zxvf boa tar.gz 4) 配 置 boa 生 成 Makefile: $ cd boa /src $./configure --host=arm-linux --target=arm-linux 5) 修 改 源 码 文 件 : 修 改 12.9-boa /boa /src/makefile: 修 改 : CC = gcc CPP = gcc -E 为 : CC = arm-none-linux-gnueabi-gcc CPP = arm-none-linux-gnueabi-gcc -E 修 改 12.9-boa /boa /src/compat.h: 修 改 : #define TIMEZONE_OFFSET(foo) foo##->tm_gmtoff 为 : #define TIMEZONE_OFFSET(foo) foo->tm_gmtoff 修 改 12.9-boa /boa /src/boa.c: 修 改 : if (setuid(0)!= -1) {

223 DIE("icky Linux kernel bug!"); } 为 : #if 0 if (setuid(0)!= -1) { DIE("icky Linux kernel bug!"); } #endif 修 改 : if (passwdbuf == NULL) { DIE("getpwuid"); } if (initgroups(passwdbuf->pw_name, passwdbuf->pw_gid) == -1) { DIE("initgroups"); } 为 : #if 0 if (passwdbuf == NULL) { DIE("getpwuid"); } if (initgroups(passwdbuf->pw_name, passwdbuf->pw_gid) == -1) { DIE("initgroups"); } #endif 修 改 /usr/local/src/s210x /project/12.9-boa /boa /src/log.c: 修 改 : if (dup2(error_log, STDERR_FILENO) == -1) { DIE("unable to dup2 the error log"); } 为 : #if 0 if (dup2(error_log, STDERR_FILENO) == -1) { DIE("unable to dup2 the error log"); } #endif 6) 修 改 完 源 码 文 件 后 输 入 命 令 开 始 编 译 源 码 : $ make $ arm-none-linux-gnueabi-strip boa

224 7) 修 改 boa 配 置 文 件 /usr/local/src/s210x/project/12.9-boa /boa /boa.conf: 修 改 : User nobody Group nogroup 为 : User 0 Group 0 修 改 : #ServerName 为 : ServerName 修 改 : DocumentRoot 为 : DocumentRoot /www 修 改 : MimeTypes /etc/mime.types 为 : MimeTypes /dev/null 修 改 : ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ 为 : ScriptAlias /cgi-bin/ /www/cgi-bin/ 8) 准 备 BOA 实 验 必 备 源 码 并 拷 贝 到 /opt/nfs 目 录 ( 实 验 中 将 通 过 ftp 服 务 加 载 到 实 验 平 台 运 行 的 linux 上 ) Ubuntu Linux 终 端 : $ cd /usr/local/src/s210x/project /12.9-boa $ cp boa /boa.conf /opt/nfs $ cp boa /src/boa /opt/nfs $ cp -av www /opt/nfs 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为

225 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 boa 下 载 到 s210x 实 验 平 台 : # mount -t nfs :/opt/nfs /tmp -o intr,nolock,rsize=1024,wsize=1024 # mkdir -p /etc/boa # cp /tmp/boa.conf /etc/boa/ # mkdir -p /var/log/boa # mkdir -p /www/cgi-bin # cp -a /tmp/www/* /www 5) 运 行 测 试 BOA 网 络 服 务 器 : # cd /tmp #./boa 在 PC 端 浏 览 器 中 输 入 实 验 平 台 的 IP 地 址 : 出 现 欢 迎 网 页, BOA 搭 建 成 功, 其 中 为 实 验 平 台 的 主 板 网 卡 的 IP 地 址 Madplay 实 验 实 验 目 的 通 过 实 验 了 解 一 般 应 用 程 序 的 移 植 方 法 ; 通 过 实 验 掌 握 在 Linux 播 放 MP3 的 方 法 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 madplay 作 为 一 款 流 行 的 嵌 入 式 播 放 器 能 够 很 好 的 兼 容 当 前 的 各 种 嵌 入 式 设 备, 具 有 良 好 的 可 移 植 性, 实 现 了 在 嵌 入 式 上 的 音 频 播 放

226 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.9-boa 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 进 入 到 Madplay 播 放 器 实 验 目 录, 并 解 压 相 应 工 具 包 及 库 : $ cd /usr/local/src/s210x/project/12.10-madplay $ tar zxvf zlib tar.gz $ tar zxvf libid3tag b.tar.gz $ tar zxvf libmad b.tar.gz $ tar zxvf madplay b.tar.gz 4) 建 立 必 要 的 临 时 文 件 夹 : $ mkdir -p madplay/include madplay/lib 5) 编 译 zlib 库 : $ cd zlib 按 照 下 面 内 容 修 改 zlib 文 件 夹 内 的 Makefile 文 件 : CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar rcs RANLIB=arm-none-linux-gnueabi-ranlib prefix = /usr/local/src/s210x/project/12.10-madplay/madplay 编 译 zlib 库 : $ make $ make install 6) 编 译 libid3tag 库 : $ cd /usr/local/src/s210x/project/12.10-madplay/libid3tag b/ $./configure CC=arm-none-linux-gnueabi-gcc --prefix=/usr/local/src/s210x/project/12.10-madplay/madplay --host=arm-linux --disable-debugging --disable-shared --enable-static CPPFLAGS=-I/usr/local/src/s210x/project/12.10-madplay/madplay/include LDFLAGS=-L/usr/local/src/s210x/project/12.10-madplay/madplay/lib $ make $ make install 7) 编 译 libmad 库 : $ cd /usr/local/src/s210x/project/12.10-madplay/libmad b/

227 $./configure CC=arm-none-linux-gnueabi-gcc --prefix=/usr/local/src/s210x/project/12.10-madplay/madplay --host=arm-linux --disable-debugging --disable-shared --enable-static CPPFLAGS=-I/usr/local/src/s210x/project/12.10-madplay/madplay/include LDFLAGS=-L/usr/local/src/s210x/project/12.10-madplay/madplay/madplay/lib # # 配 置 完 成 后,, 在 执 行 make 命 令 之 前, 删 除 Makefile 中 -fforce-mem 字 符 串, 否 则 会 出 错, 因 为 当 前 GCC 版 本 已 经 去 掉 了 该 选 项 $ make $ make install 8) 编 译 madplay: $ cd /usr/local/src/s210x/project/12.10-madplay/madplay b/ $./configure CC=arm-none-linux-gnueabi-gcc --prefix=/usr/local/src/s210x/project/12.10-madplay/madplay --host=arm-linux --disable-debugging --disable-shared --enable-static CPPFLAGS=-I/usr/local/src/s210x/project/12.10-madplay/madplay/include LDFLAGS=-L/usr/local/src/s210x/project/12.10-madplay/madplay/lib $ make $ make install 9) 拷 贝 编 译 出 来 的 madplay 文 件 到 /opt/nfs 目 录 : $ cp -av /tmp/madplay /opt/nfs $ cp test.mp3 /opt/nfs 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 madplay 下 载 到 s210x 实 验 平 台 : # mount -t nfs :/opt/nfs /tmp -o intr,nolock,rsize=1024,wsize=1024 # cp -a /tmp/madplay/* /usr # cp /tmp/test.mp3 /home/app 5) 播 放 mp3: # madplay /home/app/test.mp

228 运 行 之 后 就 可 以 听 到 优 美 的 音 乐 了 SQLite 数 据 库 移 植 实 验 实 验 目 的 进 一 步 掌 握 linux 下 一 般 应 用 程 序 的 移 植 方 法 实 现 ; 通 过 实 验 掌 握 linux 下 SQLite 数 据 库 的 使 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 SQLite 是 一 款 轻 型 的 数 据 库, 是 遵 守 ACID 的 关 联 式 数 据 库 管 理 系 统 它 的 设 计 目 标 是 嵌 入 式 的, 目 前 已 经 在 很 多 嵌 入 式 产 品 中 使 用 SQLite 占 用 资 源 非 常 的 低, 在 嵌 入 式 设 备 中, 可 能 只 需 要 几 百 K 的 内 存 就 够 了 并 且 处 理 速 度 快 它 能 够 支 持 Windows/Linux/Unix 等 主 流 的 操 作 系 统 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 12 章 /12.11-sqlite 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 进 入 到 SQLite 实 验 目 录, 并 解 压 SQLite 压 缩 包 : $ cd /usr/local/src/s210x/project/12.11-sqlite $ tar zxvf sqlite tar.gz 4) 建 立 必 要 的 临 时 文 件 夹 :

229 $ mkdir sqlite-arm 5) 进 入 SQLite 目 录 并 进 行 如 下 配 置 : $ cd sqlite / $./configure CC=arm-none-linux-gnueabi-gcc --prefix=/usr/local/src/s210x/project/12.11-sqlite/sqlite-arm --disable-tcl --host=arm-linux 6) 编 译 SQLite: $ make $ make install 7) 拷 贝 编 译 出 来 的 文 件 到 nfs 目 录 : $ cd /usr/local/src/s210x/project/12.11-sqlite $ cp -a sqlite-arm /opt/nfs 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig ethx xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 sqlite 下 载 到 s210x 实 验 平 台 : # mount -t nfs :/opt/nfs /tmp -o intr,nolock,rsize=1024,wsize=1024 # cp -a /tmp/sqlite-arm/* /usr/ 到 此,SQLite 数 据 库 移 植 完 成 下 面 介 绍 一 些 SQLite 基 本 命 令 : 1) 在 当 面 目 录 下 建 立 或 打 开 test.db 数 据 库, 并 进 入 sqlite 命 令 终 端,sqlite 命 令 终 端 以 sqlite> 前 缀 标 识 : # sqlite3 sqlite >.quit # 退 出 sqlite 的 命 令 # sqlite3 test.db # 创 建 数 据 库 SQLite version :39:23 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> 2) 创 建 名 为 film, 并 有 编 号 和 名 称 两 个 列 的 数 据 表 :

230 sqlite> create table film (number, name); 3) 向 数 据 表 film 中 添 加 编 号 为 1 名 称 为 aaa 以 及 编 号 为 2 名 称 为 bbb 的 条 目 : sqlite> insert into film values (1, 'aaa'); sqlite> insert into film values (2, 'bbb'); 4) 查 询 数 据 表 film 中 存 储 的 内 容 : sqlite> select * from film; 1 aaa 2 bbb 5) 退 出 SQLite: sqlite>.quit

231 第 十 三 章 linux 驱 动 程 序 开 发 本 章 节 主 要 介 绍 嵌 入 式 Linux 驱 动 程 序 的 编 写, 内 容 涵 盖 linux 字 符,LED, 串 口 通 信,LCD 显 示, 触 摸 屏 控 制,SD 卡, 以 太 网, 蓝 牙 通 信,WIFI 通 信,GPS 通 信,3G 通 信 实 验 等 驱 动 开 发, 通 过 本 章 节 的 学 习, 可 以 了 解 Linux 下 驱 动 程 序 的 开 发 方 法 13.1 Linux 简 单 字 符 驱 动 实 验 目 的 掌 握 嵌 入 式 简 单 字 符 驱 动 程 序 的 编 写, 编 译 和 运 行 熟 悉 linux 环 境 下 驱 动 模 块 的 加 载, 卸 载, 及 测 试 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Linux 设 备 驱 动 与 底 层 硬 件 直 接 打 交 道, 按 照 硬 件 设 备 的 具 体 工 作 方 式, 读 写 设 备 的 寄 存 器, 完 成 设 备 的 轮 询 中 断 处 理 DMA 通 信, 进 行 物 理 内 存 向 虚 拟 内 存 的 映 射 等, 最 终 让 通 信 设 备 能 收 发 数 据, 让 显 示 设 备 能 显 示 文 字 和 画 面, 让 存 储 设 备 能 记 录 文 件 和 数 据

232 图 Linux 设 备 驱 动 系 统 调 用 是 操 作 系 统 内 核 和 应 用 程 序 之 间 的 接 口, 设 备 驱 动 程 序 是 操 作 系 统 内 核 和 机 器 硬 件 之 间 的 接 口 设 备 驱 动 程 序 为 应 用 程 序 屏 蔽 了 硬 件 的 细 节, 这 样 在 应 用 程 序 看 来, 硬 件 设 备 只 是 一 个 设 备 文 件, 应 用 程 序 可 以 像 操 作 普 通 文 件 一 样 对 硬 件 设 备 进 行 操 作 用 户 进 程 利 用 系 统 调 用 在 对 设 备 文 件 进 行 诸 如 read/write 操 作 时, 系 统 调 用 通 过 设 备 文 件 的 主 设 备 号 找 到 相 应 的 设 备 驱 动 程 序, 然 后 读 取 这 个 数 据 结 构 相 应 的 函 数 指 针, 接 着 把 控 制 权 交 给 该 函 数 设 备 驱 动 程 序 的 特 点 ⑴ 核 心 代 码 : 设 备 驱 动 程 序 是 核 心 的 一 部 分, 像 核 心 中 其 他 的 代 码 一 样, 出 错 将 导 致 系 统 的 严 重 损 伤 一 个 编 写 不 当 的 设 备 驱 动 程 序 甚 至 能 够 使 系 统 崩 溃 导 致 文 件 系 统 的 破 坏 和 数 据 的 丢 失 ; ⑵ 标 准 接 口 : 设 备 驱 动 程 序 必 须 为 Linux 核 心 或 者 其 从 属 的 子 系 统 提 供 一 个 标 准 的 接 口 ( 比 如 open(),read() 等 等 ) ⑶ 核 心 机 制 : 设 备 驱 动 程 序 可 以 使 用 标 准 的 核 心 服 务 比 如 内 存 分 配 中 断 发 送 和 等 待 对 列 等 ; ⑷ 动 态 可 加 载 : 多 数 的 Linux 设 备 驱 动 程 序 可 以 在 核 心 模 块 发 出 加 载 请 求 时 进 行 加 载, 同 时 在 不 使 用 设 备 时 进 行 卸 载, 这 样 核 心 可 以 有 效 地 利 用 系 统 的 资 源 ⑸ 可 配 置 :Linux 设 备 驱 动 属 于 核 心 的 一 部 分, 用 户 可 以 根 据 自 己 的 需 要 进 行 配 置 来 选 择 适 合 自 己 的 驱 动 设 备 驱 动 的 分 类 Linux 下 设 备 驱 动 分 为 三 类 : 字 符 设 备 驱 动 块 设 备 驱 动 网 络 设 备 驱 动 设 备 驱 动 字 符 设 备 块 设 备 网 络 设 备 图 Linux 设 备 驱 动 分 类 字 符 设 备 是 指 设 备 发 送 和 接 收 数 据 以 字 符 的 形 式 进 行 Linux 下 的 设 备 驱 动 程 序 被 组 织 为 一 组 完

233 成 不 同 任 务 的 函 数 的 集 合, 通 过 这 些 函 数 使 得 Windows 的 设 备 操 作 犹 如 文 件 一 般 在 应 用 程 序 看 来, 硬 件 设 备 只 是 一 个 设 备 文 件, 应 用 程 序 可 以 像 操 作 普 通 文 件 一 样 对 硬 件 设 备 进 行 操 作, 如 open() close() read() write() 等 cdev 结 构 体 在 Linux2.6 内 核 中 cdev 结 构 体 描 述 字 符 设 备,cdev 结 构 体 的 定 义 如 下 : struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count; }; cdev 结 构 体 中 的 dev_t 成 员 定 义 了 设 备 号, 为 32 位, 其 中 高 12 位 为 主 设 备 号, 低 20 位 为 次 设 备 号 其 中,struct kobject 是 内 嵌 的 kobject 对 象 ; struct module 是 所 属 模 块 ; struct file_operations 为 文 件 操 作 结 构 体 使 用 以 下 宏 可 以 从 dev_t 获 得 主 设 备 号 和 次 设 备 号 : 引 用 MAJOR (dev_t dev); MINOR (dev_t dev); 而 使 用 下 面 宏 可 以 通 过 主 设 备 号 和 次 设 备 号 生 成 dev_t : 引 用 MKDEV (int major, int minor); file_operations 结 构 体 file_operations 结 构 体 中 的 成 员 函 数 是 字 符 设 备 驱 动 程 序 设 计 的 主 体 内 容, 这 些 函 数 实 际 会 在 应 用 程 序 进 行 Linux 的 open() write() read() close() 等 系 统 调 用 时 最 终 被 调 用 struct file_operations{ struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t(*read) (struct file *, char *, size_t, loff_t*); ssize_t(*write) (struct file *, const char *, size_t, loff_t*); int(*readdir) (struct file *, void *, filldir_t); unsigned int(*poll) (struct file *, struct poll_table_struct *); int(*ioctl) (struct inode*, struct file *, unsigned int, unsigned long); int(*mmap) (struct file *, struct vm_area_struct *); int(*open) (struct inode*, struct file *);

234 int(*flush) (struct file *); int(*release) (struct inode*, struct file *); int(*fsync) (struct file *, struct dentry*, intdatasync); int(*fasync) (int, struct file *, int); int(*lock) (struct file *, int, struct file_lock*); ssize_t(*readv) (struct file *, const struct iovec*, unsigned long, loff_t*); ssize_t(*writev) (struct file *, const struct iovec*, unsigned long, loff_t*); ssize_t(*sendpage) (struct file *, struct page *, int, size_t, loff_t*, int); long); }; unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned 其 中 在 该 结 构 体 中 的 各 个 成 员 函 数 详 解 如 下 : 1)llseek(file, offset, whence): 用 来 修 改 一 个 文 件 的 当 前 读 写 位 置, 并 将 新 位 置 返 回, 在 出 错 时, 这 个 函 数 返 回 一 个 负 值 2)read(file, buf, count, offset): 从 设 备 文 件 的 offset 处 开 始 读 出 count 个 字 节, 然 后 增 加 *offset 的 值 3)write(file, buf, count, offset): 从 设 备 文 件 的 offset 处 写 入 count 个 字 节, 然 后 增 加 *offset 的 值 4)ioctl(inode, file, cmd, arg): 向 一 个 硬 件 设 备 发 命 令, 对 设 备 进 行 控 制 5)mmap(file, vma): 将 设 备 空 间 映 射 到 进 程 地 址 空 间 6)open(inode, file): 打 开 并 初 始 化 设 备 7)release(inode, file): 关 闭 设 备 并 释 放 资 源 8)fsync(file, dentry): 实 现 内 存 与 设 备 之 间 的 同 步 通 信 9)fasync(file, on): 实 现 内 存 与 设 备 之 间 的 异 步 通 信 字 符 设 备 cdev 加 载 卸 载 模 块 加 载 函 数 模 块 卸 载 函 数 用 户 空 间 调 用 Linux 系 统 调 用 dev_t file_operations 调 用 read() ioctl() write() 字 符 设 备 驱 动 模 块 的 加 载 和 卸 载 图 Linux 字 符 设 备 驱 动 的 结 构 图 在 字 符 设 备 驱 动 的 加 载 当 中 实 现 设 备 号 的 申 请 和 cdev 的 注 册, 在 卸 载 当 中 实 现 设 备 号 的 释 放 和

235 cdev 的 注 销 常 见 的 设 备 结 构 体 加 载 函 数 和 卸 载 函 数 如 下 面 的 代 码 : struct xxx_dev /* 自 定 义 设 备 结 构 体 */ { struct cdev cdev; /*cdev 结 构 体 */... /* 特 定 设 备 的 特 定 数 据 */ }; static int init xxx_init(void) /* 设 备 驱 动 模 块 加 载 函 数 */ {... /* 申 请 设 备 号, 当 xxx_major 不 为 0 时, 表 示 静 态 指 定 ; 当 为 0 时, 表 示 动 态 申 请 */ if (xxx_major) result = register_chrdev_region(xxx_devno, 1, "DEV_NAME"); /* 静 态 申 请 设 备 号 */ else /* 动 态 申 请 设 备 号 */ { result = alloc_chrdev_region(&xxx_devno, 0, 1, " DEV_NAME "); xxx_major = MAJOR(xxx_devno); /* 获 得 申 请 的 主 设 备 号 */ } /* 初 始 化 cdev 结 构, 并 传 递 file_operations 结 构 指 针 */ cdev_init(&xxx_dev.cdev, &xxx_fops); dev->cdev.owner = THIS_MODULE; /* 指 定 所 属 模 块 */ err = cdev_add(&xxx_dev.cdev, xxx_devno, 1); /* 注 册 设 备 */ } static void exit xxx_exit(void) /* 模 块 卸 载 函 数 */ { cdev_del(&xxx_dev.cdev); /* 注 销 cdev*/ unregister_chrdev_region(xxx_devno, 1); /* 释 放 设 备 号 */ } 字 符 设 备 驱 动 的 file_operations 结 构 体 中 成 员 函 数 _operations 结 构 体 中 的 成 员 函 数 都 对 应 着 驱 动 程 序 的 接 口, 用 户 程 序 可 以 通 过 内 核 来 调 用 这 些 接 口, 从 而 控 制 设 备 大 多 数 字 符 设 备 驱 动 都 会 实 现 read() write() 和 ioctl() 函 数, 这 3 个 函 数 的 常 见 写 法 如 下 面 的 代 码 所 示 /* 文 件 操 作 结 构 体 */ static const struct file_operations xxx_fops = {

236 .owner = THIS_MODULE, /* 模 块 引 用, 任 何 时 候 都 赋 值 THIS_MODULE */.read = xxx_read, /* 指 定 设 备 的 读 函 数 */.write = xxx_write, /* 指 定 设 备 的 写 函 数 */.ioctl = xxx_ioctl, /* 指 定 设 备 的 控 制 函 数 */ }; /* 读 函 数 */ static ssize_t xxx_read(struct file *filp, char user *buf, size_t size,loff_t *ppos) {... if(size>8) copy_to_user(buf,...,...); /* 当 数 据 较 大 时, 使 用 copy_to_user(), 效 率 较 高 */ esle put_user(...,buf); /* 当 数 据 较 小 时, 使 用 put_user(), 效 率 较 高 */... } /* 写 函 数 */ static ssize_t xxx_write(struct file *filp, const char user *buf,size_t size, loff_t *ppos) {... if(size>8) copy_from_user(..., buf,...); /* 当 数 据 较 大 时, 使 用 copy_to_user(), 效 率 较 高 */ else get_user(..., buf); /* 当 数 据 较 小 时, 使 用 put_user(), 效 率 较 高 */... } /* ioctl 设 备 控 制 函 数 */ static long xxx_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {... switch (cmd) { case xxx_cmd1:... /* 命 令 1 执 行 的 操 作 */ break; case xxx_cmd1:... /* 命 令 2 执 行 的 操 作 */

237 break; default: return - EINVAL; /* 内 核 和 驱 动 程 序 都 不 支 持 该 命 令 时, 返 回 无 效 的 命 令 */ } return 0; } 文 件 操 作 结 构 体 xxx_fops 中 保 存 了 操 作 函 数 的 指 针 对 于 没 有 实 现 的 函 数, 被 赋 值 为 NULL xxx_fops 结 构 体 在 字 符 设 备 加 载 函 数 中, 作 为 cdev_init() 的 参 数, 与 cdev 建 立 了 关 联 设 备 驱 动 的 read() 和 write() 函 数 有 同 样 的 参 数 filp 是 文 件 结 构 体 的 指 针, 指 向 打 开 的 文 件 buf 是 来 自 用 户 空 间 的 数 据 地 址, 该 地 址 不 能 在 驱 动 程 序 中 直 接 读 取 size 是 要 读 的 字 节 ppos 是 读 写 的 位 置, 其 相 对 于 文 件 的 开 头 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 /13.1-hello_driver 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 hello_driver 程 序 : $ cd /usr/local/src/s210x/project/13.1-hello_driver/hello-test $ make $ make install $ make clean $ cd /usr/local/src/s210x/project/13.1-hello_driver/hello-driver $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth

238 xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 hello_driver 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./hello_test -l/home/app/hello_test # tftp -g r./hello_driver.ko -l/lib/modules/ /hello_driver.ko 5) 给 hello_test 添 加 可 执 行 权 限 : # cd /home/app/ # chmod 777 hello_test 6) 加 载 hello_driver 驱 动 : # insmod hello_driver The driver is insmoded successfully. 7) 运 行 hello_test 测 试 程 序 : #./hello_test [ ] open the description successfully. value=1: value=2: value=3: value=4: value=5: value=6: value=7: value=8: value=9: [ ] close the description successfully. 8) 查 看 / 卸 载 hello_driver 驱 动 : # lsmod hello_driver Live 0xbf # rmmod hello_driver The driver is rmmoded successfully

239 13.2 GPIO 驱 动 设 计 -LED 实 验 实 验 目 的 掌 握 嵌 入 式 GPIO 驱 动 程 序 的 编 写, 工 作 原 理 熟 悉 linux 环 境 下 LED 驱 动 程 序 的 编 写, 运 行 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 LED 硬 件 原 理 图 Linux 下 的 设 备 驱 动 程 序 即 是 对 具 体 硬 件 进 行 操 作 的 程 序, 是 操 作 系 统 内 核 和 机 器 硬 件 之 间 的 接 口 设 备 驱 动 程 序 为 应 用 程 序 屏 蔽 了 硬 件 的 细 节, 这 样 在 应 用 程 序 看 来, 硬 件 设 备 只 是 一 个 设 备 文 件, 应 用 程 序 可 以 象 操 作 普 通 文 件 一 样 对 硬 件 设 备 进 行 操 作 如 下 图 所 示, 为 s210x 开 发 平 台 的 LED 部 分 硬 件 原 理 图 如 下 : 图 LED 部 分 原 理 图 s210x 底 板 上 设 计 有 4 个 用 户 可 编 程 的 LED(D8~D11), 本 驱 动 实 验 中 我 们 四 个 灯 一 起 使 用 D8 D11 的 正 极 分 别 与 +3V3 相 连, 负 极 分 别 间 接 与 s210x 处 理 器 的 GPJ2(0) GPJ2(1) GPJ2(2)

240 GPJ2(3) 相 连, 即 GPJ2(0) GPJ2(1) GPJ2(2) GPJ2(3) 输 出 低 电 平 时,LED 亮 ; 输 出 高 电 平 时, LED 灭 Linux 系 统 下 LED 驱 动 的 编 写 设 备 驱 动 程 序 首 先 应 包 含 设 备 的 注 册 和 释 放 函 数, 即 static int init s5pv210_led_init(void) 和 static void exit s5pv210_led_exit(void) /* 模 块 的 初 始 化 */ static int init s5pv210_led_init(void) { int ret; ret = s5pv210_led_ctrl_init(); if(ret) { printk(kern_err "Apply: S5PV210_LED_init--Fail!!!/n"); return ret; } return 0; } /* 模 块 的 退 出 */ static void exit s5pv210_led_exit(void) { device_destroy(led_dev_class,device_node); class_destroy(led_dev_class); cdev_del(cdev_p); unregister_chrdev_region(num_dev,1); } s5pv210_led_init 函 数 调 用 s5pv210_led_ctrl_init() 函 数 来 注 册 设 备 的 驱 动 程 序 static int s5pv210_led_ctrl_init(void) { int err; struct device* temp=null; unsigned int gpio; /*GPIO 口 的 初 始 化 LED1,LED2,LED3,LED4, 设 置 为 输 出 */ for(gpio=s5pv210_gpj2(0);gpio<s5pv210_gpj2(4);gpio++) { s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1)); } /* 动 态 注 册 led_test 设 备,num_dev 为 动 态 分 配 出 来 的 设 备 号 ( 主 设 备 号 + 次 设 备 号 )*/

241 err=alloc_chrdev_region(&num_dev,0,1,device_list); if (err < 0) { printk(kern_err "LED: unable to get device name %d/n", err); return err; } /* 动 态 分 配 cdev 内 存 空 间 */ cdev_p = cdev_alloc(); cdev_p->ops = &s5pv210_led_ctrl_ops; /* 加 载 设 备 驱 动 */ err=cdev_add(cdev_p,num_dev,1); if(err){ printk(kern_err "LED: unable to add the device %d/n", err); return err; } /* 在 /sys/class 下 创 建 led_test 目 录 */ led_dev_class=class_create(this_module,device_list); if(is_err(led_dev_class)) { err=ptr_err(led_dev_class); goto unregister_cdev; } /* 基 于 /sys/class/led_test 和 /dev 下 面 创 建 led_light 设 备 文 件 */ temp=device_create(led_dev_class, NULL,num_dev, NULL, DEVICE_NODE); if(is_err(temp)) { err=ptr_err(temp); goto unregister_class; } return 0; unregister_class: class_destroy(led_dev_class); unregister_cdev: cdev_del(cdev_p); return err; } alloc_chrdev_region 函 数 是 动 态 分 配 设 备 号 ; cdev_alloc() 函 数 是 动 态 分 配 内 存 空 间 ; cdev_add() 函 数 为 动 态 加 载 驱 动 ;

242 class_create 函 数 是 在 /sys/class 下 创 建 设 备 类 型 ; device_create 函 数 是 基 于 类 的 基 础 上 创 建 设 备 文 件 static void exit leds_ctrl_exit(void) 函 数 是 在 我 们 使 用 完 此 设 备 后, 释 放 设 备 号 设 备 结 构 体 内 存 file_operations 结 构 体 是 一 个 函 数 指 针 集 合, 定 义 能 够 在 设 备 上 进 行 的 操 作, 比 如 open() read() write() release() ioctl() 操 作 驱 动 程 序 中 定 义 的 file_operations 结 构 体 如 下 : /* 定 义 具 体 的 文 件 操 作 */ static const struct file_operations s5pv210_led_ctrl_ops={.owner = THIS_MODULE,.open = s5pv210_led_open,.read =s5pv210_led_read,.write =s5pv210_led_write,.release =s5pv210_led_release, }; 变 量 open 定 义 的 s5pv210_led_open 用 于 打 开 LED 设 备, 变 量 release 定 义 的 s5pv210_led_release 用 于 释 放 LED 设 备 变 量 read 定 义 的 s5pv210_led_read 则 是 读 取 灯 的 状 态, 变 量 write 用 于 写 控 制 LED 灯 的 亮 灭, 其 具 体 定 义 如 下 : /* 读 取 LED 灯 的 状 态 */ static ssize_t s5pv210_led_read(struct file * file,char * buf,size_t count,loff_t * f_ops) { /* 从 用 户 空 间 读 取 数 据, 获 取 LED 灯 的 状 态 */ copy_to_user(buf, (char *)&led_status, sizeof(unsigned char)); return sizeof(unsigned char); } /* 定 义 实 现 LED 灯 的 写 操 作 */ static ssize_t s5pv210_led_write (struct file * file,const char * buf, size_t count,loff_t * f_ops) { unsigned char status; if(count==1) { /* 向 用 户 空 间 写 数 据, 如 果 写 失 败, 则 返 回 错 误 */ if(copy_from_user(&status, buf,sizeof(unsigned char))) return -EFAULT; set_led_status(status); return sizeof(unsigned char); }else return -EFAULT;

243 } 其 中 copy_to_user 和 copy_from_user 函 数 的 具 体 含 义 如 下 : unsigned long copy_to_user(void user *to, const void *from, unsigned long n) 功 能 : 从 内 核 空 间 拷 贝 一 块 儿 数 据 到 用 户 空 间, 只 能 用 于 用 户 空 间 ; To : 目 标 地 址, 这 个 地 址 是 用 户 空 间 的 地 址 ; From: 源 地 址, 这 个 地 址 是 内 核 空 间 的 地 址 ; N : 将 要 拷 贝 的 数 据 的 字 节 数 返 回 值 : 如 果 数 据 拷 贝 成 功, 则 返 回 零 ; 否 则, 返 回 没 有 拷 贝 成 功 的 数 据 字 节 数 unsigned long copy_from_user(void *to, const void user *from, unsigned long n) 功 能 : 从 用 户 空 间 拷 贝 数 据 到 内 核 空 间 To : 目 标 地 址, 这 个 地 址 是 内 核 空 间 的 地 址 ; From: 源 地 址, 这 个 地 址 是 用 户 空 间 的 地 址 ; 返 回 者 : 如 果 数 据 拷 贝 成 功, 则 返 回 零 ; 否 则, 返 回 没 有 拷 贝 成 功 的 数 据 字 节 数 关 于 LED 灯 状 态 的 控 制 代 码 如 下 : /* 设 置 LED 灯 的 状 态 */ static void set_led_status(unsigned char status) { /* 表 示 LED 灯 的 状 态 是 否 发 生 变 化 */ unsigned char led_status_changed; led_status_changed= led_status^(status & 0xF); /* 数 据 变 化 检 测 */ led_status=(status & 0xF); /* 如 果 4 个 LED 灯 的 状 态 发 生 了 变 化 */ if(led_status_changed!=0x00) { /* 判 断 是 否 改 变 LED1 灯 的 状 态 */ if(led_status_changed&led1) { if(led_status&led1) gpio_direction_output(s5pv210_gpj2(0),0); else gpio_direction_output(s5pv210_gpj2(0),1); }

244 /* 判 断 是 否 改 变 LED2 灯 的 状 态 */ if(led_status_changed&led2) { if(led_status&led2) gpio_direction_output(s5pv210_gpj2(1),0); else gpio_direction_output(s5pv210_gpj2(1),1); } /* 判 断 是 否 改 变 LED3 灯 的 状 态 */ if(led_status_changed&led3) { if(led_status&led3) gpio_direction_output(s5pv210_gpj2(2),0); else gpio_direction_output(s5pv210_gpj2(2),1); } /* 判 断 是 否 改 变 LED4 灯 的 状 态 */ if(led_status_changed&led4) { if(led_status&led4) gpio_direction_output(s5pv210_gpj2(3),0); else gpio_direction_output(s5pv210_gpj2(3),1); } } } 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project

245 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 /13.2-led_driver 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 led_driver 程 序 : $ cd /usr/local/src/s210x/project/13.2-led_driver/led_test $ make $ make install $ make clean $ cd /usr/local/src/s210x/project/13.2-led_driver/led_ctrl $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 led_driver 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./led_test -l/home/app/led_test # tftp -g r./led.ko -l/lib/modules/ /led.ko 5) 给 led_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 led_test 6) 加 载 led 驱 动 : # insmod led 7) 运 行 led_test: #./led_test led status:1 led status:2 led status:4 led status:8 led status:

246 led status:2 led status:4... 可 以 观 察 到 s210x 开 发 平 台 上 的 led1~led4 循 环 依 次 被 点 亮 13.3 按 键 驱 动 设 计 实 验 实 验 目 的 熟 悉 linux 环 境 下 按 键 驱 动 程 序 的 编 写, 测 试 及 运 行 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 按 键 电 路 原 理 按 键 同 样 使 用 GPIO 接 口, 但 按 键 本 身 需 要 外 部 的 输 入, 按 键 硬 件 驱 动 原 理 图 如 下 图 所 示 在 下 图 的 1 6 矩 阵 按 键 (SW4~SW9) 电 路 中, 使 用 6 个 输 入 (EINT2 EINT3 EINT4 EINT8 EINT9 和 EINT11) 图 按 键 电 路 按 键 入 口 对 应 的 核 心 板 接 口 电 路 如 下 图 所 示 :

247 图 核 心 板 接 口 电 路 按 键 入 口 对 应 于 核 心 板 的 GPHO 接 口, 当 其 中 一 个 SW 按 键 被 按 下, 通 过 查 询 方 式 就 可 以 检 测 到 是 哪 一 个 接 口 有 输 入 信 号, 从 而 控 制 相 应 的 操 作 以 上 的 讨 论 都 是 在 按 键 的 理 想 状 态 下 进 行 的, 但 实 际 的 按 键 动 作 会 在 短 时 间 ( 几 毫 秒 至 几 十 毫 秒 ) 内 产 生 信 号 抖 动 例 如, 当 按 键 被 按 下 时, 其 动 作 就 像 弹 簧 的 若 干 次 往 复 运 动, 将 产 生 几 个 脉 冲 信 号 一 次 按 键 操 作 将 会 产 生 若 干 次 按 键 中 断, 从 而 会 产 生 抖 动 现 象 因 此 驱 动 程 序 中 必 须 要 解 决 去 除 抖 动 所 产 生 的 毛 刺 信 号 的 问 题 Linux 系 统 下 按 键 驱 动 的 编 写 设 备 驱 动 程 序 首 先 应 包 含 设 备 的 注 册 和 释 放 函 数, 即 static int init s3c_button_init(void) 和 static void exit s3c_button_exit(void) /* 模 块 的 初 始 化 */ static int init s3c_button_init(void) { platform_device_register(&s3c_device_button); return platform_driver_register(&s3c_button_device_driver); } /* 模 块 的 退 出 */ static void exit s3c_button_exit(void) {

248 platform_driver_unregister(&s3c_button_device_driver); platform_device_unregister(&s3c_device_button); } 首 先 定 义 platform_device 函 数 接 着 注 册 platform_device 再 定 义 platform_driver, 最 后 注 册 platform_driver static struct platform_driver s3c_button_device_driver = {.probe = s3c_button_probe,.remove = s3c_button_remove,.suspend = s3c_button_suspend,.resume = s3c_button_resume,.driver = {.name = "s3c-button",.owner = THIS_MODULE, } static struct platform_device s3c_device_button = { };.name.id = -1, = "s3c-button", 在 s3c_button_probe 函 数 中 设 置 相 关 按 键 的 寄 存 器 : static int s3c_button_probe(struct platform_device *pdev) { int i; int ret; /* gph0_1 (power) */ ret = gpio_request(s5pv210_gph0(1), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(1) fail"); /* gph0_2 (menu) */ ret = gpio_request(s5pv210_gph0(2), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(2) fail"); /* gph0_3 (home) */ ret = gpio_request(s5pv210_gph0(3), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(3) fail"); /* gph0_4 (back) */ ret = gpio_request(s5pv210_gph0(4), "GPH0"); if(ret)

249 printk("button-smdkv210: request gpio GPH0(4) fail"); /* gph1_0 (vol-) */ ret = gpio_request(s5pv210_gph1(0), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(0) fail"); /* gph1_1 (vol+) */ ret = gpio_request(s5pv210_gph1(1), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(1) fail"); /* gph1_3 (camera) */ ret = gpio_request(s5pv210_gph1(3), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(3) fail"); s3c_gpio_setpull(s5pv210_gph0(1), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(1), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(2), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(2), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(3), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(3), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(4), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(4), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph1(0), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(0), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph1(1), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(1), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph1(3), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(3), S3C_GPIO_SFN(0)); s3c_button_history[0] = gpio_get_value(s5pv210_gph0(1)); s3c_button_history[1] = gpio_get_value(s5pv210_gph0(2)); s3c_button_history[2] = gpio_get_value(s5pv210_gph0(3)); s3c_button_history[3] = gpio_get_value(s5pv210_gph0(4)); s3c_button_history[4] = gpio_get_value(s5pv210_gph1(0));

250 s3c_button_history[5] = gpio_get_value(s5pv210_gph1(1)); s3c_button_history[6] = gpio_get_value(s5pv210_gph1(3));}; 再 开 启 定 时 器 定 时 扫 描 ; init_timer(&timer); timer.function = s3cbutton_timer_handler; timer.expires = jiffies + (HZ/100); add_timer(&timer); printk("s3c button Initialized!!\n"); return 0; 在 定 时 器 中 断 函 数 s3cbutton_timer_handler 中 判 断 相 应 IO 口 的 电 平, 达 到 监 控 按 键 的 作 用 static void s3cbutton_timer_handler(unsigned long data) { int flag; /* POWER */ flag = gpio_get_value(s5pv210_gph0(1)); if(flag!= s3c_button_history[0]) { if(flag) input_report_key(input, s3c_keycode[0], 0); else input_report_key(input, s3c_keycode[0], 1); s3c_button_history[0] = flag; } /* MENU */ flag = gpio_get_value(s5pv210_gph0(2)); if(flag!= s3c_button_history[1]) { if(flag) input_report_key(input, s3c_keycode[1], 0); else input_report_key(input, s3c_keycode[1], 1); s3c_button_history[1] = flag; } /* HOME */ flag = gpio_get_value(s5pv210_gph0(3)); if(flag!= s3c_button_history[2]) { if(flag) input_report_key(input, s3c_keycode[2], 0);

251 else input_report_key(input, s3c_keycode[2], 1); s3c_button_history[2] = flag; } /* BACK */ flag = gpio_get_value(s5pv210_gph0(4)); if(flag!= s3c_button_history[3]) { if(flag) input_report_key(input, s3c_keycode[3], 0); else input_report_key(input, s3c_keycode[3], 1); s3c_button_history[3] = flag; } /* VOLUME_DOWN */ flag = gpio_get_value(s5pv210_gph1(0)); if(flag!= s3c_button_history[4]) { if(flag) input_report_key(input, s3c_keycode[4], 0); else input_report_key(input, s3c_keycode[4], 1); s3c_button_history[4] = flag; } /* VOLUME_UP */ flag = gpio_get_value(s5pv210_gph1(1)); if(flag!= s3c_button_history[5]) { if(flag) input_report_key(input, s3c_keycode[5], 0); else input_report_key(input, s3c_keycode[5], 1); s3c_button_history[5] = flag; } /* CAMERA */ flag = gpio_get_value(s5pv210_gph1(3)); if(flag!= s3c_button_history[6]) { if(flag)

252 input_report_key(input, s3c_keycode[6], 0); else input_report_key(input, s3c_keycode[6], 1); s3c_button_history[6] = flag; } /* Kernel Timer restart */ mod_timer(&timer,jiffies + HZ/100); }; 向 内 核 申 请 一 个 input_dev, 再 对 其 作 些 简 单 的 初 始 化 然 后 驱 动 再 对 返 回 的 input_dev 作 进 一 步 的 初 始 化, 函 数 set_bit(ev_key, serkbd_dev->evbit) 用 来 设 定 其 支 持 的 事 件 input_register_device(serkbd_dev), 把 设 备 注 册 进 input 子 系 统 input = input_allocate_device(); if(!input) return -ENOMEM; set_bit(ev_key, input->evbit); for(i = 0; i < MAX_BUTTON_CNT; i++) set_bit(s3c_keycode[i], input->keybit); input->name = "s3c-button"; input->phys = "s3c-button/input0"; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; input->keycode = s3c_keycode; if(input_register_device(input)!= 0) { printk("s3c-button input register device fail!!\n"); input_free_device(input); return -ENODEV; } 由 于 按 键 驱 动 在 android 内 核 文 件 中 已 经 编 译 好, 源 码 存 放 的 路 径 为 /usr/local/src/s210x/x_210_android-2.3/kernel/arch/arm/mach-s5pv210, 因 此 本 实 验 只 需 要 编 写 按 键 测 试 程 序 进 行 测 试 即 可

253 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 /13.3-button_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 button_test 程 序 : $ cd /usr/local/src/s210x/project/13.3-button_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 button_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./button_test -l/home/app/button_test 5) 给 button_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 button_test 6) 运 行 button_test: #./button_test Event: time , code 139, value 1 Event: time , code 139, value 0 Event: time , code 102, value 1 Event: time , code 102, value 0 Event: time , code 158, value

254 Event: time , code 158, value 串 口 通 信 实 验 实 验 目 的 掌 握 嵌 入 式 串 口 通 信 的 工 作 原 理, 实 现 过 程 熟 悉 linux 环 境 下 串 口 通 信 程 序 的 编 写, 运 行 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 S5PV210 串 行 通 讯 (UART) 单 元 S5PV210 UART 单 元 提 供 了 三 个 独 立 的 异 步 串 行 通 信 接 口, 皆 可 工 作 于 中 断 和 DMA 模 式 使 用 系 统 时 钟 最 高 波 特 率 达 230.4Kbps, 如 果 使 用 外 部 设 备 提 供 的 时 钟, 可 以 达 到 更 高 的 速 率 每 一 个 UART 单 元 包 含 一 个 16 字 节 的 FIFO, 用 于 数 据 的 接 收 和 发 送 S5PV210 UART 支 持 可 编 程 波 特 率, 红 外 发 送 / 接 收, 一 个 或 两 个 停 止 位,5bit/6bit/ 7bit/ 或 8bit 数 据 宽 度 和 奇 偶 校 验 波 特 率 的 产 生 波 特 率 由 一 个 专 用 的 UART 波 特 率 分 频 寄 存 器 (UBRDIVn) 控 制, 计 算 公 式 如 下 : UBRDIVn =(int)( ULK/(bps x 16)) 1 或 者 UBRDIVn =(int)( PLK/(bps x 16)) 1 其 中 : 时 钟 选 用 ULK 还 是 PLK 由 UART 控 制 寄 存 器 UCONn[10] 的 状 态 决 定 如 果 UCONn[10]=0, 用 PLK 作 为 波 特 率 发 生, 否 则 选 用 ULK 做 波 特 率 发 生 UBRDIVn 的 值 必 须 在 1 到 (216-1) 之 间 例 如 :ULK 或 者 PLK 等 于 40MHz, 当 波 特 率 为 时, UBRDIVn = (int)( /( x 16) ) -1= (int)(21.7) -1= 21-1 = 20 UART 通 信 操 作

255 下 面 简 略 介 绍 UART 操 作, 关 于 数 据 发 送, 数 据 接 收, 中 断 产 生, 波 特 率 产 生, 轮 流 检 测 模 式, 红 外 模 式 和 自 动 流 控 制 的 详 细 介 绍, 请 参 照 相 关 教 材 和 数 据 手 册 发 送 数 据 帧 是 可 编 程 的 一 个 数 据 帧 包 含 一 个 起 始 位,5 到 8 个 数 据 位, 一 个 可 选 的 奇 偶 校 验 位 和 1 到 2 位 停 止 位, 停 止 位 通 过 行 控 制 寄 存 器 ULCONn 配 置 与 发 送 类 似, 接 收 帧 也 是 可 编 程 的 接 收 帧 由 一 个 起 始 位,5 到 8 个 数 据 位, 一 个 可 选 的 奇 偶 校 验 和 1 到 2 位 行 控 制 寄 存 器 ULCONn 里 的 停 止 位 组 成 接 收 器 还 可 以 检 测 溢 出 错, 奇 偶 校 验 错, 帧 错 误 和 传 输 中 断, 每 一 个 错 误 均 可 以 设 置 一 个 错 误 标 志 溢 出 错 误 (Overrun error) 是 指 已 接 收 到 的 数 据 在 读 取 之 前 被 新 接 收 的 数 据 覆 盖 奇 偶 校 验 错 是 指 接 收 器 检 测 到 的 校 验 和 与 设 置 的 不 符 帧 错 误 指 没 有 接 收 到 有 效 的 停 止 位 传 输 中 断 表 示 接 收 数 据 RxDn 保 持 逻 辑 0 超 过 一 帧 的 传 输 时 间 在 FIFO 模 式 下, 如 果 RxFIFO 非 空, 而 在 3 个 字 的 传 输 时 间 内 没 有 接 收 到 数 据, 则 产 生 超 时 UART 控 制 寄 存 器 1) UART 行 控 制 寄 存 器 ULCONn 该 寄 存 器 的 第 6 位 决 定 是 否 使 用 红 外 模 式, 位 5~3 决 定 校 验 方 式, 位 2 决 定 停 止 位 长 度, 位 1 和 0 决 定 每 帧 的 数 据 位 数 2) UART 控 制 寄 存 器 UCONn 该 寄 存 器 决 定 UART 的 各 种 模 式 UCONn[10]= 1:ULK 做 比 特 率 发 生 ;0:PLK 做 比 特 率 发 生 UCONn[9] = 1:Tx 中 断 电 平 触 发 ;0:Tx 中 断 脉 冲 触 发 UCONn[8] = 1:Rx 中 断 电 平 触 发 ;0:Rx 中 断 脉 冲 触 发 UCONn[7] = 1: 接 收 超 时 中 断 允 许 ;0: 接 收 超 时 中 断 不 允 许 UCONn[6] = 1: 产 生 接 收 错 误 中 断 ;0: 不 产 生 接 收 错 误 中 断 UCONn[5] = 1: 发 送 直 接 传 给 接 收 方 式 (Loopback); 0: 正 常 模 式 UCONn[4] = 1: 发 送 间 断 信 号 ;0: 正 常 模 式 发 送 UCONn[3:2] : 发 送 模 式 选 择 00: 不 允 许 发 送 ; 01: 中 断 或 查 询 模 式 10:DMA0 请 求 (UART0) DMA3 请 求 (UART2) 11:DMA1 请 求 (UART1) UCONn[1:0] : 接 收 模 式 选 择 00: 不 允 许 接 收 01: 中 断 或 查 询 模 式

256 10:DMA0 请 求 (UART0) DMA3 请 求 (UART2) 11:DMA1 请 求 (UART1) 3) UART FIFO 控 制 寄 存 器 UFCONn UFCONn[7:6] 00:Tx FIFO 寄 存 器 中 有 0 个 字 节 就 触 发 中 断 01:Tx FIFO 寄 存 器 中 有 4 个 字 节 就 触 发 中 断 10:Tx FIFO 寄 存 器 中 有 8 个 字 节 就 触 发 中 断 11:Tx FIFO 寄 存 器 中 有 0 个 字 节 就 触 发 中 断 UFCONn[5:4] 00:Rx FIFO 寄 存 器 中 有 0 个 字 节 就 触 发 中 断 01:Rx FIFO 寄 存 器 中 有 4 个 字 节 就 触 发 中 断 10:Rx FIFO 寄 存 器 中 有 8 个 字 节 就 触 发 中 断 11:Rx FIFO 寄 存 器 中 有 0 个 字 节 就 触 发 中 断 UFCONn[3]: 保 留 UFCONn[2] = 1:FIFO 复 位 清 零 Tx FIFO;0:FIFO 复 位 不 清 零 Tx FIFO UFCONn[1] = 1:FIFO 复 位 清 零 Rx FIFO;0:FIFO 复 位 不 清 零 Rx FIFO UFCONn[0] = 1: 允 许 FIFO 功 能 ;0: 不 允 许 FIFO 功 能 4) UART MODEM 控 制 寄 存 器 UMCONn(n=0 或 1) UMCONn[7:5] 保 留, 必 须 全 为 0 UMCONn[4] =1: 允 许 使 用 AFC 模 式 ; 0: 不 允 许 使 用 AFC UMCONn[3:1] 保 留, 必 须 全 为 0 UMCONn[0] =1: 激 活 nrts;0: 不 激 活 nrts 5) 发 送 寄 存 器 UTXH 和 接 收 寄 存 器 URXH 这 两 个 寄 存 器 存 放 着 发 送 和 接 收 的 数 据, 当 然 只 有 一 个 字 节,8 位 数 据 需 要 注 意 的 是 在 发 生 溢 出 错 误 的 时 候, 接 收 的 数 据 必 须 被 读 出 来, 否 则 会 引 发 下 次 溢 出 错 误 6) UART 串 口 电 路 本 教 学 实 验 平 台 的 电 路 中,UART 串 口 电 路 如 下 图 所 示, 只 采 用 两 根 接 线 RXD1 和 TXD1, 因 此 只 能 进 行 简 单 的 数 据 传 输 及 接 收 功 能

257 图 UART 电 路 图 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 / 13.4-uart_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 uart_test 程 序 : $ cd /usr/local/src/s210x/project/13.4-uart_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常

258 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 uart_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./uart_test -l/home/app/uart_test 5) 给 uart_test 添 加 可 执 行 权 限 : # cd /home/app/ # chmod 777 uart_test 6) 使 用 导 线 将 位 于 实 验 平 台 的 串 口 COM1 的 RXD 与 TXD( 由 于 封 装 的 原 因, 实 际 短 接 的 为 COM1 串 口 上 排 的 2,3 管 脚 ) 7) 运 行 uart_test, 根 据 提 示 在 minicom 下 输 入 一 些 字 符 串, 如 hello, 则 会 在 minicom 下 输 出 发 送 和 接 收 到 的 字 符 串 $./uart_test Enter The Sending Data :SEND : RECV : please Enter the next sending data : hello SEND : hello RECV : hello please Enter the next sending data : 如 果 收 到 的 字 符 串 和 输 入 的 字 符 串 一 致 则 表 明 实 验 成 功 13.5 LCD 显 示 实 验 实 验 目 的 掌 握 嵌 入 式 LCD 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 LCD 显 示 屏 的 工 作 原 理

259 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 LCD 的 工 作 原 理 要 使 一 块 LCD 正 常 的 显 示 文 字 或 图 像, 不 仅 需 要 LCD 驱 动 器, 而 且 还 需 要 相 应 的 LCD 控 制 器 在 通 常 情 况 下, 生 产 厂 商 把 LCD 驱 动 器 会 以 COF/COG 的 形 式 与 LCD 玻 璃 基 板 制 作 在 一 起, 而 LCD 控 制 器 则 是 由 外 部 的 电 路 来 实 现, 现 在 很 多 的 MCU 内 部 都 集 成 了 LCD 控 制 器, 如 S5PV210 等 通 过 LCD 控 制 器 就 可 以 产 生 LCD 驱 动 器 所 需 要 的 控 制 信 号 来 控 制 STN/TFT 屏 了 LCD 控 制 器 可 以 通 过 编 程 支 持 不 同 LCD 屏 的 要 求, 例 如 行 和 列 像 素 数, 数 据 总 线 宽 度, 接 口 时 序 和 刷 新 频 率 等 LCD 控 制 器 的 主 要 作 用, 是 将 定 位 在 系 统 存 储 器 中 的 显 示 缓 冲 区 中 的 LCD 图 像 数 据 传 送 到 外 部 LCD 驱 动 器, 并 产 生 必 要 的 控 制 信 号, 例 如 RGB_VSYNC, RGB_HSYNC, RGB_VCLK 等 如 下 图 所 示 是 S5PV210 的 LCD 控 制 器 内 部 结 构 框 图 如 下 : 图 LCD 控 制 器 结 构 框 图 主 要 由 VSFR, VDMA, VPRCS, VTIME 和 视 频 时 钟 产 生 器 几 个 模 块 组 成 : 1) VSFR 由 121 个 可 编 程 控 制 器 组, 一 套 gamma LUT 寄 存 器 组 ( 包 括 64 个 寄 存 器 ), 一 套 i80 命 令 寄 存 器 组 ( 包 括 12 个 寄 存 器 ) 和 5 块 256*32 调 色 板 存 储 器 组 成, 主 要 用 于 对 lcd 控 制 器 进 行 配 置 2) VDMA 是 LCD 专 用 的 DMA 传 输 通 道, 可 以 自 动 从 系 统 总 线 上 获 取 视 频 数 据 传 送 到 VPRCS, 无 需 CPU 干 涉 3) VPRCS 收 到 数 据 后 组 成 特 定 的 格 式 ( 如 16bpp 或 24bpp), 然 后 通 过 数 据 接 口 (RGB_VD, VEN_VD, V656_VD or SYS_VD) 传 送 到 外 部 LCD 屏 上 4) VTIME 模 块 由 可 编 程 逻 辑 组 成, 负 责 不 同 lcd 驱 动 器 的 接 口 时 序 控 制 需 求 VTIME 模 块 产 生 RGB_VSYNC, RGB_HSYNC, RGB_VCLK, RGB_VDEN, VEN_VSYNC 等 信 号

260 主 要 特 性 : 支 持 4 种 接 口 类 型 :RGB/i80/ITU 601(656)/YTU444 支 持 单 色 4 级 灰 度 16 级 灰 度 256 色 的 调 色 板 显 示 模 式 支 持 64K 和 16M 色 非 调 色 板 显 示 模 式 支 持 多 种 规 格 和 分 辨 率 的 LCD 虚 拟 屏 幕 最 大 可 达 16MB 5 个 256*32 位 调 色 板 内 存 支 持 透 明 叠 加 外 部 接 口 电 路 S5PV210 内 部 LCD 控 制 器 接 口 图 如 下 : 图 LCD 控 制 器 接 口 电 路 数 据 结 构 及 接 口 函 数 从 帧 缓 冲 设 备 驱 动 程 序 结 构 看, 该 驱 动 主 要 跟 fb_info 结 构 体 有 关, 该 结 构 体 记 录 了 帧 缓 冲 设 备 的 全 部 信 息, 包 括 设 备 的 设 置 参 数 状 态 以 及 对 底 层 硬 件 操 作 的 函 数 指 针 在 Linux 中, 每 一 个 帧 缓 冲 设 备 都 必 须 对 应 一 个 fb_info,fb_info 在 /linux/fb.h 中 的 定 义 如 下 :( 只 列 出 重 要 的 一 些 ) struct fb_info { int node; int flags;

261 struct fb_var_screeninfo var;/*lcd 可 变 参 数 结 构 体 */ struct fb_fix_screeninfo fix;/*lcd 固 定 参 数 结 构 体 */ struct fb_monspecs monspecs; /*LCD 显 示 器 标 准 */ struct work_struct queue; /* 帧 缓 冲 事 件 队 列 */ struct fb_pixmap pixmap; /* 图 像 硬 件 mapper*/ struct fb_pixmap sprite; /* 光 标 硬 件 mapper*/ struct fb_cmap cmap; /* 当 前 的 颜 色 表 */ struct fb_videomode *mode; /* 当 前 的 显 示 模 式 */ #ifdef CONFIG_FB_BACKLIGHT struct backlight_device *bl_dev;/* 对 应 的 背 光 设 备 */ struct mutex bl_curve_mutex; u8 bl_curve[fb_backlight_levels];/* 背 光 调 整 */ #endif #ifdef CONFIG_FB_DEFERRED_IO struct delayed_work deferred_work; struct fb_deferred_io *fbdefio; #endif struct fb_ops *fbops; /* 对 底 层 硬 件 操 作 的 函 数 指 针 */ struct device *device; struct device *dev; /*fb 设 备 */ int class_flag; #ifdef CONFIG_FB_TILEBLITTING struct fb_tile_ops *tileops; /* 图 块 Blitting*/ #endif char iomem *screen_base; /* 虚 拟 基 地 址 */ unsigned long screen_size; /*LCD IO 映 射 的 虚 拟 内 存 大 小 */ void *pseudo_palette; /* 伪 16 色 颜 色 表 */ #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 u32 state; /*LCD 的 挂 起 或 恢 复 状 态 */ void *fbcon_par; void *par; }; 其 中, 比 较 重 要 的 成 员 有 struct fb_var_screeninfo var struct fb_fix_screeninfo fix 和 struct fb_ops *fbops, 他 们 也 都 是 结 构 体 fb_var_screeninfo 结 构 体 主 要 记 录 用 户 可 以 修 改 的 控 制 器 的 参 数, 比 如 屏 幕 的 分 辨 率 和 每 个 像 素 的 比 特 数 等, 该 结 构 体 定 义 如 下 : struct fb_var_screeninfo {

262 u32 xres; /* 可 见 屏 幕 一 行 有 多 少 个 像 素 点 */ u32 yres; /* 可 见 屏 幕 一 列 有 多 少 个 像 素 点 */ u32 xres_virtual; /* 虚 拟 屏 幕 一 行 有 多 少 个 像 素 点 */ u32 yres_virtual; /* 虚 拟 屏 幕 一 列 有 多 少 个 像 素 点 */ u32 xoffset; /* 虚 拟 到 可 见 屏 幕 之 间 的 行 偏 移 */ u32 yoffset; /* 虚 拟 到 可 见 屏 幕 之 间 的 列 偏 移 */ }; u32 bits_per_pixel; /* 每 个 像 素 的 位 数 即 BPP*/ u32 grayscale; /* 非 0 时, 指 的 是 灰 度 */ struct fb_bitfield red; /*fb 缓 存 的 R 位 域 */ struct fb_bitfield green; /*fb 缓 存 的 G 位 域 */ struct fb_bitfield blue; /*fb 缓 存 的 B 位 域 */ struct fb_bitfield transp; /* 透 明 度 */ u32 nonstd; /*!= 0 非 标 准 像 素 格 式 */ u32 activate; u32 height; /* 高 度 */ u32 width; /* 宽 度 */ u32 accel_flags; /* 定 时 : 除 了 pixclock 本 身 外, 其 他 的 都 以 像 素 时 钟 为 单 位 */ u32 pixclock; /* 像 素 时 钟 ( 皮 秒 )*/ u32 left_margin; /* 行 切 换, 从 同 步 到 绘 图 之 间 的 延 迟 */ u32 right_margin; /* 行 切 换, 从 绘 图 到 同 步 之 间 的 延 迟 */ u32 upper_margin; /* 帧 切 换, 从 同 步 到 绘 图 之 间 的 延 迟 */ u32 lower_margin; /* 帧 切 换, 从 绘 图 到 同 步 之 间 的 延 迟 */ u32 hsync_len; /* 水 平 同 步 的 长 度 */ u32 vsync_len; /* 垂 直 同 步 的 长 度 */ u32 sync; u32 vmode; u32 rotate; u32 reserved[5]; /* 保 留 */ 而 fb_fix_screeninfo 结 构 体 又 主 要 记 录 用 户 不 可 以 修 改 的 控 制 器 的 参 数, 比 如 屏 幕 缓 冲 区 的 物 理 地 址 和 长 度 等, 该 结 构 体 的 定 义 如 下 : struct fb_fix_screeninfo { char id[16]; /* 字 符 串 形 式 的 标 示 符 */ unsigned long smem_start; /*fb 缓 存 的 开 始 位 置 */ u32 smem_len; /*fb 缓 存 的 长 度 */ u32 type; /* 看 FB_TYPE_* */ u32 type_aux; /* 分 界 */ u32 visual; /* 看 FB_VISUAL_* */

263 u16 xpanstep; /* 如 果 没 有 硬 件 panning 就 赋 值 为 0 */ u16 ypanstep; /* 如 果 没 有 硬 件 panning 就 赋 值 为 0 */ u16 ywrapstep; /* 如 果 没 有 硬 件 ywrap 就 赋 值 为 0 */ u32 line_length; /* 一 行 的 字 节 数 */ unsigned long mmio_start; /* 内 存 映 射 IO 的 开 始 位 置 */ u32 mmio_len; /* 内 存 映 射 IO 的 长 度 */ u32 accel; u16 reserved[3]; /* 保 留 */ }; fb_ops 结 构 体 是 对 底 层 硬 件 操 作 的 函 数 指 针, 该 结 构 体 中 定 义 了 对 硬 件 的 操 作 有 :( 这 里 只 列 出 了 常 用 的 操 作 ) struct fb_ops { struct module *owner; // 检 查 可 变 参 数 并 进 行 设 置 int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); // 根 据 设 置 的 值 进 行 更 新, 使 之 有 效 int (*fb_set_par)(struct fb_info *info); // 设 置 颜 色 寄 存 器 int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); // 显 示 空 白 int (*fb_blank)(int blank, struct fb_info *info); // 矩 形 填 充 void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); // 复 制 数 据 void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); // 图 形 填 充 void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); }; LCD 参 数 配 置 在 S5PV210 中,LCD 控 制 器 被 集 成 在 芯 片 的 内 部 作 为 一 个 相 对 独 立 的 单 元, 所 以 Linux 把 它 看 做 是 一 个 平 台 设 备, 故 在 内 核 代 码 /kernel/arch/armmach-s5pv210/samsung 中 定 义 有 LCD 相 关 的 平 台 设 备 及 资 源, 代 码 如 下 : /* LCD Controller */ //LCD 控 制 器 的 资 源 信 息 static struct resource s3cfb_resource [] = { [0] = {.start = S5P_PA_LCD, // 控 制 器 IO 端 口 开 始 地 址 (0xf )

264 .end = S5P_PA_LCD + S5P_SZ_LCD - 1,// 控 制 器 IO 端 口 结 束 地 址 (1M).flags = IORESOURCE_MEM,// 标 识 为 LCD 控 制 器 IO 端 口, 在 驱 动 中 引 用 这 个 就 表 示 引 用 IO 端 口 }, [1] = {.start = IRQ_LCD1,//LCD 中 断.end = IRQ_LCD1,.flags = IORESOURCE_IRQ,// 标 识 为 LCD 中 断 } }; static u64 fb_dma_mask = 0xffffffffUL; struct platform_device s3c_device_fb = {.name = "s3cfb",// 作 为 平 台 设 备 的 LCD 设 备 名.id = -1,.num_resources = ARRAY_SIZE(s3cfb_resource),// 资 源 数 量.resource = s3cfb_resource,// 引 用 上 面 定 义 的 资 源.dev = {.dma_mask = &fb_dma_mask,.coherent_dma_mask = 0xffffffffUL } }; EXPORT_SYMBOL(s3c_device_fb); 除 此 之 外, Linux 还 在 /arch/arm/mach-s5pv210/ 中 为 LCD 平 台 设 备 定 义 了 一 个 s3c_platform_fb 结 构 体, 该 结 构 体 主 要 是 记 录 LCD 的 硬 件 参 数 信 息 ( 比 如 该 结 构 体 的 s3cfb_lcdy 成 员 结 构 中 就 用 于 记 录 LCD 的 屏 幕 尺 寸 屏 幕 信 息 可 变 的 屏 幕 参 数 LCD 配 置 寄 存 器 等 ), 这 样 在 写 驱 动 的 时 候 就 直 接 使 用 这 个 结 构 体 下 面, 我 们 来 看 一 下 内 核 是 如 果 使 用 这 个 结 构 体 的 在 /arch/arm/mach-s5pv210/dev-lcd.c 中 定 义 有 : /* LCD driver info */ static struct s3c_platform_fb lte480wv_fb_data initdata = {.width = 800,// 屏 幕 宽 度.height = 480,// 屏 幕 高 度 // 以 下 一 些 参 数 在 上 面 的 时 序 图 分 析 中 讲 到 过, 各 参 数 的 值 请 跟 据 具 体 的 LCD 屏 数 据 手 册 结 合 上 面 时 序 分 析 来 设 定. freq = 60,// 像 素 时 钟.bpp = 32,// 色 位 模 式. h_fp = 160,// 行 切 换, 从 同 步 到 绘 图 之 间 的 延 迟. h_bp = 160,// 行 切 换, 从 绘 图 到 同 步 之 间 的 延 迟. h_sw = 2,// 水 平 同 步 的 长 度. v_fp = 12,// 帧 切 换, 从 同 步 到 绘 图 之 间 的 延 迟

265 . v_fp= 23,// 帧 切 换, 从 绘 图 到 同 步 之 间 的 延 迟. v_sw = 2,// 垂 直 同 步 的 长 度 }; static struct s3c_platform_fb lte480wv_fb_data initdata = {.hw_ver = 0x62,.nr_wins = 5,.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,.swap = FB_SWAP_WORD FB_SWAP_HWORD,.lcd = &lte480wv,.cfg_gpio = s3cfb_cfg_gpio, };.backlight_on = s3cfb_backlight_on,.backlight_off = s3cfb_backlight_off,.lcd_on = s3cfb_lcd_on,.lcd_off = s3cfb_lcd_off, LCD 硬 件 的 配 置 信 息, 这 些 参 数 要 根 据 具 体 的 LCD 屏 进 行 设 置 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 13 章 / 13.5-lcd_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 lcd_test 程 序 : $ cd /usr/local/src/s210x/project/13.5-lcd_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth

266 xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 lcd_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./lcd_test -l/home/app/lcd_test 5) 给 lcd_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 lcd_test 6) 运 行 lcd_test $./lcd_test Framebuffer:800 * 480 Bits: 32 Draw retangle Draw square Draw circle 运 行 lcd_test 程 序 后, 可 以 在 显 示 屏 上 观 察 到 每 隔 5 秒 钟 依 次 画 出 长 方 形, 正 方 形, 圆 形 13.6 触 摸 屏 采 集 实 验 实 验 目 的 掌 握 嵌 入 式 触 摸 屏 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 触 摸 屏 屏 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 电 容 式 触 摸 屏 简 介

267 电 容 式 触 摸 屏 是 利 用 人 体 的 电 流 感 应 进 行 工 作 的 电 容 式 触 摸 屏 的 感 应 屏 是 一 块 四 层 复 合 玻 璃 屏, 玻 璃 屏 的 内 表 面 和 夹 层 各 涂 有 一 层 导 电 层, 最 外 层 是 一 薄 层 矽 土 玻 璃 保 护 层 当 我 们 用 手 指 触 摸 在 感 应 屏 上 的 时 候, 人 体 的 电 场 让 手 指 和 和 触 摸 屏 表 面 形 成 一 个 耦 合 电 容, 对 于 高 频 电 流 来 说, 电 容 是 直 接 导 体, 于 是 手 指 从 接 触 点 吸 走 一 个 很 小 的 电 流 这 个 电 流 分 从 触 摸 屏 的 四 角 上 的 电 极 中 流 出, 并 且 流 经 这 四 个 电 极 的 电 流 与 手 指 到 四 角 的 距 离 成 正 比, 控 制 器 通 过 对 这 四 个 电 流 比 例 的 精 确 计 算, 得 出 触 摸 点 的 位 置 FT5406 硬 件 结 构 及 特 性 FT5x06 系 列 ICs 是 单 芯 片 电 容 式 触 摸 屏 控 制 器 IC, 带 有 一 个 内 置 的 8 位 微 控 制 器 单 元 (MCU) 采 用 互 电 容 的 方 法, 在 配 合 的 相 互 的 电 容 式 触 摸 面 板, 它 支 持 真 正 的 多 点 触 摸 功 能 FT5x06 具 有 用 户 友 好 的 输 入 的 功 能, 这 可 以 应 用 在 许 多 便 携 式 设 备, 例 如 蜂 窝 式 电 话, 移 动 互 联 网 设 备, 上 网 本 和 笔 记 本 个 人 电 脑 如 下 是 FT5406 的 Touch 接 口 功 能 框 图 如 下 : 图 Touch 接 口 功 能 框 图 外 部 接 口 FT5406 内 部 Touch 外 部 接 口 如 下 图 所 示 : 图 Touch 外 部 接 口

268 从 FT5X06 的 datasheet 中, 我 们 可 以 看 到,FT5X06 既 可 以 工 作 的 SPI 的 接 口 方 式, 也 可 以 工 作 在 I2C 的 接 口 方 式, 不 管 工 作 在 SPI, 还 是 工 作 在 I2C, 从 硬 件 的 接 口 设 计 上 来 说, 这 下 面 几 个 控 制 口, 都 是 需 要 要 接 的 1): INT 引 脚, 这 个 脚 是 一 个 中 端 信 号, 它 用 来 通 知 HOST 端 FT5X06 已 经 准 备 好, 可 以 进 行 读 操 作 了 2): WAKE 引 脚 : 这 个 功 能 主 要 的 作 用 是 将 FT5X06 从 睡 眠 状 态 转 换 到 工 作 状 态 3): /RST 引 脚 :FT5X06 的 芯 片 复 位 信 号 根 据 FT5406 数 据 手 册 上 的 指 令, 我 们 先 了 解 下 驱 动 如 何 实 现 电 容 屏 的 多 点 触 摸, 其 实 很 简 单, 主 要 需 要 触 摸 屏 IC FT5406 能 够 捕 获 多 点 数 据, 这 点 电 容 屏 基 本 多 能 支 持 到 捕 获 2 点 以 上, 而 FT5406 可 以 捕 获 5 个 触 摸 点, 编 写 驱 动 时, 只 要 去 获 取 这 几 个 点 的 数 据, 然 后 上 报 就 可 以 了 数 据 结 构 及 接 口 函 数 input.h 中 定 义 了 struct input_dev 结 构, 它 表 示 Input 驱 动 程 序 的 各 种 信 息, 对 于 Event 设 备 分 为 同 步 设 备 键 盘 相 对 设 备 ( 鼠 标 ) 绝 对 设 备 ( 触 摸 屏 ) 等 input_dev 中 定 义 并 归 纳 了 各 种 设 备 的 信 息, 例 如 按 键 相 对 设 备 绝 对 设 备 杂 项 设 备 LED 声 音 设 备, 强 制 反 馈 设 备 开 关 设 备 等 struct ft5x0x_ts_data { struct input_dev *input_dev; struct ts_event event; struct work_struct pen_event_work; struct workqueue_struct *ts_workqueue; struct early_suspend early_suspend; }; struct input_dev { const char *name; // 设 备 名 称 const char *phys; // 设 备 文 件 节 点 const char *uniq; // 统 一 的 ID struct input_id id; // 设 备 ID unsigned long evbit[bits_to_longs(ev_cnt)]; unsigned long keybit[bits_to_longs(key_cnt)]; unsigned long relbit[bits_to_longs(rel_cnt)]; unsigned long absbit[bits_to_longs(abs_cnt)]; unsigned long mscbit[bits_to_longs(msc_cnt)]; unsigned long ledbit[bits_to_longs(led_cnt)]; unsigned long sndbit[bits_to_longs(snd_cnt)]; unsigned long ffbit[bits_to_longs(ff_cnt)]; // 设 备 所 支 持 的 事 件 // 按 键 值 存 放 表 // 相 对 坐 标 值 存 放 表 // 绝 对 坐 标 值 存 放 表 // 其 它 事 件 类 型 //LED 设 备 // 声 音 设 备 // 强 制 反 馈 设 备

269 unsigned long swbit[bits_to_longs(sw_cnt)]; // 开 关 设 备 unsigned int keycodemax; // 按 键 码 的 最 大 值 unsigned int keycodesize; // 按 键 码 的 大 小 void *keycode; // 按 键 码 int (*setkeycode)(struct input_dev *dev, unsigned int scancode, unsigned int keycode); // 可 选 的 方 法 来 改 变 当 前 的 keymap, 用 来 修 改 少 量 的 keymaps 如 果 不 使 用, 则 会 有 默 认 的 途 径 来 使 用 int (*getkeycode)(struct input_dev *dev, unsigned int scancode, unsigned int *keycode); // 可 选 的 方 法 来 恢 复 (retrieve) 当 前 的 keymap struct ff_device *ff; // 如 果 设 备 支 持 力 反 馈, 则 这 个 结 构 体 要 关 联 unsigned int repeat_key; // 重 复 按 键 的 键 值 struct timer_list timer; // 定 时 器 int sync; int abs[abs_cnt]; // 来 自 绝 对 轴 的 当 前 值 int rep[rep_max + 1]; // 存 放 重 复 按 键 时 的 延 时, 系 统 依 靠 这 个 延 时 时 间 来 判 断 重 复 按 键 unsigned long key[bits_to_longs(key_cnt)]; // 设 备 的 按 键 的 当 前 状 态 unsigned long led[bits_to_longs(led_cnt)]; // 设 备 的 leds 的 当 前 状 态 unsigned long snd[bits_to_longs(snd_cnt)]; // 音 效 的 当 前 状 态 unsigned long sw[bits_to_longs(sw_cnt)]; // 设 备 开 关 的 当 前 状 态 int absmax[abs_cnt]; int absmin[abs_cnt]; int absfuzz[abs_cnt]; int absflat[abs_cnt]; int absres[abs_cnt]; // 最 大 值, 用 于 绝 对 设 备 // 最 大 值, 用 于 绝 对 设 备 // 噪 声 大 小, 不 需 要 可 设 为 0, 表 示 获 得 的 值 是 准 确 的 // 中 心 位 置, 不 需 要 可 设 为 0, 表 示 获 得 的 值 是 准 确 的 int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); int (*flush)(struct input_dev *dev, struct file *file); int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); // 上 报 events 的 入 口 struct input_handle *grab; spinlock_t event_lock; struct mutex mutex; unsigned int users; bool going_away; struct device dev;

270 }; struct list_head h_list; struct list_head node; //FT5406 设 备 信 息 结 构 体 typedef struct ft5x0x_ts_data{ }; int irq; // 中 断 号 unsigned int pwren_pin; unsigned int touch_key; struct input_dev *input; struct input_dev *input_key; struct i2c_client *client; // 设 备 的 input handles 的 列 表 // 用 来 在 input_dev_list 中 放 置 设 备 // 电 源 使 能 pin,gpio 地 址 //touch 设 备 信 息 //touch key 设 备 信 息 //i2c 设 备 信 息 struct ts_event event; // 坐 标 信 息 struct work_struct pen_event_work; struct workqueue_struct *ts_workqueue; struct early_suspend early_suspend; // 触 摸 屏 事 件 结 构 体, 多 点 触 控 最 多 支 持 5 个 点 struct ts_event { }; u16 au16_x[cfg_max_touch_points]; u16 au16_y[cfg_max_touch_points]; u8 au8_touch_event[cfg_max_touch_points]; u8 au8_finger_id[cfg_max_touch_points]; u16 pressure; u8 touch_point; #if CFG_SUPPORT_TOUCH_KEY int tsp_keycodes[cfg_numofkeys] ={ //x coordinate //y coordinate Android & linux 系 统 与 应 用 开 发 //touch event: 0 -- down; 1-- contact; 2 -- contact //touch ID KEY_MENU, KEY_HOME, KEY_BACK, KEY_SEARCH }; char *tsp_keyname[cfg_numofkeys] = { "Menu", "Home", "Back", "Search"

271 }; 参 数 设 置 在 此 实 验 平 台 中, 使 用 到 的 触 摸 屏 是 FT5406, 根 据 触 屏 具 体 信 息 设 置 如 下 参 数 值, 代 码 在 /drivers/input/touchscreen/ft5x06_ts.h 中 : #define CFG_SUPPORT_AUTO_UPG /*0*/0 // 这 里 要 设 置 1 #define CFG_SUPPORT_UPDATE_PROJECT_SETTING 0 #define CFG_SUPPORT_TOUCH_KEY 0/*1*/ //touch key, HOME, SEARCH, RETURN etc #define CFG_SUPPORT_READ_LEFT_DATA 0 #define CFG_DBG_RAW_DATA_READ 0 #define CFG_MAX_TOUCH_POINTS 5 #define CFG_NUMOFKEYS 4 #define CFG_FTS_CTP_DRIVER_VERSION "2.0" #define SCREEN_MAX_X 1728 #define SCREEN_MAX_Y 1024 #define PRESS_MAX 255 #define CFG_POINT_READ_BUF (3 + 6 * (CFG_MAX_TOUCH_POINTS)) #define FT5X0X_NAME "ft5x0x_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"// #define KEY_PRESS 1 #define KEY_RELEASE 0 enum ft5x0x_ts_regs { FT5X0X_REG_THGROUP = 0x80, /* touch threshold, related to sensitivity */ FT5X0X_REG_THPEAK = 0x81, FT5X0X_REG_THCAL = 0x82, FT5X0X_REG_THWATER = 0x83, FT5X0X_REG_THTEMP = 0x84, FT5X0X_REG_THDIFF = 0x85, FT5X0X_REG_CTRL = 0x86, FT5X0X_REG_TIMEENTERMONITOR = 0x87, FT5X0X_REG_PERIODACTIVE = 0x88, /* report rate */ FT5X0X_REG_PERIODMONITOR = 0x89, FT5X0X_REG_HEIGHT_B = 0x8a, FT5X0X_REG_MAX_FRAME = 0x8b, FT5X0X_REG_DIST_MOVE = 0x8c, FT5X0X_REG_DIST_POINT = 0x8d, FT5X0X_REG_FEG_FRAME = 0x8e, FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f, FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,

272 FT5X0X_REG_SINGLE_CLICK_TIME = 0x91, FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92, FT5X0X_REG_UP_DOWN_OFFSET = 0x93, FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94, FT5X0X_REG_DISTANCE_UP_DOWN = 0x95, FT5X0X_REG_ZOOM_DIS_SQR = 0x96, }; FT5X0X_REG_RADIAN_VALUE =0x97, FT5X0X_REG_MAX_X_HIGH = 0x98, FT5X0X_REG_MAX_X_LOW = 0x99, FT5X0X_REG_MAX_Y_HIGH = 0x9a, FT5X0X_REG_MAX_Y_LOW = 0x9b, FT5X0X_REG_K_X_HIGH = 0x9c, FT5X0X_REG_K_X_LOW = 0x9d, FT5X0X_REG_K_Y_HIGH = 0x9e, FT5X0X_REG_K_Y_LOW = 0x9f, FT5X0X_REG_AUTO_CLB_MODE = 0xa0, FT5X0X_REG_LIB_VERSION_H = 0xa1, FT5X0X_REG_LIB_VERSION_L = 0xa2, FT5X0X_REG_CIPHER = 0xa3, FT5X0X_REG_MODE = 0xa4, FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */ FT5X0X_REG_FIRMID = 0xa6, /* Firmware version */ FT5X0X_REG_STATE = 0xa7, FT5X0X_REG_FT5201ID = 0xa8, FT5X0X_REG_ERR = 0xa9, FT5X0X_REG_CLB = 0xaa, //FT5X0X_REG_PMODE #define PMODE_ACTIVE 0x00 #define PMODE_MONITOR 0x01 #define PMODE_STANDBY 0x02 #define PMODE_HIBERNATE 0x03 #ifndef ABS_MT_TOUCH_MAJOR #define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */ #define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */ #define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */ #define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */ #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */

273 #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ #define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */ #endif /* ABS_MT_TOUCH_MAJOR */ #ifndef ABS_MT_TRACKING_ID #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ #endif 接 口 函 数 触 摸 屏 驱 动 程 序 ft5x06_ts.c, 首 先 实 现 加 载 和 卸 载 部 分, 在 驱 动 加 载 部 分, 我 们 主 要 做 的 事 情 是 : 启 用 ADC 所 需 要 的 时 钟 映 射 IO 口 初 始 化 寄 存 器 申 请 中 断 初 始 化 输 入 设 备 将 输 入 设 备 注 册 到 输 入 子 系 统 这 种 方 式 会 告 诉 其 他 的 输 入 系 统 中 的 设 备 当 前 注 册 的 是 什 么, 会 产 生 什 么 events 或 者 是 被 这 个 输 入 设 备 接 受 什 么 static int ft5406_ts_probe(struct platform_device * pdev) { struct i2c_adapter * adapter; struct i2c_client * client; struct i2c_board_info info; int ret; adapter = i2c_get_adapter(ft5406_i2c_bus); if(adapter == NULL) return -ENODEV; memset(&info, 0, sizeof(struct i2c_board_info)); info.addr = I2C_CTPM_ADDRESS; strlcpy(info.type, "ft5406-iic", I2C_NAME_SIZE); client = i2c_new_device(adapter, &info); if(!client) { printk("unable to add I2C device for 0x%x\n", info.addr); return -ENODEV; } i2c_put_adapter(adapter); ret = i2c_add_driver(&ft5406_iic_driver); if(ret) { printk("ft5406 iic add driver error!\r\n"); return ret;

274 } return 0; } // 是 否 支 持 多 点 触 控 // 通 过 set bit 来 设 置 input_dev 的 相 关 的 bit, 这 里 就 要 看 自 己 的 设 备 中 到 底 是 使 用 哪 些 set_bit(abs_mt_touch_major, input_dev->absbit); set_bit(abs_mt_position_x, input_dev->absbit); set_bit(abs_mt_position_y, input_dev->absbit); set_bit(abs_mt_width_major, input_dev->absbit); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, TOUCH_X, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, TOUCH_Y, 0, 0); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0); input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 5, 0, 0); set_bit(ev_key, input_dev->evbit); set_bit(ev_abs, input_dev->evbit); // 注 册 touch 设 备 input_dev->name = FT5X0X_NAME; //dev_name(&client->dev) err = input_register_device(input_dev); if (err) { dev_err(&client->dev,"ft5x0x_ts_probe: failed to register input device: %s\n", dev_name(&client->dev)); goto exit_input_register_device_failed; } // 按 键 设 备 初 始 化 #if CFG_SUPPORT_TOUCH_KEY int ft5x0x_touch_key_process(struct input_dev *dev, int x, int y, int touch_event) { int i; int key_id; if ( y < 150 && y > 90)//103 { key_id = 2; }

275 else if ( y < 90 &&y > 60)//73 { key_id = 0; } else if ( y < 60 && y > 30)//43 { key_id = 1; } else if (y < 30)//0 { key_id = 3; } else { key_id = 0xf; } for(i = 0; i <CFG_NUMOFKEYS; i++ ) { if(tsp_keystatus[i]) { input_report_key(dev, tsp_keycodes[i], 0); //printk("[fts] %s key is release. Keycode : %d\n", tsp_keyname[i], tsp_keycodes[i]); tsp_keystatus[i] = KEY_RELEASE; } else if( key_id == i ) { if( touch_event == 0) // detect { input_report_key(dev, tsp_keycodes[i], 1); //printk( "[FTS] %s key is pressed. Keycode : %d\n", tsp_keyname[i], tsp_keycodes[i]); tsp_keystatus[i] = KEY_PRESS; } } } return 0; } #endif

276 触 摸 屏 驱 动 程 序 ft5x06_ts..c, 首 先 实 现 加 载 和 卸 载 部 分, 在 驱 动 加 载 部 分, 我 们 主 要 做 的 事 情 是 : 启 用 AD static void ft5x0x_ts_pen_irq_work(struct work_struct *work) { int ret = -1; #if CFG_SUPPORT_READ_LEFT_DATA do { ret = ft5x0x_read_data(); if (ret >= 0) { ft5x0x_report_value(); } }while (ret > 0); #else ret = ft5x0x_read_data(); if (ret == 0) { ft5x0x_report_value(); } #endif enable_irq(irq_eint7); } static void ft5x0x_report_value(void) { struct ft5x0x_ts_data *data = i2c_get_clientdata(this_client); struct ts_event *event = &data->event; int i; for (i = 0; i < event->touch_point; i++) { //tmp=event->au16_y[i];event->au16_y[i]=event->au16_x[i];event->au16_x[i]=tmp; //printk("p[%d]=[%d,%d]\r\n",i,event->au16_x[i],event->au16_y[i]);//lqm added. if (event->au16_x[i] < TOUCH_X && event->au16_y[i] < TOUCH_Y) // LCD view area {

277 //printk("p[%d]=[%d,%d]\r\n",i,event->au16_x[i],event->au16_y[i]);//lqm added. //#ifdef CFG_ONBOARD_FT5X06 // event->au16_y[i] = TOUCH_Y - event->au16_y[i]; //#endif input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]); input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]); input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1); input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->au8_finger_id[i]); if (event->au8_touch_event[i]== 0 event->au8_touch_event[i] == 2) { input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure); } else { input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0); } } 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 / 13.6-touch_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 uart_test 程 序 : $ cd /usr/local/src/s210x/project/13.6-touch_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth

278 xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 touch_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./touch_test -l/home/app/touch_test 5) 给 touch_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 touch_test 6) 运 行 touch _test 并 点 击 触 摸 屏 可 以 在 minicom 下 看 到 触 摸 点 的 坐 标 信 息 $./touch_test event = X, value = 761 event = Y, value = 234 event = X, value = 761 event = Y, value = 234 event = X, value = 467 event = Y, value = 285 event = X, value = 466 event = Y, value = 285 event = X, value = 466 event = Y, value = 285 event = X, value = 465 event = Y, value = 286 event = X, value = 465 event = Y, value = SD 卡 存 储 实 验 实 验 目 的 掌 握 嵌 入 式 SD 卡 驱 动 程 序 的 编 写, 实 现 了 解 SD 卡 的 工 作 原 理

279 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 SD 卡 的 工 作 原 理 SD 卡 (Secure Digital Memory Card) 是 一 种 为 满 足 安 全 性 容 量 性 能 和 使 用 环 境 等 各 方 面 的 需 求 而 设 计 的 一 种 新 型 存 储 器 件,SD 卡 允 许 在 两 种 模 式 下 工 作 即 SD 模 式 和 SPI 模 式 下 图 是 SD 卡 内 部 结 构 和 引 脚 图 图 SD 卡 内 部 结 构 和 引 脚 其 主 要 引 脚 和 功 能 为 : CLK: 每 个 时 钟 周 期 传 输 一 个 命 令 或 数 据 位 频 率 可 在 0~25MHz 之 间 变 化 SD 卡 的 总 线 管 理 器 可 以 不 受 任 何 限 制 自 由 产 生 0~25MHz 的 频 率 CMD: 命 令 从 该 CMD 线 上 串 行 传 输 一 个 命 令 是 一 次 主 机 到 从 卡 操 作 的 开 始 命 令 可 以 以 单 机 寻 址 ( 寻 址 命 令 ) 或 呼 叫 所 有 卡 ( 广 播 命 令 ) 方 式 发 送 回 复 从 该 CMD 线 上 串 行 传 输 一 个 命 令 是 对 之 前 命 令 的 回 答 回 复 可 以 来 自 单 机 或 所 有 卡 DAT0~3: 数 据 可 以 从 卡 传 向 主 机 或 副 versa, 数 据 通 过 数 据 线 传 输

280 硬 件 原 理 图 如 下 图 所 示 图 SD 卡 接 口 电 路 图 SD 卡 上 所 有 单 元 由 内 部 时 钟 信 号 MMCLK 提 供 接 口 驱 动 单 元 同 步 外 部 时 钟 的 DAT 和 CMD 信 号 到 内 部 所 用 时 钟 SD 卡 中 的 命 令 控 制 与 实 现 1) 程 序 中 调 用 的 sd 卡 命 令 在 程 序 中 的 sd 的 命 令 发 送 响 应 主 要 通 过 函 数 UCS_DRSD_niCommandRespond 来 实 现 其 他 函 数 通 过 调 用 这 个 函 数 完 成 对 sd 卡 的 操 作, 这 里 主 要 有 3 个 函 数 :sd 卡 驱 动 程 序 初 始 化 读 sd 卡 操 作 和 写 sd 卡 操 作 函 数, 下 面 分 别 对 这 些 函 数 具 体 分 析 : 命 令 响 应 函 数 UCS_DRSD_niCommandRespond UCS_DRSD_niCommandRespond(W icmd,uw uiarg,ub *pucrsp) 参 数 分 别 表 示 : icmd 命 令 号 ; uiarg 命 令 参 数 ; pucrsp 命 令 响 应 的 存 储 地 址 本 函 数 分 别 涉 及 到 了 命 令 的 处 理 : CMD9 CMD10: 接 收 sd 卡 的 CSD 和 CID 信 息 ; CMD17 CMD24: 读 写 单 个 block 数 据,CMD18 CMD25: 读 写 多 个 block 数 据 ; CMD58: 读 取 sd 卡 OCR 信 息 sd 卡 驱 动 程 序 初 始 化 UCS_DRSD_giSdIdentify 在 maintask 中 最 开 始 调 用, 进 行 sd 卡 驱 动 的 上 电 初 始 化

281 本 函 数 调 用 上 面 的 函 数 实 现 命 令 的 设 置, 顺 序 进 行 了 如 下 设 置 : CMD1: 设 置 sd 卡 的 工 作 电 压 UCS_DRSD_niCommandRespond(CMD1,UCS_DRSD_OCR_VAL,ucRsp_a); CMD59: 使 能 CRC 校 验 UCS_DRSD_niCommandRespond(CMD59,1,ucRsp_a); CMD9: 读 取 sd 卡 的 CSD 信 息 UCS_DRSD_niCommandRespond(CMD9, 0, ucrsp_a); CMD10: 读 取 sd 卡 的 CID 信 息 UCS_DRSD_niCommandRespond(CMD10, 0, ucrsp_a); CMD16: 设 置 sd 读 写 块 的 大 小, 设 置 值 为 512 个 字 节 UCS_DRSD_niCommandRespond(CMD16,UCS_DRSD_ATASECTORSIZE,ucRsp_a) 读 sd 卡 操 作 函 数 本 函 数 主 要 处 理 了 CMD17 的 读 单 个 block 操 作, 通 过 调 用 DataIn 函 数 来 读 取 512 字 节 的 数 据,DataIn 函 数 的 是 这 样 实 现 的, 接 收 512 个 字 节 的 数 据 和 2 个 字 节 的 16 位 CRC 校 验 码 写 sd 卡 操 作 函 数 本 函 数 主 要 处 理 了 CMD24, 写 单 个 block 操 作, 函 数 调 用 DataOut 函 数, 其 机 制 与 DataIn 相 似 2)sd 卡 的 配 置 信 息 和 相 关 结 构 体 sd 卡 驱 动 程 序 共 定 义 了 4 个 结 构 体 : UCS_DRSD_SDTInfo_st sd 卡 任 务 信 息 ; UCS_DRSD_SD_BASICINFO_st sd 卡 物 理 信 息 ; UCS_DRSD_SD_CID_st sd 卡 CID 信 息 ; UCS_DRSD_SD_CSD_st sd 卡 CSD 信 息 其 中, 物 理 信 息 CID 和 CSD 信 息 是 从 硬 件 上 读 取 回 来 的,CID 和 CSD 直 接 复 制 给 程 序 中 的 结 构 体, 物 理 信 息 basicinfo 需 要 转 换 它 们 是 在 maintask 的 identify 函 数 中 调 用 的,CID 和 CSD 通 过 命 令 CMD9 和 CMD10 获 取 硬 件 信 息 后, 直 接 复 制 物 理 信 息 的 结 构 体 是 将 CSD 信 息 中 LBA( 逻 辑 块 地 址 ) 方 式 转 换 成 CHS( 柱 面 磁 头 扇 区 ) 方 式 后 得 到 的 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 :

282 $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 13 章 /13.7-sd_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 sd_test 程 序 : $ cd /usr/local/src/s210x/project/13.7-sd_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 sd_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./sd_test -l/home/app/sd_test 5) 给 sd_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 sd_test 6) 接 下 来 将 SD 卡 插 到 s210x 实 验 箱 主 板 上 的 SD 卡 插 槽 ( 在 WCDMA 模 块 和 zigbee 模 块 下 面 ) 中, 注 意 minicom 下 的 变 化, 此 时 minicom 下 会 打 印 以 下 信 息, 然 后 按 回 车, 可 看 到 提 示 命 令 提 示 符 #: # [ ] mmc3: new high speed SDHC card at address 1234 [ ] mmcblk2: mmc3:1234 SA04G 3.63 GiB [ ] mmcblk2: p1 7) 在 minicom 下 执 行 mount 命 令 将 SD 卡 挂 到 /mnt 下 : $ mount -t vfat /dev/mmcblk1p1 /mnt/ 8) 运 行 /home/app/ 目 录 下 的 sd_test 应 用 程 序, 在 SD 里 创 建 一 个 文 件, 并 向 这 个 文 件 里 写 入 内 容, 以 回 车 来 结 束 输 入 : $./sd_test

283 Please input the file name you want to create: thefile Please input the content you want to : Welcome to zonesion! The input is: Welcome to zonesion! 9) 查 看 SD 卡 内 文 件 sd_test 是 否 被 创 建, 以 及 文 件 内 容 是 否 写 入 无 误 $ cat /mnt/thefile Welcome to zonesion! 13.8 以 太 网 实 验 实 验 目 的 掌 握 linux 下 以 太 网 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 以 太 网 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 以 太 网 简 介 以 太 网, 指 由 施 乐 公 司 创 建 并 由 施 乐 Intel 和 DEC 公 司 联 合 开 发 的 基 带 局 域 网 规 范 以 太 网 络 使 用 CSMA/CD( 载 波 监 听 多 路 访 问 及 冲 突 检 测 技 术 ) 技 术, 并 以 10 Mbps 的 速 率 运 行 在 多 种 类 型 的 电 缆 上 以 太 网 其 实 是 一 个 IEEE802.3 下 的 协 议 标 准, 各 生 产 厂 商 在 这 个 协 议 标 准 之 下, 生 产 出 同 种 电 气 结 构 数 据 通 信 结 构 的 产 品, 用 这 些 产 品 组 建 起 来 的 网 络 总 称 就 是 以 太 网, 包 括 局 域 网 城 域 网 广 域 网 以 太 网 可 以 采 用 多 种 连 接 介 质, 包 括 同 轴 缆 双 绞 线 和 光 纤 等 其 中 双 绞 线 多 用 于 从 主 机 到 集 线 器 或 交 换 机 的 连 接, 而 光 纤 则 主 要 用 于 交 换 机 间 的 级 联 和 交 换 机 到 路 由 器 间 的 点 到 点 的 链 路 上 同 轴 电 缆 作 为 早 期 的 主 要 连 接 介 质 已 经 逐 渐 趋 于 淘 汰

284 以 太 网 中 节 点 都 可 以 看 到 在 网 络 中 发 送 的 所 有 信 息, 因 此, 我 们 说 以 太 网 是 一 种 广 播 网 络 其 工 作 过 程 如 下 : 当 以 太 网 中 的 一 台 主 机 要 传 输 数 据 时, 它 将 按 如 下 步 骤 进 行 : 1) 监 听 信 道 上 是 否 有 信 号 在 传 输 如 果 有 的 话, 表 明 信 道 处 于 忙 状 态, 就 继 续 监 听, 直 到 信 道 空 闲 为 止 ; 2) 若 没 有 监 听 到 任 何 信 号, 就 传 输 数 据 ; 3) 传 输 的 时 候 继 续 监 听, 如 发 现 冲 突 则 执 行 退 避 算 法, 随 机 等 待 一 段 时 间 后, 重 新 执 行 步 骤 1) ( 当 冲 突 发 生 时, 涉 及 冲 突 的 计 算 机 会 发 送 返 回 到 监 听 信 道 的 状 态 ); 注 意 : 每 台 计 算 机 一 次 只 允 许 发 送 一 个 包, 一 个 拥 塞 序 列, 以 警 告 所 有 的 节 点 4) 若 未 发 现 冲 突 则 发 送 成 功, 所 有 计 算 机 在 试 图 再 一 次 发 送 数 据 之 前, 必 须 在 最 近 一 次 发 送 后 等 待 9.6 微 秒 ( 以 10Mbps 运 行 ) 当 今 居 于 主 导 地 位 的 局 域 网 技 术 以 太 网, 是 建 立 在 CSMA/CD 机 制 上 的 广 播 型 网 络 冲 突 的 产 生 是 限 制 以 太 网 性 能 的 重 要 因 素, 早 期 的 以 太 网 设 备 如 集 线 器 是 物 理 层 设 备, 不 能 隔 绝 冲 突 扩 散, 限 制 了 网 络 性 能 的 提 高 而 交 换 机 ( 网 桥 ) 做 为 一 种 能 隔 绝 冲 突 的 二 层 网 络 设 备, 极 大 的 提 高 了 以 太 网 的 性 能 正 逐 渐 替 代 集 线 器 成 为 主 流 的 以 太 网 设 备 然 而 交 换 机 ( 网 桥 ) 对 网 络 中 的 广 播 数 据 流 量 则 不 做 任 何 限 制, 这 也 影 响 了 网 络 的 性 能 通 过 在 交 换 机 上 划 分 VLAN 和 采 用 三 层 的 网 络 设 备 - 路 由 器 解 决 了 这 一 问 题 以 太 网 做 为 一 种 原 理 简 单, 便 于 实 现 同 时 又 价 格 低 廉 的 局 域 网 技 术 已 经 成 为 业 界 的 主 流 而 更 高 性 能 的 快 速 以 太 网 和 千 兆 以 太 网 的 出 现 更 使 其 成 为 最 有 前 途 的 网 络 技 术 Linux 下 以 以 太 网 的 驱 动 设 计 Linux 网 络 设 备 驱 动 程 序 的 体 系 结 构 从 上 到 下 可 以 划 分 为 4 层, 依 次 为 网 络 协 议 接 口 层 网 络 设 备 接 口 层 提 供 实 际 功 能 的 设 备 驱 动 功 能 层 以 及 网 络 设 备 与 媒 介 层, 这 4 层 的 作 用 如 下 图 所 示 图 Linux 网 络 设 备 驱 动 程 序 的 体 系 结 构 网 络 协 议 接 口 层 向 网 络 层 协 议 提 供 统 一 的 数 据 包 收 发 接 口, 不 论 上 层 协 议 为 ARP 还 是 IP, 都 通

285 过 dev_queue_xmit() 函 数 发 送 数 据, 并 通 过 netif_rx() 函 数 接 收 数 据 这 一 层 的 存 在 使 得 上 层 协 议 独 立 于 具 体 的 设 备 网 络 设 备 接 口 层 向 协 议 接 口 层 提 供 统 一 的 用 于 描 述 具 体 网 络 设 备 属 性 和 操 作 的 结 构 体 net_device, 该 结 构 体 是 设 备 驱 动 功 能 层 中 各 函 数 的 容 器 实 际 上, 网 络 设 备 接 口 层 从 宏 观 上 规 划 了 具 体 操 作 硬 件 的 设 备 驱 动 功 能 层 的 结 构 设 备 驱 动 功 能 层 各 函 数 是 网 络 设 备 接 口 层 net_device 数 据 结 构 的 具 体 成 员, 是 驱 使 网 络 设 备 硬 件 完 成 相 应 动 作 的 程 序, 它 通 过 hard_start_xmit() 函 数 启 动 发 送 操 作, 并 通 过 网 络 设 备 上 的 中 断 触 发 接 收 操 作 网 络 设 备 与 媒 介 层 是 完 成 数 据 包 发 送 和 接 收 的 物 理 实 体, 包 括 网 络 适 配 器 和 具 体 的 传 输 媒 介, 网 络 适 配 器 被 设 备 驱 动 功 能 层 中 的 函 数 物 理 上 驱 动 对 于 Linux 系 统 而 言, 网 络 设 备 和 媒 介 都 可 以 是 虚 拟 的 在 设 计 具 体 的 网 络 设 备 驱 动 程 序 时, 我 们 需 要 完 成 的 主 要 工 作 是 编 写 设 备 驱 动 功 能 层 的 相 关 函 数 以 填 充 net_device 数 据 结 构 的 内 容 并 将 net_device 注 册 入 内 核 在 驱 动 程 序 中 注 册 网 卡 驱 动 为 平 台 驱 动 并 初 始 化 dm9000 static struct platform_driver dm9000_driver = {.driver = {.name = "dm9000",.owner = THIS_MODULE,.pm = &dm9000_drv_pm_ops, },.probe = dm9000_probe,.remove = devexit_p(dm9000_drv_remove), }; static int init dm9000_init(void) { printk(kern_info "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION); return platform_driver_register(&dm9000_driver); }; 我 们 的 网 卡 开 发 重 点 是 填 充 net_device_ops 结 构 体 里 的 函 数 指 针 static const struct net_device_ops dm9000_netdev_ops = {.ndo_open = dm9000_open,.ndo_stop = dm9000_stop,.ndo_start_xmit = dm9000_start_xmit,.ndo_tx_timeout = dm9000_timeout,

286 .ndo_set_multicast_list = dm9000_hash_table,.ndo_do_ioctl = dm9000_ioctl,.ndo_change_mtu = eth_change_mtu,.ndo_validate_addr = eth_validate_addr,.ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER.ndo_poll_controller = dm9000_poll_controller, #endif }; 在 s210x 开 发 平 台 的 初 始 化 函 数 中 注 册 网 卡 为 平 台 设 备 struct platform_device s5p_device_dm9000 = {.name = "dm9000",.id = 1,.num_resources = ARRAY_SIZE(s5p_dm9000_resources),.resource = s5p_dm9000_resources,.dev = {.platform_data = &s5p_dm9000_platdata, } }; static struct platform_device *smdkv210_devices[] initdata = {. #ifdef CONFIG_DM9000 &s5p_device_dm9000, #endif }; 同 时 需 要 对 连 接 以 太 网 的 IO 管 脚 做 相 应 的 配 置 struct platform_device s5p_device_dm9000 = {.name = "dm9000", #ifdef CONFIG_DM9000 static void init smdkv210_dm9000_set(void) { unsigned int tmp; /************song add from utc100******************************/ tmp = raw_readl(s5p_srom_bw); tmp &=~(0xF<<4); tmp = (1<<7) (1<<6) (1<<5) (1<<4); raw_writel(tmp, S5P_SROM_BW); raw_writel((0x0<<28) (0x0<<24) (0x5<<16) (0x0<<12) (0x0<<8) (0x0<<4) (0x0<<0), S5P_SROM_BC3);

287 tmp = raw_readl(s5pv210_mp01con); tmp = (2 << 4); raw_writel(tmp, S5PV210_MP01CON); } #endif 实 验 步 骤 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 连 接 好 网 线, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 3) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 在 minicom 下 输 入 以 下 命 令 配 置 开 发 板 的 ip 地 址 和 子 网 掩 码 # ifconfig eth0 add netmask ) 通 过 输 入 以 下 指 令 查 看 当 前 开 发 板 的 网 络 配 置 # ifconfig eth0 Link encap:ethernet HWaddr 00:09:C0:FF:EC:48 inet addr: Bcast: Mask: inet6 addr: fe80::209:c0ff:feff:ec48/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:267 errors:0 dropped:0 overruns:0 frame:0 TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:22668 (22.1 KiB) TX bytes:468 (468.0 B) Interrupt:42 Base address:0x6300 lo Link encap:local Loopback inet addr: Mask: inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 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:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) 6) 通 过 连 接 主 机 查 看 以 太 网 是 否 畅 通 # ping

288 ping PING ( ): 56 data bytes 64 bytes from : seq=0 ttl=64 time=1.304 ms 64 bytes from : seq=1 ttl=64 time=0.224 ms 64 bytes from : seq=2 ttl=64 time=0.271 ms 64 bytes from : seq=3 ttl=64 time=0.224 ms 64 bytes from : seq=4 ttl=64 time=0.225 ms 可 以 看 到 主 机 能 够 与 开 发 板 能 够 建 立 通 信, 说 明 以 太 网 驱 动 工 作 正 常 13.9 WIFI 实 验 实 验 目 的 掌 握 嵌 入 式 WIFI 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 WIFI 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 WIFI 简 介 Wi-Fi 俗 称 无 线 宽 带, 全 称 Wireless Fidelity b 有 时 也 被 错 误 地 标 为 Wi-Fi, 实 际 上 Wi-Fi 是 无 线 局 域 网 联 盟 (WLANA) 的 一 个 商 标, 该 商 标 仅 保 障 使 用 该 商 标 的 商 品 互 相 之 间 可 以 合 作, 与 标 准 本 身 实 际 上 没 有 关 系 但 是 后 来 人 们 逐 渐 习 惯 用 WIFI 来 称 呼 b 协 议 它 的 最 大 优 点 就 是 传 输 速 度 较 高, 可 以 达 到 11Mbps, 另 外 它 的 有 效 距 离 也 很 长, 同 时 也 与 已 有 的 各 种 DSSS 设 备 兼 容 笔 记 本 电 脑 技 术 迅 驰 技 术 就 是 基 于 该 标 准 的 IEEE([ 美 国 ] 电 子 和 电 气 工 程 师 协 会 )802.11b 无 线 网 络 规 范 是 IEEE 网 络 规 范 的 变 种, 最 高 带 宽 为 11 Mbps, 在 信 号 较 弱 或 有 干 扰 的 情 况 下, 带 宽 可 调 整 为 5.5Mbps 2Mbps 和 1Mbps, 带 宽 的 自 动 调 整, 有 效 地 保 障 了 网 络 的 稳 定 性 和 可 靠 性 其 主 要 特 性 为 : 速 度 快, 可 靠 性 高, 在 开 放 性 区 域, 通 讯 距 离 可 达 305 米, 在 封 闭 性 区 域, 通 讯 距 离 为 76 米 到 122 米, 方 便 与 现 有 的 有 线

289 以 太 网 络 整 合, 组 网 的 成 本 更 低 Wi-Fi (Wireless Fidelity), 无 线 保 真 技 术 与 蓝 牙 技 术 一 样, 同 属 于 在 办 公 室 和 家 庭 中 使 用 的 短 距 离 无 线 技 术 该 技 术 使 用 的 是 2.4GHz 附 近 的 频 段, 该 频 段 目 前 尚 属 没 用 许 可 的 无 线 频 段 其 目 前 可 使 用 的 标 准 有 两 个, 分 别 是 IEEE802.11a 和 IEEE802.11b 该 技 术 由 于 有 着 自 身 的 优 点, 因 此 受 到 厂 商 的 青 睐 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 / 13.9-wifi_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 将 路 径 切 换 到 /usr/local/src/s210x/project /13.9-wifi_test 下, 执 行 以 下 命 令 编 译 应 用 程 序 : $ cd /usr/local/src/s210x/project/13.9-wifi_test $ tar xvf rtl8192_8188cu_linux_v tar.bz2 $ cd rtl8192_8188cu_linux_v / 4) 修 改 Makefile 文 件 : 修 改 Makefile 中 267 行 Linux 内 核 源 码 路 径 为 : ifeq ($(CONFIG_PLATFORM_ARM_S5PV210), y) EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN ARCH := arm CROSS_COMPILE := arm-none-linux-gnueabi- KVER := KSRC?=/usr/local/src/s210x/x210_android-2.3/kernel endif 5) 编 译 wifi 库 文 件 : $ make 在 该 目 录 下 将 生 成 wifi 驱 动 模 块 8192cu.ko 6) 拷 贝 生 成 的 8192cu.ko 到 /opt/tftp/ 目 录 下 : $ cp 8192cu.ko /opt/tftp/ 7) 解 压 工 具 包 并 进 入 工 具 包 目 录 : $ cd /usr/local/src/s210x/project/13.9-wifi_test $ tar xvf wireless_tools_29.tgz

290 $ cd wireless_tools_29/ 8) 编 译 程 序, 并 拷 贝 所 生 成 的 iwconfig 和 libiw.so.29 文 件 到 /opt/tftp 工 作 目 录 : $ make $ cp iwconfig /opt/tftp $ cp libiw.so.29 /opt/tftp 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 接 好 WIFI 模 块, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 wifi_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./iwconfig -l/home/app/iwconfig # tftp -g r./libiw.so.29 -l/lib/libiw.so.29 # tftp -g r./8192cu.ko -l/lib/modules/ /8192cu.ko 5) 加 载 wifi 模 块 : # insmod 8192cu 6) 通 过 iwconfig 命 令 查 看 设 备 : # cd /home/app/ # chmod 777 iwconfig #./iwconfig lo no wireless extensions. eth0 no wireless extensions. usb0 no wireless extensions. wlan0 unassociated Nickname:"<WIFI@REALTEK>" Mode:Auto Frequency=2.412 GHz Access Point: Not-Associated Sensitivity:0/0 Retry:off RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=0/100 Signal level=0 dbm Noise level=0 dbm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:0 Missed beacon:

291 可 以 看 到 wlan0 无 线 设 备 7) 输 入 命 令 打 开 无 线 网 卡 设 备, 并 设 置 IP: # ifconfig wlan0 up # 打 开 wifi [ ] +871x_drv - drv_open, bup=0 [ ] ===> FirmwareDownload91C() fw:rtl819xfwimagearray_umc_b [ ] fw_ver=v75, fw_subver=0, sig=0x88c0 [ ] fw download ok! [ ] HalDetectPwrDownMode(): PDN=0 [ ] HalDetectSelectiveSuspendMode(): SS Enable [ ] Set RF Chip ID to RF_6052 and RF type to 1T1R. [ ] GPIO_IN=0f [ ] erfpowerstatetoset=0 [ ] IQK:Start!!! [ ] Path A IQK Success!! [ ] Path A IQK Success!! [ ] IQK: final_candidate is 0 [ ] IQK: RegE94=102 RegE9C=e RegEA4=fb RegEAC=4 RegEB4=0 RegEBC=0 RegEC4=0 R egecc=0 [ ] Path A IQ Calibration Success! [ ] pdmpriv->txpowertrackcontrol = 1 [ ] MAC Address from REG_MACID = a-cc-28-ba [ ] MAC Address = a-cc-28-ba [ ] -871x_drv - drv_open, bup=1 [ ] ADDRCONF(NETDEV_UP): wlan0: link is not ready # ifconfig wlan # 设 置 ip 地 址 8) 输 入 命 令 连 接 无 线 路 由 网 络 : # iwconfig wlan0 essid zonesion 注 意 : zonesion 是 无 线 网 络 的 名 称, 请 查 看 自 己 的 无 线 网 络, 这 里 的 无 线 路 由 没 有 设 置 密 码 这 样 网 络 就 配 置 好 了, 我 们 可 以 输 入 命 令 查 看 : # /home/app/iwconfig lo no wireless extensions. eth0 no wireless extensions. usb0 no wireless extensions. wlan0 IEEE bgn ESSID:"zonesion" Nickname:"<WIFI@REALTEK>" Mode:Managed Frequency:2.432 GHz Access Point: 00:07:26:7E:4D:A5 Bit Rate:150 Mb/s Sensitivity:0/0 Retry:off RTS thr:off Fragment thr:off Encryption key:off

292 Power Management:off Link Quality=69/100 Signal level=-60 dbm Noise level=0 dbm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:0 Missed beacon:0 Bit Rate:1 Mb/s RTS thr:off Fragment thr:off Encryption key:off Link Quality=10/100 Signal level:0 dbm Noise level:-115 dbm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retrie s:0 Invalid misc:0 Missed beacon:0 9) 我 们 可 以 ping 一 下 局 域 网 内 的 其 他 IP: # ping PING ( ): 56 data bytes 64 bytes from : seq=0 ttl=64 time=1.837 ms 64 bytes from : seq=1 ttl=64 time=0.696 ms 64 bytes from : seq=2 ttl=64 time=0.644 ms 64 bytes from : seq=3 ttl=64 time=0.692 ms 64 bytes from : seq=4 ttl=64 time=0.713 ms 64 bytes from : seq=5 ttl=64 time=0.634 ms ping statistics packets transmitted, 6 packets received, 0% packet loss round-trip min/avg/max = 0.634/0.869/1.837 ms 从 上 我 们 看 到 无 线 网 络 模 块 已 经 驱 动 好 了, 基 于 此, 我 们 可 以 开 发 相 关 的 网 络 上 层 应 用 了 蓝 牙 实 验 实 验 目 的 掌 握 嵌 入 式 蓝 牙 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 蓝 牙 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统

293 实 验 原 理 蓝 牙 通 信 原 理 蓝 牙 的 无 线 通 信 技 术 采 用 每 秒 1600 次 的 快 跳 频 和 短 分 组 技 术, 减 少 干 扰 和 信 号 衰 落, 保 证 传 输 的 可 靠 性 ; 以 时 分 方 式 进 行 全 双 工 通 信, 传 输 速 率 设 计 为 1MHz; 采 用 前 向 纠 错 (FEC) 编 码 技 术, 减 少 远 距 离 传 输 时 的 随 机 噪 声 影 响 ; 其 工 作 频 段 为 非 授 权 的 工 业 医 学 科 学 频 段 (2.4GHz 的 ISM 频 段 ), 保 证 能 在 全 球 范 围 内 使 用 这 种 无 线 通 用 接 口 和 通 信 技 术 ; 话 音 采 用 抗 衰 落 能 力 很 强 的 连 续 可 变 斜 率 调 制 (CVSD) 编 码 方 式 以 提 高 话 音 质 量 ; 采 用 频 率 调 制 方 式, 降 低 设 备 的 复 杂 性 下 图 显 示 了 数 据 经 过 无 线 传 输 时, 所 有 协 议 之 间 的 相 互 关 系, 但 在 某 些 应 用 中 这 种 关 系 是 有 变 化 的 图 蓝 牙 协 议 栈 完 整 的 协 议 栈 包 括 蓝 牙 专 用 协 议 ( 如 连 接 管 理 LMP 和 逻 辑 链 路 控 制 应 用 协 议 L2CAP) 和 非 专 用 协 议 ( 如 对 象 交 换 协 议 OBEX 和 用 户 数 据 报 协 议 UDP) 设 计 协 议 和 协 议 栈 的 主 要 原 则 是 尽 可 能 利 用 现 有 的 各 种 高 层 协 议, 保 证 现 有 协 议 与 蓝 牙 技 术 的 融 合 以 及 各 种 应 用 之 间 的 互 通 性, 充 分 利 用 兼 容 蓝 牙 技 术 规 范 的 软 硬 件 系 统 蓝 牙 技 术 规 范 的 的 开 放 性 保 证 了 设 备 制 造 商 可 自 由 地 选 用 其 专 利 协 议 或 常 用 的 公 共 协 议, 在 蓝 牙 技 术 规 范 基 础 上 开 发 新 的 应 用 蓝 牙 BlueZ 协 议 栈 : BlueZ 是 官 方 Linux Bluetooth 栈, 由 主 机 控 制 接 口 (Host Control Interface,HCI) 层 Bluetooth 协 议 核 心 逻 辑 链 路 控 制 和 适 配 协 议 (Logical Link Control and Adaptation Protocol,L2CAP) SCO 音 频 层 其 他 Bluetooth 服 务 用 户 空 间 后 台 进 程 以 及 配 置 工 具 组 成

294 Bluetooth 规 范 支 持 针 对 Bluetooth HCI 数 据 分 组 的 UART( 通 用 异 步 接 收 器 / 传 送 器 ) 和 USB 传 输 机 制 BlueZ 栈 对 这 两 个 传 输 机 制 (drivers/bluetooth/) 都 支 持 BlueZ BNEP(Bluetooth 网 络 封 装 协 议 ) 实 现 了 Bluetooth 上 的 以 太 网 仿 真, 这 使 TCP/IP 可 以 直 接 运 行 于 Bluetooth 之 上 BNEP 模 块 (net/bluetooth/bnep/) 和 用 户 模 式 pand 后 台 进 程 实 现 了 Bluetooth 个 人 区 域 网 (PAN) BNEP 使 用 register_netdev 将 自 己 作 为 以 太 网 设 备 注 册 到 Linux 网 络 层, 并 使 用 上 面 为 WLAN 驱 动 程 序 描 述 的 netif_rx 来 填 充 sk_buffs 并 将 其 发 送 到 协 议 栈 BlueZ RFCOMM(net/bluetooth/rfcomm/) 提 供 Bluetooth 上 的 串 行 仿 真, 这 使 得 串 行 端 口 应 用 程 序 ( 如 minicom) 和 协 议 ( 如 点 对 点 协 议 (PPP)) 不 加 更 改 地 在 Bluetooth 上 运 行 RFCOMM 模 块 和 用 户 模 式 dund 后 台 进 程 实 现 了 Bluetooth 拨 号 网 络 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 :05- 实 验 例 程 / 第 13 章 / blue_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 2) 进 入 到 蓝 牙 实 验 目 录, 并 解 压 蓝 牙 工 具 包 及 库 : $ cd /usr/local/src/s210x/project/13.10-bluetooth_test $ tar zxvf bluez-libs-2.25.tar.gz $ tar zxvf bluez-utils-2.25.tar.gz 3) 交 叉 编 译 蓝 牙 Bluez 库 文 件 和 工 具 集 ; $ cd bluez-libs-2.25/ $./configure --host=arm-linux --target=arm-linux --prefix=/usr/local/src/s210x/project/13.10-bluetooth_test/libs CC=arm-none-linux-gnueabi-gcc CPP=arm-none-linux-gnueabi-cpp AR=arm-none-linux-gnueabi-ar STRIP=arm-none-linux-gnueabi-strip RANLIB=arm-none-linux-gnueabi-ranlib LD=arm-none-linux-gnueabi-ld $ make $ make install $ cd../bluez-utils-2.25/ $./configure --host=arm-linux --target=arm-linux --prefix=/usr/local/src/s210x/project/13.10-bluetooth_test/utils CC=arm-none-linux-gnueabi-gcc CPP=arm-none-linux-gnueabi-cpp AR=arm-none-linux-gnueabi-ar STRIP=arm-none-linux-gnueabi-strip RANLIB=arm-none-linux-gnueabi-ranlib LD=arm-none-linux-gnueabi-ld

295 --includedir=/usr/local/src/s210x/project/13.10-bluetooth_test/libs/include --libdir=/usr/local/src/s210x/project/13.10-bluetooth_test/libs/lib --with-bluez=/usr/local/src/s210x/project/13.10-bluetooth_test/libs --disable-test --disable-cups --disable-pcmia $ make $ make install 4) 将 编 译 完 成 的 文 件 拷 贝 到 nfs 文 件 夹 : $ cd /usr/local/src/s210x/project/13.10-bluetooth_test $ cp -av utils /opt/nfs $ cp -av libs /opt/nfs 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 接 好 蓝 牙 模 块, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 blue_test 程 序 下 载 到 s210x 实 验 平 台 $ mount -t nfs :/opt/nfs /tmp -o intr,nolock,rsize=1024,wsize=1024 $ cp -a /tmp/libs/lib/* /usr/lib/ $ cp -a /tmp/utils/* / 5) 在 minicom 终 端 输 入 命 令 加 载 蓝 牙 设 备 : $ hciconfig hci0 up $ hcid -f /etc/bluetooth/hcid.conf $ hciconfig -a hci0: Type: USB BD Address: 00:1B:10:00:2A:EC ACL MTU: 1017:8 SCO MTU: 64:0 UP RUNNING PSCAN ISCAN RX bytes:396 acl:0 sco:0 events:19 errors:0 TX bytes:327 acl:0 sco:0 commands:19 errors:0 Features: 0xff 0xff 0x8d 0xfe 0x9b 0xf9 0x00 0x80 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH HOLD SNIFF PARK Link mode: SLAVE ACCEPT Name: 'BlueZ (0)'

296 Class: 0x3e0100 Service Classes: Networking, Rendering, Capturing Device Class: Computer, Uncategorized HCI Ver: 2.0 (0x3) HCI Rev: 0x3000 LMP Ver: 2.0 (0x3) LMP Subver: 0x420b Manufacturer: Broadcom Corporation (15) 可 以 看 到 目 标 板 上 蓝 牙 的 信 息, 名 称 为 BlueZ (0), 地 址 为 :00:1B:10:00:2A:EC 6) 搜 索 周 边 的 蓝 牙 设 备 : ~ $ hcitool scan Scanning... 20:13:02:19:01:26 HC-05 20:13:02:19:00:61 HC-05 20:13:02:19:01:13 HC-05 20:13:02:19:00:79 H-C 前 面 一 串 16 进 制 数 字 为 该 蓝 牙 手 机 设 备 的 唯 一 标 识 7) 查 看 设 备 所 提 供 的 服 务 ( 如 果 设 备 没 有 开 通 服 务, 则 无 法 打 印 出 信 息 ) ~ $ sdptool browse Inquiring... Browsing 20:13:02:19:00:79... Browsing 20:13:02:19:01:13... Browsing 20:13:02:19:01:26... Browsing 20:13:02:19:00: 摄 像 头 驱 动 实 验 实 验 目 的 掌 握 嵌 入 式 USB 摄 像 头 驱 动 应 用 程 序 的 编 写 : 了 解 linux 环 境 下 USB 摄 像 头 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统

297 实 验 原 理 CMOS 摄 像 头 简 介 CMOS 摄 像 头 是 一 种 镜 头 的 名 称, 是 数 码 设 备 用 来 感 光 成 像 的 部 件 CMOS 被 看 作 未 来 的 成 像 器 件 因 为 CMOS 摄 像 头 构 件 相 对 简 单, 与 现 有 的 大 规 模 集 成 电 路 生 产 工 艺 相 同, 从 而 生 产 成 本 可 以 降 低 从 原 理 上,CMOS 的 信 号 是 以 点 为 单 位 的 电 荷 信 号, 速 度 很 快, 也 很 省 电 CMOS 摄 像 头 利 用 矽 感 光 二 极 体 (photodiode) 进 行 光 与 电 的 转 换 这 种 转 换 的 原 理 与 各 位 手 上 具 备 太 阳 电 能 电 子 计 算 机 的 太 阳 能 电 池 效 应 相 近, 光 线 越 强 电 力 越 强 ; 反 之, 光 线 越 弱 电 力 也 越 弱 的 道 理, 将 光 影 像 转 换 为 电 子 数 字 信 号 CMOS 应 用 半 导 体 工 业 常 用 的 MOS 制 程, 可 以 一 次 整 合 全 部 周 边 设 施 于 单 晶 片 中, 节 省 加 工 晶 片 所 需 负 担 的 成 本 和 效 率 的 损 失 CMOS 的 影 像 电 荷 驱 动 方 式 为 主 动 式, 感 光 二 极 体 所 产 生 的 电 荷 会 直 接 由 旁 边 的 电 晶 体 做 放 大 输 出 CMOS 具 有 低 成 本 低 耗 电 以 及 高 整 合 度 的 特 性 CMOS 系 列 开 始 朝 向 大 尺 寸 面 积 与 高 速 影 像 处 理 晶 片 统 合, 藉 由 后 续 的 影 像 处 理 修 正 噪 点 以 及 画 质 表 现, 特 别 是 Canon 系 列 的 EOSD30 EOS300D 的 成 功, 足 见 高 速 影 像 处 理 晶 片 已 经 可 以 胜 任 高 像 素 CMOS 所 产 生 的 影 像 处 理 时 间 与 能 力 的 缩 短 CMOS 未 来 跨 足 高 阶 的 影 像 市 场 产 品, 前 景 可 期 目 前, 市 场 销 售 的 数 码 摄 像 头 中 以 CMOS 感 光 器 件 的 为 主 在 采 用 CMOS 为 感 光 元 器 件 的 产 品 中, 通 过 采 用 影 像 光 源 自 动 增 益 补 强 技 术, 自 动 亮 度 白 平 衡 控 制 技 术, 色 饱 和 度 对 比 度 边 缘 增 强 以 及 伽 马 矫 正 等 先 进 的 影 像 控 制 技 术 摄 像 头 驱 动 在 Linux 下 编 写 摄 像 头 驱 动 主 要 是 编 写 ISI(ImageSensorInterface) 驱 动 ISI 驱 动 的 主 要 流 程 如 下 在 Linux 内 核 中 配 置 DeviceDrivers/Multimediasupport/Videocaptureadapters/CAM8000-Dcamera Module 图 配 置 CAM8000-D 驱 动 使 用 I2C 总 线 挂 载 摄 像 头 驱 动 staticconststructi2c_device_idcam8000_id[]={ {CAM8000_DRIVER_NAME,0}, {}, };

298 MODULE_DEVICE_TABLE(i2c,cam8000_id); staticstructv4l2_i2c_driver_datav4l2_i2c_data={.name=cam8000_driver_name,.probe=cam8000_probe,.remove= devexit_p(cam8000_remove),.id_table=cam8000_id, }; 在 板 级 文 件 中 加 载 CAM8000 #ifdefconfig_video_cam8000 staticintcam8000_power_en(intonoff) { interr; err=gpio_request(s5pv210_gpj4(3),"gpj4"); //err=gpio_request(s5pv210_gph1(3),"gph1"); if(err) printk(kern_err"####failedtopower(gpj4)formipicam\n"); err=gpio_request(s5pv210_gpe1(4),"gpe1"); if(err) printk(kern_err"####failedtoreset(gpe1)formipicam\n"); s3c_gpio_setpull(s5pv210_gpj4(3),s3c_gpio_pull_none); //s3c_gpio_setpull(s5pv210_gph1(3),s3c_gpio_pull_none); s3c_gpio_setpull(s5pv210_gpe1(4),s3c_gpio_pull_none); if(onoff){ gpio_direction_output(s5pv210_gpj4(3),0); //gpio_direction_output(s5pv210_gph1(3),0); gpio_direction_output(s5pv210_gpe1(4),0); mdelay(5); gpio_set_value(s5pv210_gpe1(4),1); }else{ gpio_direction_output(s5pv210_gpe1(4),0); mdelay(5); gpio_direction_output(s5pv210_gpj4(3),1); //gpio_direction_output(s5pv210_gph1(3),1); } gpio_free(s5pv210_gpj4(3)); //gpio_free(s5pv210_gph1(3)); gpio_free(s5pv210_gpe1(4)); return0;

299 } #endif #ifdefcam8000_enabled staticstructcam8000_platform_datacam8000_plat={.default_width=800,.default_height=480,.pixelformat=v4l2_pix_fmt_uyvy,.freq= *16,.is_mipi=0, }; staticstructi2c_board_infocam8000_i2c_info={ I2C_BOARD_INFO("CAM8000",(0x60>>1)),.platform_data=&cam8000_plat, }; staticstructs3c_platform_cameracam8000={.id =CAMERA_PAR_A,.type =CAM_TYPE_ITU,.fmt =ITU_601_YCBCR422_8BIT,.order422 =CAM_ORDER422_8BIT_CBYCRY,.i2c_busnum =1,.info =&cam8000_i2c_info,.pixelformat =V4L2_PIX_FMT_UYVY,.srclk_name ="mout_mpll", /*.srclk_name ="xusbxti",*/.clk_name ="sclk_cam0",.clk_rate = *16,.line_length =1920,.width =800,.height =480,.window ={.left =0,.top =0,.width =800,.height =480, }, /*Polarity*/.inv_pclk =0,.inv_vsync =1,

300 .inv_href =0,.inv_hsync =0,.initialized =0,.cam_power =cam8000_power_en, }; #endif staticstructs3c_platform_fimcfimc_plat={.srclk_name ="mout_mpll",.clk_name ="fimc",.clk_rate = , #ifdefined(s5k4ea_enabled) defined(s5k6aa_enabled).default_cam =CAMERA_CSI_C, #else #ifdefwriteback_enabled.default_cam =CAMERA_WB, #elifcam_8000_ch_a.default_cam =CAMERA_PAR_A, #else.default_cam =CAMERA_PAR_B, #endif #endif.camera ={ #ifdefs5k3ba_enabled &s5k3ba, #endif #ifdefs5k4ba_enabled &s5k4ba, #endif #ifdefs5k4ea_enabled &s5k4ea, #endif #ifdefs5k6aa_enabled &s5k6aa, #endif #ifdefcam8000_enabled &cam8000, #endif #ifdefwriteback_enabled

301 &writeback, #endif }, }; #endif.hw_ver =0x43, 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 /13.11-camera_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 luvc_test 程 序 : $ cd /usr/local/src/s210x/project/13.11-luvc_test $ make $ cp -a luvc_test /opt/tftp $ make clean 可 执 行 文 件 会 被 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 将 模 拟 摄 像 头 接 入 到 Video 接 口 的 左 边 第 一 个 接 线 柱 上, 同 时 给 摄 像 头 接 上 自 带 的 电 源 适 配 器 ( 如 果 使 用 的 是 数 字 摄 像 头 则 直 接 将 摄 像 头 插 入 到 Camera 接 口 ) 3) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 启 动 uboot 后, 快 速 按 任 意 键 进 入 uboot 命 令 行 界 面, 输 入 以 下 命 令 修 改 uboot 参 数 : x210 # setenv bootargs=console=ttysac0, lcd=7inch root=/dev/mmcblk0p2 rootfstype=ext4 init=/linuxrc lcd=8inch # 如 果 用 的 是 8 寸 屏 模 拟 摄 像 头 x210 # setenv bootargs=console=ttysac0, lcd=7inch root=/dev/mmcblk0p2 rootfstype=ext

302 init=/linuxrc lcd=8inch camera=ov2655 x210 # saveenv # 如 果 用 的 是 8 寸 屏 数 字 摄 像 头 4) 重 启 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 5) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 luvc_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./luvc_test -l./home/app/luvc_test 6) 给 luvc_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 luvc_test 7) 运 行 应 用 程 序 #./luvc_test open bfamebuffer /dev/fb0 800x480, 32bpp, xoffset=0,yoffset=0 finfo.line_length= 0xc80 The framebuffer device was mapped to memory successfully. Device /dev/video0 opened: s3c-fimc0. [ ] tvp514x 2-005d: tvp514x 2-005d decoder driver registered!! [ ] tvp514x_fmt_cap() bytesperline-1440 width-720 height-576 [ ] tvp514x 2-005d: tvp5146m2 (Version - 0x03) found at 0xba (s3c2410-i2c) video_set_format: width: 640 height: 480 Video format set: width: 720 height: 576 buffer size: buffers allocated. length: offset: 0 Buffer 0 mapped at address 0x length: offset: 4096 Buffer 1 mapped at address 0x4020e000. length: offset: 8192 Buffer 2 mapped at address 0x402a4000. length: offset: Buffer 3 mapped at address 0x4033a000. 可 以 看 到 LCD 屏 幕 上 显 示 摄 像 头 拍 摄 的 画 面 下 图 是 实 验 时 拍 摄 到 的 画 面 :

303 图 摄 像 头 实 验 采 集 照 片 GPS 实 验 实 验 目 的 掌 握 嵌 入 式 GPS 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 GPS 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 全 球 定 位 系 统 GPS(Global Position System), 即 全 球 定 位 系 统, 这 是 一 个 由 覆 盖 全 球 的 24 颗 卫 星 组 成 的 卫

304 星 系 统 这 个 系 统 可 以 保 证 在 任 意 时 刻, 地 球 上 任 意 一 点 都 可 以 同 时 观 测 到 4 颗 卫 星, 以 保 证 卫 星 可 以 采 集 到 该 观 测 点 的 经 纬 度 和 高 度, 以 便 实 现 导 航 定 位 授 时 等 功 能, 其 目 的 是 在 全 球 范 围 内 对 地 面 和 空 中 目 标 进 行 准 确 定 位 和 监 测 随 着 全 球 性 空 间 定 位 信 息 应 用 的 日 益 广 泛,GPS 提 供 的 全 时 域 全 天 候 高 精 度 定 位 服 务 将 给 空 间 技 术 地 球 物 理 大 地 测 绘 遥 感 技 术 交 通 调 度 军 事 作 战 以 及 人 们 的 日 常 生 活 带 来 巨 大 的 变 化 和 深 远 的 影 响 GPS 包 括 三 个 基 本 部 分 : 太 空 部 分, 即 空 中 的 GPS 卫 星 GPS 的 空 间 部 分 是 由 24 颗 工 作 卫 星 组 成, 它 位 于 距 地 表 20200km 的 上 空, 均 匀 分 布 在 6 个 轨 道 面 上 ( 每 个 轨 道 面 4 颗 ), 轨 道 倾 角 为 55 此 外, 还 有 4 颗 有 源 备 份 卫 星 在 轨 运 行 卫 星 的 分 布 使 得 在 全 球 任 何 地 方 任 何 时 间 都 可 观 测 到 4 颗 以 上 的 卫 星, 并 能 保 持 良 好 定 位 解 算 精 度 的 几 何 图 象 这 就 提 供 了 在 时 间 上 连 续 的 全 球 导 航 能 力 GPS 卫 星 产 生 两 组 电 码 : 一 组 称 为 C/A 码 (Coarse/Acquisition Code11023MHz); 一 组 称 为 P 码 (Procise Code 10123MHz), P 码 因 频 率 较 高, 不 易 受 干 扰, 定 位 精 度 高, 因 此 受 美 国 军 方 管 制, 并 设 有 密 码, 一 般 民 间 无 法 解 读, 主 要 为 美 国 军 方 服 务 C/A 码 人 为 采 取 措 施 而 刻 意 降 低 精 度 后, 主 要 开 放 给 民 间 使 用 控 制 部 分, 即 地 面 的 GPS 卫 星 监 控 系 统 地 面 控 制 部 分 由 一 个 主 控 站,5 个 全 球 监 测 站 和 3 个 地 面 控 制 站 组 成 监 测 站 均 配 装 有 精 密 的 铯 钟 和 能 够 连 续 测 量 到 所 有 可 见 卫 星 的 接 受 机 监 测 站 将 取 得 的 卫 星 观 测 数 据, 包 括 电 离 层 和 气 象 数 据, 经 过 初 步 处 理 后, 传 送 到 主 控 站 主 控 站 从 各 监 测 站 收 集 跟 踪 数 据, 计 算 出 卫 星 的 轨 道 和 时 钟 参 数, 然 后 将 结 果 送 到 3 个 地 面 控 制 站 地 面 控 制 站 在 每 颗 卫 星 运 行 至 上 空 时 把 这 些 导 航 数 据 及 主 控 站 指 令 注 入 到 卫 星 这 种 注 入 对 每 颗 GPS 卫 星 每 天 一 次, 并 在 卫 星 离 开 注 入 站 作 用 范 围 之 前 进 行 最 后 的 注 入 如 果 某 地 面 站 发 生 故 障, 那 么 在 卫 星 中 预 存 的 导 航 信 息 还 可 用 一 段 时 间, 但 导 航 精 度 会 逐 渐 降 低 用 户 部 分, 即 GPS 的 移 动 用 户 端 用 户 部 分 即 GPS 信 号 接 收 机 其 主 要 功 能 是 能 够 捕 获 到 按 一 定 卫 星 截 止 角 所 选 择 的 待 测 卫 星, 并 跟 踪 这 些 卫 星 的 运 行 当 接 收 机 捕 获 到 跟 踪 的 卫 星 信 号 后, 即 可 测 量 出 接 收 天 线 至 卫 星 的 伪 距 离 和 距 离 的 变 化 率, 解 调 出 卫 星 轨 道 参 数 等 数 据 根 据 这 些 数 据, 接 收 机 中 的 微 处 理 计 算 机 就 可 按 定 位 解 算 方 法 进 行 定 位 计 算, 计 算 出 用 户 所 在 地 理 位 置 的 经 纬 度 高 度 速 度 时 间 等 信 息 接 收 机 硬 件 和 机 内 软 件 以 及 GPS 数 据 的 后 处 理 软 件 包 构 成 完 整 的 GPS 用 户 设 备 GPS 接 收 机 的 结 构 分 为 天 线 单 元 和 接 收 单 元 两 部 分 接 收 机 一 般 采 用 机 内 和 机 外 两 种 直 流 电 源 设 置 机 内 电 源 的 目 的 在 于 更 换 外 电 源 时 不 中 断 连 续 观 测 在 用 机 外 电 源 时 机 内 电 池 自 动 充 电 关 机 后, 机 内 电 池 为 RAM 存 储 器 供 电, 以 防 止 数 据 丢 失 目 前 各 种 类 型 的 接 受 机 体 积 越 来 越 小, 重 量 越 来 越 轻, 便 于 野 外 观 测 使 用 GPS 工 作 原 理 GPS 的 工 作 概 念 是 基 于 卫 星 的 距 离 修 正 用 户 通 过 测 量 到 太 空 各 可 视 卫 星 的 距 离 来 计 算 他 们 的 当 前 位 置, 卫 星 的 左 右 相 当 于 精 确 的 已 知 参 考 点 每 颗 GPS 卫 星 时 刻 发 布 其 位 置 和 时 间 数 据 信 号,

305 用 户 接 收 机 可 以 测 量 每 颗 卫 星 信 号 到 接 收 机 的 时 间 延 迟, 根 据 信 号 传 输 的 速 度 就 可 以 计 算 出 接 收 机 到 不 同 卫 星 的 距 离 同 时 收 集 到 至 少 四 颗 卫 星 的 数 据 时 就 可 以 解 算 出 三 维 坐 标 速 度 和 时 间 GPS 接 收 机 对 收 到 的 卫 星 信 号, 进 行 解 码 或 采 用 其 它 技 术, 将 调 制 在 载 波 上 的 信 息 去 掉 后, 就 可 以 恢 复 原 来 的 信 号 按 定 位 方 式,GPS 定 位 分 为 单 点 定 位 和 相 对 定 位 ( 差 分 定 位 ) 单 点 定 位 就 是 根 据 一 台 接 收 机 的 观 测 数 据 来 确 定 接 收 机 位 置 的 方 式, 它 只 能 采 用 伪 距 观 测 量, 可 用 于 车 船 等 的 概 略 导 航 定 位 相 对 定 位 ( 差 分 定 位 ) 是 根 据 两 台 以 上 接 收 机 的 观 测 数 据 来 确 定 观 测 点 之 间 的 相 对 位 置 的 方 法, 它 既 可 采 用 伪 距 观 测 量 也 可 采 用 相 位 观 测 量, 大 地 测 量 或 工 程 测 量 均 应 采 用 相 位 观 测 值 进 行 相 对 定 位 在 GPS 观 测 量 中 包 含 了 卫 星 和 接 收 机 的 钟 差 大 气 传 播 延 迟 多 路 径 效 应 等 误 差, 在 定 位 计 算 时 还 要 受 到 卫 星 广 播 星 历 误 差 的 影 响, 因 此 是 伪 距 测 量 而 相 对 定 位 时 大 部 分 公 共 误 差 被 抵 消 或 削 弱, 因 此 定 位 精 度 将 大 大 提 高, 双 频 接 收 机 可 以 根 据 两 个 频 率 的 观 测 量 抵 消 大 气 中 电 离 层 误 差 的 主 要 部 分, 在 精 度 要 求 高, 接 收 机 间 距 离 较 远 时 ( 大 气 有 明 显 差 别 ), 应 选 用 双 频 接 收 机 在 定 位 观 测 时, 若 接 收 机 相 对 于 地 球 表 面 运 动, 则 称 为 动 态 定 位, 如 用 于 车 船 等 概 略 导 航 定 位 的 精 度 为 米 的 伪 距 单 点 定 位, 或 用 于 城 市 车 辆 导 航 定 位 的 米 级 精 度 的 伪 距 差 分 定 位, 或 用 于 测 量 放 样 等 的 厘 米 级 的 相 位 差 分 定 位 (RTK), 实 时 差 分 定 位 需 要 数 据 链 将 两 个 或 多 个 站 的 观 测 数 据 实 时 传 输 到 一 起 计 算 在 定 位 观 测 时, 若 接 收 机 相 对 于 地 球 表 面 静 止, 则 称 为 静 态 定 位, 在 进 行 控 制 网 观 测 时, 一 般 均 采 用 这 种 方 式 由 几 台 接 收 机 同 时 观 测, 它 能 最 大 限 度 地 发 挥 GPS 的 定 位 精 度, 专 用 于 这 种 目 的 的 接 收 机 被 称 为 大 地 型 接 收 机, 是 接 收 机 中 性 能 最 好 的 一 类 目 前,GPS 已 经 能 够 达 到 地 壳 形 变 观 测 的 精 度 要 求 GPS 模 块 输 出 信 号 分 析 本 实 验 平 台 采 用 了 Samsung 公 司 的 GPS 接 收 模 块 MEB1280,MEB128 的 输 出 信 号 是 根 据 NMEA (National Marine Electronics Association)0183 格 式 标 准 输 出 的 输 出 信 息 主 要 包 括 位 置 测 定 系 统 定 位 资 料 GPGGA, 偏 差 信 息 和 卫 星 状 态 GPGSA, 导 航 系 统 卫 星 相 关 资 料 GPGSV, 最 起 码 的 GNSS 信 息 GPRMC 共 4 个 部 分 下 面 将 主 要 以 GPRMC(Reco-mmended Minimum Specific GNSS Data) 最 起 码 的 GNSS( 全 球 卫 星 导 航 系 统 ) 信 息 为 例 对 信 息 进 行 分 析 GPGGA 位 置 测 定 系 统 定 位 资 料 定 位 后 的 卫 星 定 位 信 息 (Global Positioning System Fix Data) 卫 星 时 间 位 置 和 相 关 信 息 信 息 示 例 : $GPGGA, , ,N, ,E,1,08,00.9, ,M,-2.1,M,,*7B 表 GPGGA 信 息 说 明 名 称 数 值 单 位 说 明 信 息 代 码 $GPGGA GGA 信 息 标 准 码 格 林 威 治 时 间 时 时 分 分 秒 秒. 秒 秒 秒 纬 度 度 度 分 分. 秒 秒 秒 秒 南 / 北 极 N N: 北 极 S: 南 极 经 度 度 度 度 分 分. 秒 秒 秒 秒

306 等 ) 东 / 西 经 E E: 东 半 球 W 西 半 球 定 位 代 码 1 1 表 示 定 位 代 码 是 有 效 的 使 用 中 的 卫 星 数 08 水 平 稀 释 精 度 米 海 拔 高 度 米 单 位 M 米 偏 差 修 正 使 用 区 间 -2.1 米 单 位 M 米 校 验 码 *7B GSA 方 向 及 速 度 (Course Over Ground and Ground Speed) 信 息 示 例 : $GPGSA,A,3,06,16,14,22,25,01,30,20,,,,,01.6,00.9,01.3*0D 表 GPGSA 信 息 说 明 Android & linux 系 统 与 应 用 开 发 名 称 数 值 单 位 说 明 信 息 代 码 $GPGSA GSA 信 息 标 准 码 自 动 / 手 动 选 择 2 维 /3 维 形 式 A MM = 手 动 选 择 A = 自 動 控 制 可 用 的 模 式 3 2 = 2 维 模 式 3 = 3 维 模 式 接 收 到 信 号 的 卫 星 编 号 06,16,14,22,25,01,30,20 收 到 信 号 的 卫 星 的 编 号 位 置 精 度 稀 释 01.6 水 平 精 度 稀 释 00.9 垂 直 精 度 稀 释 01.3 校 验 码 *0D GSV 导 航 系 统 卫 星 相 关 资 料 GNSS 天 空 范 围 内 的 卫 星 (GNSS Satellites in View) 即 可 见 卫 星 数 伪 码 乱 码 数 值 卫 星 仰 角 信 息 示 例 : $GPGSV,2,1,08,06,26,075,44,16,50,227,47,14,57,097,44,22,17,169,41*70 $GPGSV,2,2,08,25,49,352,45,01,64,006,45,30,13,039,39,20,15,312,34*7A 表 GPGSV 信 息 说 明 名 称 数 值 单 位 说 明 信 息 代 码 $GPGSV GSV 信 息 标 准 码 GPGSV 信 息 被 分 割 的 数 目 2 信 息 被 分 割 成 2 部 分 信 息 被 分 割 后 的 序 号 1 接 收 到 的 卫 星 数 目 08 卫 星 的 编 号 卫 星 编 号 分 别 是 , 下 面 的 信 息 也 是 以 列 的 形 式 对 应 卫 星 的 仰 角 度 正 上 方 90 度, 范 围 0~90 度 卫 星 的 方 位 角 度 正 北 方 是 0 度, 范 围 0~360 度 信 号 强 度 db 范 围 0~99, 如 果 输 出 null 表 示 未 用 校 验 码 *70 RMC 最 起 码 的 GNSS 信 息 (Recommended Minimum Specific GNSS Data) 主 要 是 卫 星 的 时 间 位 置 方 位 速 度 等 信 息 示 例 : $GPRMC, ,A, ,N, ,E,000.0,276.0,150805,002.1,W*7C

307 表 GPRMC 信 息 说 明 名 称 数 值 单 位 说 明 信 息 代 码 $GPRMC RMC 信 息 起 始 码 格 林 威 治 时 间 / 标 准 定 位 时 间 UTC 时 时 分 分 秒. 秒 秒 (Hhmmss.sss) 状 态 A A= 信 息 有 效 ;V= 信 息 无 效 纬 度 度 度 秒 秒. 秒 秒 秒 秒 南 / 北 维 N N= 北 纬 ;S= 南 纬 经 度 度 度 秒 秒. 秒 秒 秒 秒 东 / 西 经 E E= 东 经 ;W= 西 经 对 地 速 度 对 地 方 向 日 期 日 日 月 月 年 年 磁 极 变 量 度 数 检 验 码 W*7C 硬 件 原 理 图 s210x 实 验 平 台 扩 展 了 GPS 接 收 模 块 图 GPS 模 块 电 路 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 / gps_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 gps_test 程 序 : $ cd /usr/local/src/s210x/project/13.12-gps_test $ make

308 $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 gps_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./gps_test -l/home/app/gps_test 5) 给 gps_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 gps_test 6) 运 行 gps_test #./gps_test This is a test about GPS Select what you want to read: 1 : Original GPS data 2 : Is the signal OK 3 : Basic coordinates info 4 : Quit > 比 如 选 择 1 之 后 回 车 会 打 印 以 下 信 息, 显 示 以 前 的 串 口 信 息 : >1 00,V, ,N, ,E,000.0,000.0,280606,,,N*7A $GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02 输 入 2 回 车 将 会 探 测 当 前 GPS 信 号 强 度 : >2 GPS connected Signal OK

309 如 果 显 示 信 号 OK, 则 表 明 当 前 GPS 信 号 良 好, 可 以 正 常 输 出 有 效 定 位 信 息, 输 入 3 回 车 将 会 显 示 当 前 GPS 经 纬 度 信 息 : >3 1 time: 08h 51m s 2 status: Yes 3 North Latitude(N): East Longtitude(E): 输 入 4 退 出 程 序 : >4 Quit GPS function. byebye : 如 果 收 到 的 字 符 串 和 输 入 的 字 符 串 一 致 则 表 明 实 验 成 功 GSM 显 示 实 验 实 验 目 的 了 解 嵌 入 式 GSM 驱 动 程 序 的 编 写, 实 现 了 解 linux 环 境 下 GSM 的 工 作 原 理 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 GSM 简 介 GSM 是 由 欧 洲 电 信 标 准 组 织 ETSI 制 订 的 一 个 数 字 移 动 通 信 标 准 GSM 是 全 球 移 动 通 信 系 统 (Global System of Mobile communication) 的 简 称 它 的 空 中 接 口 采 用 时 分 多 址 技 术 自 90 年 代 中 期 投 入 商 用 以 来, 为 全 球 超 过 100 个 国 家 采 用 GSM 标 准 的 设 备 占 据 当 前 全 球 蜂 窝 移 动 通 信 设 备 市 场 80% 以 上 GSM 属 于 2 代 蜂 窝 移 动 通 信 技 术 2 代 的 说 法 是 相 对 于 应 用 于 80 年 代 的 模 拟 蜂 窝 移 动 通 信 技 术

310 以 及 目 前 正 逐 渐 进 入 商 用 的 宽 带 CDMA 技 术 模 拟 蜂 窝 技 术 被 称 为 一 代 移 动 通 信 技 术, 宽 带 CDMA 技 术 也 即 三 代,3G GSM 是 GlobalSystemofMobilecommunication 全 球 移 动 通 讯 系 统 的 英 文 缩 写, 是 当 前 应 用 最 为 广 泛 的 移 动 电 话 标 准 全 球 超 过 200 个 国 家 和 地 区 超 过 10 亿 人 正 在 使 用 GSM 电 话 所 有 用 户 可 以 在 签 署 了 漫 游 协 定 移 动 电 话 运 营 商 之 间 自 由 漫 游 GSM 较 之 它 以 前 的 标 准 最 大 的 不 同 是 他 的 信 令 和 语 音 信 道 都 是 数 字 式 的, 因 此 GSM 被 看 作 是 第 二 代 (2G) 移 动 电 话 系 统. 这 说 明 数 字 通 讯 从 很 早 就 已 经 构 建 到 系 统 中 GSM 是 一 个 当 前 由 3GPP 开 发 的 开 放 标 准 从 用 户 观 点 出 发,GSM 的 主 要 优 势 在 于 用 户 可 以 从 更 高 的 数 字 语 音 质 量 和 低 费 用 的 [SMS]] 之 间 作 出 选 择 网 络 运 营 商 的 优 势 是 他 们 可 以 不 同 的 客 户 定 制 他 们 的 设 备 配 置, 因 为 GSM 作 为 开 放 标 准 提 供 了 更 容 易 的 互 操 作 性 这 样, 标 准 就 允 许 网 络 运 营 商 提 供 漫 游 服 务, 用 户 就 可 以 在 全 球 使 用 他 们 的 移 动 电 话 了 GSM 作 为 一 个 继 续 开 发 的 标 准, 保 持 向 后 兼 容 原 始 的 GSM 电 话, 例 如 报 文 交 换 能 力 在 Release'97 版 本 的 标 准 才 被 加 入 进 来, 也 就 是 GPRS 高 速 数 据 交 换 也 是 在 Release'99 版 标 准 才 引 入 的, 主 要 是 EDGE 和 UMTS 标 准 尽 管 当 前 GSM 相 当 普 及, 但 是 构 思 移 动 电 话 的 历 史 在 GSM 之 前 很 长 时 间 就 开 始 了 GSM 小 组 创 立 于 1982 年 GSM 的 名 字 也 是 源 于 这 个 小 组 的 名 字, 尽 管 后 来 决 定 使 用 缩 写 代 替 了 它 的 原 有 的 含 义 最 开 始 这 个 小 组 由 CEPT 负 责 管 理 GSM 系 统 的 原 始 技 术 在 1987 年 定 义 1989 年,ETSI 从 CEPT 接 手 1990 年 第 一 个 GSM 规 范 说 明 完 成, 这 个 规 范 的 文 本 长 达 超 过 6000 页 商 业 运 营 开 始 于 1991 年, 地 点 是 芬 兰 的 Radiolinja 1998 年,3G 合 作 项 目 (3GPP) 启 动 最 初, 这 个 项 目 的 目 标 是 制 定 详 细 的 下 一 代 移 动 通 讯 网 (3G) 规 范 然 而,3GPP 也 接 受 了 维 护 和 开 发 GSM 规 范 的 工 作 ETSI 是 3GPP 的 一 个 成 员 目 前 国 内 支 持 国 际 电 联 确 定 的 三 个 无 线 接 口 标 准, 分 别 是 中 国 电 信 的 CDMA2000, 中 国 联 通 的 WCDMA, 中 国 移 动 的 TD-SCDMA GSM 设 备 采 用 的 是 时 分 多 址, 而 CDMA 使 用 的 是 码 分 扩 频 技 术, 先 进 功 率 和 话 音 激 活 至 少 可 提 供 大 于 3 倍 GSM 网 络 容 量, 业 界 将 CDMA 技 术 作 为 3G 的 主 流 技 术 3G 主 要 特 征 是 可 提 供 移 动 宽 带 多 媒 体 业 务 3G 上 网 功 能 点 对 点 协 议 (PPP) 为 在 点 对 点 连 接 上 传 输 多 协 议 数 据 包 提 供 了 一 个 标 准 方 法 PPP 最 初 设 计 是 为 两 个 对 等 节 点 之 间 的 IP 流 量 传 输 提 供 一 种 封 装 协 议 在 TCP-IP 协 议 集 中 它 是 一 种 用 来 同 步 调 制 连 接 的 数 据 链 路 层 协 议 (OSI 模 式 中 的 第 二 层 ), 替 代 了 原 来 非 标 准 的 第 二 层 协 议, 即 SLIP 除 了 IP 以 外 PPP 还 可 以 携 带 其 它 协 议, 包 括 DECnet 和 Novell 的 Internet 网 包 交 换 (IPX) PPP 主 要 由 以 下 几 部 分 组 成 : 封 装 : 一 种 封 装 多 协 议 数 据 报 的 方 法 PPP 封 装 提 供 了 不 同 网 络 层 协 议 同 时 在 同 一 链 路 传 输 的 多 路 复 用 技 术 PPP 封 装 精 心 设 计, 能 保 持 对 大 多 数 常 用 硬 件 的 兼 容 性, 克 服 了 SLIP 不 足 之 处 的 一 种 多 用 途 点 到 点 协 议, 它 提 供 的 WAN 数 据 链 接 封 装 服 务 类 似 于 LAN 所 提 供 的 封 闭 服 务 所 以,

311 PPP 不 仅 仅 提 供 帧 定 界, 而 且 提 供 协 议 标 识 和 位 级 完 整 性 检 查 服 务 链 路 控 制 协 议 : 一 种 扩 展 链 路 控 制 协 议, 用 于 建 立 配 置 测 试 和 管 理 数 据 链 路 连 接 网 络 控 制 协 议 : 协 商 该 链 路 上 所 传 输 的 数 据 包 格 式 与 类 型, 建 立 配 置 不 同 的 网 络 层 协 议 ; 配 置 : 使 用 链 路 控 制 协 议 的 简 单 和 自 制 机 制 该 机 制 也 应 用 于 其 它 控 制 协 议, 例 如 : 网 络 控 制 协 议 (NCP) 为 了 建 立 点 对 点 链 路 通 信,PPP 链 路 的 每 一 端, 必 须 首 先 发 送 LCP 包 以 便 设 定 和 测 试 数 据 链 路 在 链 路 建 立,LCP 所 需 的 可 选 功 能 被 选 定 之 后,PPP 必 须 发 送 NCP 包 以 便 选 择 和 设 定 一 个 或 更 多 的 网 络 层 协 议 一 旦 每 个 被 选 择 的 网 络 层 协 议 都 被 设 定 好 了, 来 自 每 个 网 络 层 协 议 的 数 据 报 就 能 在 链 路 上 发 送 了 链 路 将 保 持 通 信 设 定 不 变, 直 到 有 LCP 和 NCP 数 据 包 关 闭 链 路, 或 者 是 发 生 一 些 外 部 事 件 的 时 候 ( 如, 休 止 状 态 的 定 时 器 期 满 或 者 网 络 管 理 员 干 涉 ) 当 用 户 拨 号 接 入 ISP 时, 路 由 器 的 调 制 解 调 器 对 拨 号 做 出 确 认, 并 建 立 一 条 物 理 连 接 ( 底 层 up) PC 机 向 路 由 器 发 送 一 系 列 的 LCP 分 组 ( 封 装 成 多 个 PPP 帧 ) 这 些 分 组 及 其 响 应 选 择 一 些 PPP 参 数, 和 进 行 网 络 层 配 置 ( 此 前 如 有 PAP 或 CHAP 验 证 先 要 通 过 验 证 ),NCP 给 新 接 入 的 PC 机 分 配 一 个 临 时 的 IP 地 址, 使 PC 机 成 为 因 特 网 上 的 一 个 主 机 通 信 完 毕 时,NCP 释 放 网 络 层 连 接, 收 回 原 来 分 配 出 去 的 IP 地 址 接 着,LCP 释 放 数 据 链 路 层 连 接 最 后 释 放 的 是 物 理 层 的 连 接 PPP 协 议 是 一 种 点 点 串 行 通 信 协 议 PPP 具 有 处 理 错 误 检 测 支 持 多 个 协 议 允 许 在 连 接 时 刻 协 商 IP 地 址 允 许 身 份 认 证 等 功 能, 还 有 其 他 PPP 提 供 了 3 类 功 能 : 成 帧 ; 链 路 控 制 协 议 LCP; 网 络 控 制 协 议 NCP PPP 是 面 向 字 符 类 型 的 协 议 GPRS 模 块 概 述 GPRS(General Packet Radio Service, 通 用 分 组 无 线 业 务 ) 是 在 现 有 GSM 系 统 上 发 展 起 来 的 一 种 新 的 承 载 业 务 基 于 这 种 业 务 的 各 种 应 用 也 蓬 勃 发 展 起 来, 典 型 的 应 用 有 : 工 业 控 制 环 境 保 护 道 路 交 通 上 午 金 融 移 动 办 公 零 售 服 务 公 安 系 统 等 GPRS 允 许 用 户 在 端 到 端 分 组 转 义 模 式 下 发 送 和 接 收 数 据, 而 不 需 要 利 用 电 路 交 换 的 模 式, 比 较 适 合 于 突 发 性 的, 频 繁 的, 数 据 量 小 的 数 据 传 输, 也 适 用 于 偶 尔 数 据 量 大 的 数 据 传 输 目 前,GPRS 模 块 的 提 供 商 有 西 门 子 摩 托 罗 拉 飞 利 浦 大 唐 中 兴 华 为 等 其 中 西 门 子 和 摩 托 罗 拉 公 司 的 GPRS 模 块 产 品 较 为 常 见 本 实 验 使 用 的 GPRS 模 块 是 西 门 子 公 司 生 产 的 MC35i 该 款 GPRS 模 块 具 有 很 高 的 性 能, 可 以 广 泛 应 用 于 以 下 场 合 :POS 终 端 自 动 售 货 机 安 全 系 统 远 程 遥 测 交 通 控 制 导 航 系 统 手 持 设 备 GPRS 调 制 解 调 器 等 模 块 特 性 : 双 频 段 :EGSM900MHz 和 GSM1800MHz; 输 出 功 率 :4 类 EGSM 频 段 :2W,1 类 GSM 频 段 :1W; 使 用 AT 命 令 控 制 ;

312 SIM 应 用 工 具 包 ; 电 源 范 围 :3.3V-4.8V; 节 电 模 式 ; 供 电 消 耗 : - 空 闲 模 式 :25mA - 通 话 模 式 : 平 均 300mA - GPRS 模 式 : 平 均 360mA - 发 送 突 发 : 最 大 2.5A - 掉 电 模 式 :50uA - 睡 眠 模 式 : 最 大 3.5mA 尺 寸 : mm; 重 量 :9g; 工 作 温 度 :-20~55 度 模 块 接 口 : 40-pin ZIF 连 接 器 电 源 供 电 : SIM 卡 3V 供 电 ; RS232 双 向 数 据 总 线 ; 自 适 应 波 特 率 两 路 模 拟 音 频 信 号 接 口 50ohm GSC 连 接 器 ; 要 获 得 更 多 信 息, 请 参 考 该 模 块 的 详 细 资 料 标 准 V.25ter AT 命 令 AT 命 令 符 合 ITU-T( 国 际 电 联 )V.25ter 文 件 标 准 现 简 单 介 绍 几 个 和 收 发 短 消 息 有 关 的 几 个 AT 命 令 表 AT 命 令 AT 命 令 功 能 描 述 AT 与 模 块 连 接 AT+CMGF=? 返 回 当 前 的 工 作 模 式 AT+CMGF=n 设 置 当 前 工 作 模 式,n=0:PDU 模 式,n=1:text 模 式 AT+CMGS 发 送 短 信 息 AT+CMGR=<index> 读 短 信 息, 其 中 index 是 消 息 在 当 前 存 储 区 中 的 序 列 号 AT+CMGL 输 出 短 信 息 列 表 AT+CMGD=<index> 删 除 短 消 息, 删 除 当 前 存 储 区 中 序 列 号 为 index 的 短 消 息

313 设 置 收 到 的 短 消 息 报 告 模 式,mode=0: 缓 冲 短 消 息 结 果 码 ; AT+CNMI=<mode> mode=1: 在 数 据 通 信 状 态 下, 阻 止 结 果 码 发 送 到 TE(); Mode=2: 无 论 何 种 状 态 下, 都 向 TE 发 送 结 果 码 电 路 连 接 图 本 实 验 中 总 体 电 路 连 接 图 如 下 : 图 电 路 连 接 图 S5PV210 处 理 器 通 过 UART0 接 收 PC 机 在 输 入 超 级 终 端 输 入 的 控 制 信 息 或 者 AT 命 令 等, 并 通 过 UART1 控 制 GPRS 模 块, 使 其 工 作 在 合 适 的 模 式, 并 完 成 短 消 息 的 发 送 或 者 接 收 工 作 实 验 步 骤 编 译 : 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project 2 ) 部 署 实 验 源 码, 将 光 盘 : 05- 实 验 例 程 / 第 13 章 / gprs_test 文 件 夹 拷 贝 到 /usr/local/src/s210x/project 路 径 下 ; 3) 编 译 并 拷 贝 gprs_test 程 序 : $ cd /usr/local/src/s210x/project/13.13-gprs_test $ make $ make install $ make clean 可 执 行 文 件 会 自 动 拷 贝 到 /opt/tftp 目 录 下 运 行 : 1) 正 确 设 置 ubuntu 系 统 的 网 络, 保 证 网 络 通 信 正 常

314 2) 准 备 好 s210x 实 验 平 台, 确 保 已 经 按 照 第 11 章 节 固 化 好 Linux 操 作 系 统 附 注 : 确 保 交 叉 网 线 和 交 叉 串 口 线 已 经 连 接 好 主 机 和 实 验 平 台, 在 终 端 上 用 ifconfig eth xxx 命 令 设 置 ip 地 址 核 对 主 机 网 卡 的 ip 地 址 和 s210x 实 验 平 台 的 ip 地 址 为 同 一 个 网 段 本 实 验 测 试 时, 主 机 网 卡 的 ip 地 址 为 ,s210x 实 验 平 台 的 ip 地 址 为 ) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 可 以 看 到 串 口 终 端 的 启 动 打 印 信 息 4) 系 统 启 动 完 成 后, 在 minicom 下 执 行 以 下 命 令 将 gprs_test 程 序 下 载 到 s210x 实 验 平 台 # tftp -g r./gprs_test -l/home/app/gprs_test 5) 给 gprs_test 添 加 可 执 行 权 限 : #cd /home/app/ # chmod 777 gprs_test 6) 运 行 应 用 程 序 #./gprs_test Select what you want to do: 1 : Simple Test 2 : Make A Call 3 : Wait A Call 4 : Short message 5 : Quit > 7) 输 入 1, 直 到 串 口 打 印 OK, 表 明 GPRS 信 号 通 畅 : >1 No data at OK 8) 如 果 GPRS 信 号 良 好, 则 选 择 2 可 以 拨 出 电 话 并 接 通, 根 据 提 示 需 要 输 入 对 方 电 话 号 码, 拨 通 后, 会 显 示 OK, 同 时 按 回 车 可 以 挂 机 >2 please input telephone number: No data atd ; OK Read Messages press enter to quit: [Enter]

315 No data ath OK 9) 如 果 GPRS 信 号 良 好, 则 选 择 3 可 以 等 待 接 入 电 话 并 接 通 : >3 No data No data No data No data RING some one call in... press 'A' and then press enter to answer, or press enter to hang up: 10) 其 他 功 能 用 户 可 以 自 行 根 据 提 示 操 作

316 第 十 四 章 嵌 入 式 GUI 设 计 实 验 目 前 的 桌 面 机 操 作 系 统 大 多 有 着 美 观 操 作 方 便 功 能 齐 全 的 GUI( 图 形 用 户 界 面 ), 例 如 KDE 或 者 GNOME GUI( 图 形 用 户 界 面 ) 是 指 计 算 机 与 其 使 用 者 之 间 的 对 话 接 口, 可 以 说,GUI 是 当 今 计 算 机 技 术 的 重 大 成 就 它 的 存 在 为 使 用 者 提 供 了 友 好 便 利 的 界 面, 并 大 大 地 方 便 了 非 专 业 用 户 的 使 用, 使 得 人 们 从 繁 琐 的 命 令 中 解 脱 出 来, 可 以 通 过 窗 口 菜 单 方 便 地 进 行 操 作 而 在 嵌 入 式 系 统 中,GUI 的 地 位 也 越 来 越 重 要, 但 是 不 同 于 桌 面 机 系 统, 嵌 入 式 GUI 要 求 简 单 直 观 可 靠 占 用 资 源 小 且 反 应 快 速, 以 适 应 系 统 硬 件 资 源 有 限 的 条 件 另 外, 由 于 嵌 入 式 系 统 硬 件 本 身 的 特 殊 性, 嵌 入 式 GUI 应 具 备 高 度 可 移 植 性 与 可 裁 减 性, 以 适 应 不 同 的 硬 件 条 件 和 使 用 需 求 总 体 来 讲, 嵌 入 式 GUI 具 备 以 下 特 点 : 体 积 小 ; 运 行 时 耗 用 系 统 资 源 少 ; 上 层 接 口 与 硬 件 无 关, 高 度 可 移 植 ; 高 可 靠 性 ; 在 某 些 应 用 场 合 应 具 备 实 时 性 14.1 主 机 编 译 Qt 实 验 目 的 了 解 什 么 是 QT 为 什 么 选 择 QT 以 及 QT 的 优 势 具 体 体 现 在 哪 些 方 面 ; 掌 握 在 主 机 上 编 译 Qt4.8 的 实 验 步 骤 以 及 如 何 验 证 主 机 成 功 编 译 Qt 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 1. 什 么 是 QT Qt 是 挪 威 的 Trolltech 公 司 基 于 C++ 的 GUI 开 发 工 具 QT/X11 和 QTE(QT Embedded) 是 它 其 中 的 两 个 版 本 Qt/X11 是 基 于 X Windows 系 统 的 Qt 版 本,KDE 便 是 基 于 它 来 构 建 的 为 了 适 用

317 于 嵌 入 式 系 统, 该 公 司 将 Qt/X11 进 行 了 裁 减, 发 布 了 QTE(QT Embedded) 版 本 QTE 直 接 基 于 Linux 中 的 FrameBuffer 设 备, 删 除 了 Qt/X11 中 一 些 对 资 源 要 求 很 高 的 类 实 现 所 以, 基 于 QTE 实 现 的 应 用, 不 作 修 改 重 新 编 译 后, 就 可 以 在 Qt/X11 上 运 行, 而 反 过 来 便 不 可 以 QPE 是 Trolltech 公 司 所 推 出 的 针 对 PDA 软 件 的 整 体 解 决 方 案, 包 含 了 从 底 层 的 GUI 系 统 Window Manager Soft Keyboard 到 上 层 的 PIM 浏 览 器 多 媒 体 等 方 面 目 前 QPE 的 高 版 本 已 更 名 为 Qtopia, 其 包 含 了 更 多 功 能 2. 为 什 么 选 择 QT QT 是 基 于 C++ 的 一 种 语 言 相 信 C/C++ 目 前 还 是 一 种 很 多 人 都 在 学 习 的 语 言 QT 的 好 处 就 在 於 QT 本 身 可 以 被 称 作 是 一 种 C++ 的 延 伸 QT 中 有 数 百 个 class 都 是 用 C++ 写 出 来 的 这 也 就 是 说,QT 本 身 就 具 备 了 C++ 的 快 速 简 易 Object-Oriented Programming(OOP) 等 等 无 数 的 优 点. 3.QT 具 有 非 常 好 的 可 移 植 性 (Portable) QT 不 只 是 可 以 在 Linux 中 运 作. 也 同 样 可 以 运 行 在 Microsoft Windows 中 这 也 就 意 味 者, 利 用 QT 编 写 出 来 的 程 式, 在 几 乎 不 用 修 改 的 情 况 下, 就 可 以 同 时 在 Linux 中 和 Microsoft Windows 中 运 行 QT 的 应 用 非 常 之 广 泛, 从 Linux 到 Windows 从 x86 到 Embedded 都 有 QT 的 影 子 实 验 步 骤 1) 设 置 工 作 环 境 : $ mkdir -p /usr/local/src/s210x/project/14.1-qt_x86 2) 部 署 实 验 源 码, 把 common 下 的 qt-everywhere-opensource-src tar.gz 拷 贝 到 /usr/local/src/s210x/project/14.1-qt_x86 目 录 ; 3) 执 行 下 面 步 骤 来 进 行 编 译, 该 编 译 过 程 总 共 大 概 需 要 花 费 半 个 小 时 左 右, 请 耐 心 等 待 : $ cd /usr/local/src/s210x/project/14.1-qt_x86 $ tar zxvf qt-everywhere-opensource-src tar.gz $ cd qt-everywhere-opensource-src $ echo "yes"./configure -prefix../qt opensource $ make $ make install 4) 编 译 成 功 后, 在 安 装 目 录 下 的 demos 文 件 夹 里 有 一 些 实 验 程 序, 可 以 验 证 qt 安 装 是 否 成 功, 比 如 在 当 前 终 端 执 行 下 列 代 码 进 行 验 证, 验 证 图 片 如 下 : $ cd /usr/local/src/s210x/project/14.1-qt_x86 $./qt4.8.3/demos/books/books

318 图 主 机 编 译 Qt4.8 成 功 验 证 界 面 14.2 移 植 Qt4.8 到 硬 件 平 台 实 验 目 的 掌 握 Qt4.8 移 植 到 硬 件 平 台 过 程 中 如 何 编 译 QT4.8 源 码 包 ; 掌 握 Qt4.8 移 植 到 硬 件 平 台 过 程 中 QT4.8 文 件 系 统 的 制 作 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Qt/Embedded 是 一 个 为 嵌 入 式 设 备 上 的 图 形 用 户 接 口 和 应 用 开 发 而 订 做 的 C++ 工 具 开 发 包 它 通 常 可 以 运 行 在 多 种 不 同 的 处 理 器 上 部 署 的 嵌 入 式 Linux 操 作 系 统 上 如 果 不 考 虑 X 窗 口 系 统 的

319 需 要, 基 于 Qt/Embedded 的 应 用 程 序 可 以 直 接 对 缓 冲 帧 进 行 写 操 作 除 了 类 库 以 外,Qt/Embedded 还 包 括 了 几 个 提 高 开 发 速 度 的 工 具, 使 用 标 准 的 Qt API, 我 们 可 以 非 常 熟 练 的 在 Windows 和 Unix 编 程 环 境 里 开 发 应 用 程 序 Qt/Embedded 提 供 了 一 种 类 型 安 全 的 被 称 之 为 信 号 与 插 槽 的 真 正 的 组 件 化 编 程 机 制, 这 种 机 制 和 以 前 的 回 调 函 数 有 所 不 同 Qt/Embedded 还 提 供 了 一 个 通 用 的 widgets 类, 这 个 类 可 以 很 容 易 的 被 子 类 化 为 客 户 自 己 的 组 件 或 是 对 话 框 针 对 一 些 通 用 的 任 务,Qt 还 预 先 为 客 户 定 制 了 像 消 息 框 和 向 导 这 样 的 对 话 框 运 行 Qt/Embedded 所 需 的 系 统 资 源 可 以 很 小, 相 对 X 窗 口 下 的 嵌 入 解 决 方 案 而 言,Qt/Embedded 只 要 求 一 个 较 小 的 存 储 空 间 (Flash) 和 内 存 Qt/Embedded 可 以 运 行 在 不 同 的 处 理 器 上 部 署 的 Linux 系 统, 只 要 这 个 系 统 有 一 个 线 性 地 址 的 缓 冲 帧 并 支 持 C++ 的 编 译 器 你 可 以 选 择 不 编 译 Qt/Embedded 某 些 你 不 需 要 的 功 能, 从 而 大 大 减 小 了 它 的 内 存 占 有 量 Qt/Embedded 包 括 了 它 自 身 的 窗 口 系 统, 并 支 持 多 种 不 同 的 输 入 设 备 开 发 者 可 以 使 用 他 们 熟 悉 的 开 发 环 境 来 编 写 代 码 Qt 的 图 形 设 计 器 (designer) 可 以 用 来 可 视 化 地 设 计 用 户 接 口, 设 计 器 中 有 一 个 布 局 系 统, 它 可 以 使 你 设 计 的 窗 口 和 组 件 自 动 根 据 屏 幕 空 间 的 大 小 而 改 变 布 局 开 发 者 可 以 选 择 一 个 预 定 义 的 视 觉 风 格, 或 是 建 立 自 已 独 特 的 视 觉 风 格 使 用 UNIX/LINUX 操 作 系 统 的 用 户, 可 以 在 工 作 站 上 通 过 一 个 虚 拟 缓 冲 帧 的 应 用 程 序 仿 真 嵌 入 式 系 统 的 显 示 终 端 Qt/Embedded 也 提 供 了 许 多 特 定 用 途 的 非 图 形 组 件, 例 如 国 际 化, 网 络 和 数 据 库 交 互 组 件 Qt/Embedded 是 成 熟 可 靠 的 工 具 开 发 包, 它 在 世 界 各 地 被 广 泛 使 用 除 了 在 商 业 上 的 许 多 应 用 以 外,Qt/Embedded 还 是 为 小 型 设 备 提 供 的 Qtopia 应 用 环 境 的 基 础 Qt/Embedded 以 简 洁 的 系 统, 可 视 化 的 表 单 设 计 和 详 致 的 API 让 编 写 代 码 变 得 愉 快 和 舒 畅 QT/Embedded 是 面 向 嵌 入 式 系 统 的 QT 版 本,QTE 是 Qt/Embedded 的 缩 写 形 式 qte 的 作 用 是 提 供 嵌 入 式 开 发 所 需 的 类 库 以 及 链 接 库, 在 开 发 板 上 运 行 QT 程 序 就 需 要 这 些 动 态 链 接 库 Qt/Embedded 只 支 持 鼠 标 和 键 盘 的 操 作, 但 在 大 部 分 嵌 入 式 系 统 中 利 用 触 摸 屏, 所 以 用 户 必 须 对 触 摸 屏 的 相 关 操 作 编 译 成 共 享 库 或 静 态 库 Qt/Embedded 采 用 两 种 方 式 进 行 发 布 : 在 GPL 协 议 下 发 布 的 free 版 与 专 门 针 对 商 业 应 用 的 commercial 版 本 二 者 除 了 发 布 方 式 外, 在 源 码 上 没 有 任 何 区 别 纵 向 看 来, 当 前 主 流 的 版 本 为 Qtopia 的 2.x 系 列 与 最 新 的 3.0x 系 列 其 中 2.0 版 本 系 统 较 多 地 应 用 于 采 用 Qtopia 作 为 高 档 PDA 主 界 面 的 应 用 中 ;3.x 版 本 系 列 则 应 用 于 功 能 相 对 单 一, 但 需 要 高 级 GUI 图 形 支 持 的 场 合, 如 Volvo 公 司 的 远 程 公 交 信 息 系 统 3.x 版 本 系 列 的 Qt/Embedded 相 对 于 2.x 版 本 系 统 增 加 了 许 多 新 的 模 块, 如 SQL 数 据 库 查 询 模 块 等 几 乎 所 有 2.x 版 本 中 原 有 的 类 库, 在 3.x 版 本 中 都 得 到 极 大 程 度 的 增 强 这 就 极 大 地 缩 短 了 应 用 软 件 的 开 发 时 间, 扩 大 了 Qt/Embedded 的 应 用 范 围 在 代 码 设 计 上,Qt/Embedded 巧 妙 地 利 用 了 C++ 独 有 的 机 制, 如 继 承 多 态 模 板 等, 具 体 实 现 非 常 灵 活 但 其 底 层 代 码 由 于 追 求 与 多 种 系 统 多 种 硬 件 的 兼 容, 代 码 补 丁 较 多, 风 格 稍 显 混 乱

320 实 验 步 骤 编 译 QT4.8 源 码 包 1) 设 置 工 作 环 境 : $ PATH=/usr/local/src/s210x/arm-2009q3/bin:$PATH $ mkdir -p /usr/local/src/s210x/project/14.2-qt_arm 2 ) 部 署 实 验 源 码, 光 盘 :05- 实 验 例 程 / 第 14 章 /common 下 的 qt-everywhere-opensource-src tar.gz 拷 贝 到 /usr/local/src/s210x/project/14.2-qt_arm 目 录 ; 3) 执 行 下 面 步 骤 来 解 压 缩 源 码 : $ cd /usr/local/src/s210x/project/14.2-qt_arm $ tar zxvf qt-everywhere-opensource-src tar.gz 修 改 mkspecs/qws/linux-arm-g++/qmake.conf 文 件, 替 换 所 有 arm-linux 为 arm-none-linux-gnueabi, 修 改 完 后 执 行 下 面 步 骤 来 进 行 编 译 : $ cd /usr/local/src/s210x/project/14.2-qt_arm/qt-everywhere-opensource-src $ echo "yes"./configure -prefix../qt opensource -embedded arm -xplatform qws/linux-arm-g++ -qt-libmng -qt-libjpeg -qt-mouse-pc -no-mouse-linuxtp -no-qt3support -little-endian 4 ) 执 行 make 命 令, 编 译 源 码 包, 执 行 make install 完 成 安 装 $ make $ make install QT4.8 文 件 系 统 的 制 作 1) 参 照 11.6 章 节 获 得 root-mini, 并 将 其 复 制 到 当 前 目 录, 执 行 代 码 如 下 所 示 : $ cd /usr/local/src/s210x/project/14.2-qt_arm $ cp -a../11.6-busybox/root-mini./ $ cp../11.6-busybox/make_ext4fs./ 2) 将 编 译 好 的 QT 库 及 DEMO 应 用 拷 贝 到 文 件 系 统 中, 并 添 加 执 行 脚 本 文 件 qt4: $ mkdir -p root-mini/opt/qt4.8.3 $ cp -a qt4.8.3/lib root-mini/opt/qt4.8.3/ $ cp -a qt4.8.3/demos root-mini/opt/qt4.8.3/ $ cp -a qt4.8.3/plugins root-mini/opt/qt4.8.3/ $ cp -a qt4 root-mini/bin/ $ chmod 777 root-mini/bin/qt4 3) 如 果 想 要 开 机 自 动 运 行 Qt Demo, 则 修 改 文 件 root-mini/etc/init.d/rcs 文 件, 将 最 后 一 行 的 注 释 去 掉, 使 其 变 为 : /bin/qt4 & 4) 重 新 制 作 ext4 文 件 系 统, 即 可 生 成 映 像 文 件 rootfs.img

321 $./make_ext4fs -l 256M -s rootfs.img root-mini 5) 参 照 11.6 章 节 烧 写 文 件 系 统 镜 像 到 实 验 板 中 开 机 启 动 后, 该 Demo 将 自 动 运 行, 界 面 如 下 图 所 示 : 图 实 验 平 台 自 带 Demo 运 行 界 面 14.3 Qt Creator 开 发 应 用 程 序 实 验 目 的 重 点 掌 握 Linux 下 Qt Creator 的 配 置 以 及 Qt Creator 开 发 QT 下 的 应 用 程 序 ; 分 别 运 行 桌 面 版 和 实 验 平 台 上 的 小 程 序, 验 证 QT 的 跨 平 台 特 点 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 Qt Creator 是 跨 平 台 的 Qt IDE, Qt Creator 是 Qt 被 Nokia 收 购 后 推 出 的 一 款 新 的 轻 量 级 集 成 开 发 环 境 (IDE) 此 IDE 能 够 跨 平 台 运 行, 支 持 的 系 统 包 括 Linux(32 位 及 64 位 ) Mac OS X 以 及 Windows 根 据 官 方 描 述,Qt Creator 的 设 计 目 标 是 使 开 发 人 员 能 够 利 用 Qt 这 个 应 用 程 序 框 架 更 加 快 速 及 轻 易 的 完 成 开 发 任 务 功 能 和 优 势 QtCreator 主 要 是 为 了 帮 助 新 Qt 用 户 更 快 速 入 门 并 运 行 项 目, 还 可 提 高 有 经 验 的 Qt 开 发 人

322 员 的 工 作 效 率 1 使 用 强 大 的 C++ 代 码 编 辑 器 可 快 速 编 写 代 码 语 法 标 识 和 代 码 完 成 功 能 输 入 时 进 行 静 态 代 码 检 验 以 及 提 示 样 式 上 下 文 相 关 的 帮 助 代 码 折 叠 括 号 匹 配 和 括 号 选 择 模 式 高 级 编 辑 功 能 2 使 用 浏 览 工 具 管 理 源 代 码 集 成 了 领 先 的 版 本 控 制 软 件, 包 括 Git Perforce 和 Subversion 开 放 式 文 件, 无 须 知 晓 确 切 的 名 称 或 位 置 搜 索 类 和 文 件 跨 不 同 位 置 或 文 件 沿 用 符 号 在 头 文 件 和 源 文 件, 或 在 声 明 和 定 义 之 间 切 换 3 为 Qt 跨 平 台 开 发 人 员 的 需 求 而 量 身 定 制 集 成 了 特 定 于 Qt 的 功 能, 如 信 号 与 槽 (Signals & Slots) 图 示 调 试 器, 对 Qt 类 结 构 可 一 目 了 然 集 成 了 Qt Designer 可 视 化 布 局 和 格 式 构 建 器 只 需 单 击 一 下 就 可 生 成 和 运 行 Qt 项 目 实 验 步 骤 Linux 下 Qt Creator 的 安 装 1) 设 置 工 作 环 境 : $ mkdir -p /usr/local/src/s210x/project/14.3-qtcreator 2 ) 将 光 盘 : 04- 常 用 工 具 /QT/qt-creator-linux-x86_64-opensource bin 拷 贝 到 /usr/local/src/s210x/project/14.3-qtcreator 目 录 3) 执 行 下 面 步 骤 来 进 行 安 装 : $ cd /usr/local/src/s210x/project/14.3-qtcreator $./qt-creator-linux-x86_64-opensource bin 4) 安 装 过 程 中, 读 者 可 自 定 义 安 装 路 径, 其 余 步 骤 按 默 认 安 装 即 可, 安 装 完 成 后, 桌 面 会 出 现 应 用 程 序 的 快 捷 图 标, 运 行 程 序 后 界 面 如 下 : 图 手 动 设 置 Qt 版 本

323 Linux 下 Qt Creator 的 配 置 1) 在 桌 面 上 找 到 Qt Creator, 打 开 后 可 以 看 到 主 界 面, 在 主 界 面 中 从 菜 单 栏 点 击 " 工 具 "->" 选 项 "-> 在 左 侧 点 击 " 构 建 和 运 行 " -> 选 择 "Qt 版 本 " 选 项 卡, 界 面 如 下 图 所 示, 点 击 按 钮 添 加 Host 版 本 和 ARM 版 本 的 构 建 环 境 路 径 : Qt 4.8.3(qt4.8.3-x86) /usr/local/src/s210x/project/14.1-qt_x86/qt4.8.3/bin/qmake Qt 4.8.3(qt4.8.3-arm) /usr/local/src/s210x/project/14.2-qt_arm/qt4.8.3/bin/qmake 图 手 动 设 置 Qt 版 本 2) 接 下 来 将 指 定 编 译 器,Qt Creator 已 经 检 测 到 X86 的 GCC, 只 需 要 手 动 设 置 指 定 用 于 arm 开 发 的 交 叉 工 具 链 即 可, 点 击 工 具 链 选 项 卡, 编 译 器 路 径 为 /usr/local/src/s210x/arm-2009q3/bin/arm-none-linux-gnueabi-g++, 如 图 中 所 示 配 置 完 成 后, 点 击 应 用 图 手 动 设 置 Qt 工 具 链 3) 分 别 对 QT 构 建 环 境 与 编 译 器 进 行 绑 定 : 点 击 Unconfigured Project 选 项 卡, 如 下 图 所

324 示, 指 定 设 备 类 型 所 用 的 编 译 器 版 本 以 及 QT 版 本, 配 置 桌 面 和 ARM 两 项, 分 别 对 应 在 PC 和 ARM 实 验 平 台 两 个 版 本 图 构 建 套 件 的 配 置 使 用 Qt Creator 进 行 初 步 开 发 1) 下 面 新 建 一 个 项 目, 点 击 菜 单 文 件 -> 新 建, 如 下 图 所 示, 选 择 Applications - Qt Gui 应 用 接 下 来 填 写 项 目 名 称 和 选 择 保 存 位 置 ; 图 新 建 一 个 Qt Gui 应 用 HelloWorld 2) 点 击 下 一 步 选 择 构 建 套 件, 将 桌 面 Embedded Linux 复 选 框 全 部 勾 选 上, 接 下 来 步 骤 按 默 认 操 作 即 可, 如 下 图 所 示 :

325 图 选 择 桌 面 套 件 图 选 择 helloworld 项 目 的 安 装 目 录 3) 工 程 新 建 完 成 后 可 以 看 到 工 程 目 录, 如 下 图 所 示 : 图 helloworld 工 程 目 录 文 件 4) 双 击 工 程 目 录 中 界 面 文 件 下 的 mainwindow.ui 文 件, 可 以 看 到 在 VS 下 利 用 C# 等 开 发 非 常 类 似 的 界 面, 可 以 从 左 侧 选 择 一 些 控 件 添 加 到 工 程 中, 右 下 角 可 以 针 对 具 体 的 控 件 属 性 进 行 修 改, 如 下 图 所 示 :

326 图 helloworld 工 程 可 视 化 编 辑 界 面 中 添 加 Lable 控 件 5) 点 击 左 下 角 的 直 接 运 行, 构 建 完 成 后 就 会 弹 出 刚 刚 设 计 的 界 面, 如 下 图 所 示 : 图 helloworld 工 程 在 pc 机 上 运 行 后 的 界 面 6) 接 下 来 进 行 实 验 平 台 上 运 行 的 程 序 的 开 发, 点 击 左 侧 项 目 按 钮, 添 加 Embedded Linux 的 构 建 设 置, 环 境 配 置 如 图 所 示 : 图 配 置 helloworld 工 程 在 实 验 平 台 上 运 行

327 7) 更 改 了 构 建 选 项 后, 点 击 左 下 角 构 建 项 目 按 钮, 生 成 arm 格 式 的 可 执 行 文 件 然 后 在 项 目 安 装 目 录 /home/ubuntu 同 等 级 目 录 下 找 到 自 动 生 成 的 文 件 夹, 执 行 下 列 命 令 : $ cd /home/ubuntu $ cd helloworld-build-embedded-qt_4_8_3-arm $ file helloworld 如 果 看 到 如 下 信 息, 则 表 示 helloworld 为 在 实 验 平 台 上 可 执 行 的 程 序 helloworld: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux , not stripped 8) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 参 照 前 面 章 节 关 于 tftp 的 使 用, 将 helloworld 传 到 实 验 平 台 的 /home/app/ 目 录 下 ; 9) 在 minicom 串 口 终 端 执 行 如 下 命 令 运 行 应 用 程 序, 在 实 验 平 台 上 可 以 看 到 如 下 界 面 : # cd /home/app #./helloworld -qws 图 helloworld 工 程 在 实 验 平 台 上 运 行 界 面 14.4 Qt Creator 开 发 Led 控 制 实 验 实 验 目 的 重 点 掌 握 Linux 下 Qt Creator 的 配 置 以 及 Qt Creator 开 发 QT 下 的 应 用 程 序 ; 掌 握 Linux 下 Qt Creator 利 用 QT 编 写 LED 控 制 程 序

328 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), s210x 系 列 实 验 平 台 ; 软 件 :ZEmberOS 操 作 系 统 实 验 原 理 LED 灯 只 有 两 种 状 态, 亮 与 不 亮 查 看 用 户 手 册 可 以 知 道, 当 GPIO 被 赋 予 低 电 平 的 时 候,LED 灯 被 点 亮, 否 则 将 处 于 熄 灭 的 状 态, 因 此, 只 要 设 置 好 管 脚 高 低 电 平 两 个 状 态 就 可 以 完 成 驱 动 程 序 连 接 底 层 硬 件 和 应 用 程 序 的 功 能 了 实 验 开 发 板 Led 的 原 理 图 如 下 : 图 LED 原 理 图 实 验 步 骤 1) 在 桌 面 上 打 开 Qt Creator, 在 菜 单 栏 点 击 文 件, 单 击 打 开 文 件 或 工 程, 选 择 光 盘 : 05- 实 验 例 程 / 第 14 章 /14.4-ledtest/ledtest/leds.pro 将 工 程 导 入 到 Qt Creator 环 境 中, 如 下 图 所 示 :

329 图 将 工 程 leds2/leds.pro 导 入 到 Qt Creator 2) 点 击 左 侧 项 目 按 钮 配 置 编 译 环 境, 如 下 图 所 示 : 图 通 过 项 目 选 项 卡 配 置 编 译 环 境 3) 点 击 左 下 角 构 建 项 目 按 钮, 生 成 arm 格 式 的 可 执 行 文 件 leds 4) 运 行 minicom 串 口 终 端, 给 实 验 平 台 加 电, 进 入 Linux 系 统, 将 目 录 home/ubuntu/leds-build-embedded-qt_4_8_3_qt4_8_3-arm 目 录 下 编 译 好 了 的 可 执 行 文 件 leds 传 输 到 实 验 平 台 /home/app 目 录 下 ; 5) 参 照 13.2 章 节 的 实 验 步 骤, 依 次 执 行 编 译 步 骤 的 步, 编 译 led_driver 程 序, 可 执 行 文 件 led.ko 会 自 动 拷 贝 到 /opt/tftp 目 录 下, 将 /opt/tftp/led.ko 传 输 到 实 验 平 台 的 /lib/modules/ 目 录 下 ; 6) 在 minicom 终 端 执 行 如 下 命 令 加 载 模 块 : # insmod led

330 7) 执 行 下 列 命 令 运 行 leds 执 行 程 序 : # cd /home/app #./leds -qws 8) 实 验 平 台 上 会 看 到 如 下 界 面 : 图 实 验 平 台 上 显 示 的 Led 控 制 对 话 框 图 单 击 led3 复 选 框 时 第 3 个 led 灯 亮

331 第 十 五 章 Android Ndk 开 发 Android & linux 系 统 与 应 用 开 发 本 章 节 主 要 介 绍 Android 中 间 件 开 发 的 基 本 过 程, 第 一 节 简 单 介 绍 中 间 件 开 发 的 基 础 知 识, 其 余 四 节 为 实 验 章 节, 实 验 内 容 包 括 Android 中 间 件 开 发 基 础,Android JNI 的 介 绍,NDK 环 境 构 建 NDK 开 发 LED 中 间 件 和 NDK 开 发 串 口 中 间 件 通 过 本 章 节 的 学 习, 可 以 熟 悉 和 掌 握 Android 中 间 件 开 发 的 基 本 方 法 15.1 Ndk 开 发 基 础 中 间 件 相 关 名 词 解 释 表 中 间 件 相 关 名 词 解 释 名 词 解 释 操 作 系 统 和 应 用 程 序 的 沟 通 桥 梁, 并 分 为 两 层 : 函 数 层 (Library) 和 虚 拟 机 (Virtual 中 间 件 Machine) 应 用 程 序 用 Java 语 言 开 发, 操 作 系 统 代 码 则 是 C 代 码, 它 们 之 间 的 通 信 需 要 用 JNI 来 实 现 本 地 编 程 接 口, 它 使 得 在 Java 虚 拟 机 (VM) 内 部 运 行 的 Java 代 码 能 够 与 函 数 层 JNI (Library) 的 C/C++ 本 地 库 进 行 交 互 操 作 JNI 的 源 文 件 为 普 通 的 cpp 文 件, 编 译 后 为 so 文 件 C/C++ 被 编 译 后 生 成 的 动 态 库 文 件, 被 Java 代 码 载 入 调 用 如 果 是 应 用 者 开 发 的 so 文 件 JNI 标 准 so 文 件, 可 以 和 应 用 程 序 一 起 打 包 在 apk 文 件 里 该 文 件 向 编 译 系 统 描 述 你 的 源 代 码, 是 GNU Makefile 的 一 小 部 分, 会 被 编 译 系 统 Android.mk 解 析 一 次 或 多 次 的 build 系 统 每 个 需 要 被 编 译 的 代 码 文 件 都 有 与 之 对 应 的 mk 文 件 Android application package 文 件 每 个 要 安 装 到 Android 平 台 的 应 用 都 要 被 编 译 apk 文 件 打 包 为 一 个 单 独 的 apk 文 件 如 果 应 用 代 码 调 用 自 己 实 现 的 JNI, 需 要 将 so 文 件 打 包 在 apk 中 Android NDK 是 一 套 工 具, 允 许 Android 应 用 开 发 者 嵌 入 从 C C++ 源 代 码 文 件 编 译 来 的 本 地 机 器 代 码 到 各 自 的 应 用 软 件 包 中 就 是 将 JNI 的 so 文 件 和 java 应 用 一 NDK 起 打 包 成 apk 如 果 不 使 用 NDK 工 具,so 和 java 应 用 的 打 包 工 作 由 Android.mk 描 述 给 交 叉 编 译 系 统 通 过 资 源 打 包 的 方 式 实 现 中 间 件 开 发 步 骤 1) 实 现 JNI, 为 上 层 Java 应 用 程 序 提 供 函 数 接 口 2) 实 现 本 地 C/C++ 代 码, 调 用 内 核 代 码 提 供 的 接 口

332 JNI 基 础 知 识 JNI(Java Native Interface) 中 文 为 Java 本 地 接 口 从 Java1.1 开 始,JNI 标 准 成 为 Java 平 台 的 一 部 分, 它 允 许 Java 代 码 和 其 他 语 言 写 的 代 码 进 行 交 互 JNI 是 本 地 编 程 接 口, 它 使 得 在 Java 虚 拟 机 (VM) 内 部 运 行 的 Java 代 码 能 够 与 其 它 编 程 语 言 编 写 的 应 用 程 序 和 库 进 行 交 互 操 作 JNI 一 开 始 是 为 了 本 地 已 编 译 语 言, 尤 其 是 C 和 C++ 而 设 计 的, 但 是 它 并 不 妨 碍 你 使 用 其 他 语 言, 只 要 调 用 约 定 受 支 持 就 可 以 了 JNI 一 般 有 以 下 一 些 应 用 场 景 : 1) 高 性 能, 在 一 些 情 况 下 因 为 处 理 运 算 量 非 常 大, 为 了 获 取 高 性 能, 直 接 使 用 java 是 不 能 胜 任 的, 如 : 一 些 图 形 的 处 理 ; 2) 调 用 一 些 硬 件 的 驱 动 或 者 一 些 软 件 的 驱 动, 比 如 调 用 一 些 外 部 系 统 接 口 的 驱 动, 如 : 读 卡 器 的 驱 动,OCI 驱 动 ; 3) 需 要 使 用 大 内 存, 远 远 超 过 VM 所 能 分 配 的 内 存, 如 : 进 程 内 Cache; 4) 调 用 C 或 者 操 作 系 统 提 供 的 服 务, 如 java 调 用 搜 索 服 务, 搜 索 是 由 C/C++ 实 现 的 JNI 的 架 构 由 于 Android 的 应 用 层 的 类 都 是 以 Java 写 的, 这 些 Java 类 编 译 为 Dex 形 式 的 Bytecode 之 后, 必 须 靠 Dalvik 虚 拟 机 (VM: Virtual Machine) 来 执 行 在 执 行 Java 类 的 过 程 中, 如 果 Java 类 需 要 与 C 组 件 沟 通 时,VM 就 会 通 过 JNI 去 载 入 C 组 件, 然 后 让 Java 的 函 数 顺 利 地 调 用 到 C 组 件 的 函 数 在 Android 中, 主 要 的 JNI 代 码 放 在 以 下 的 路 径 中 :frameworks/base/core/jni/, 这 个 路 径 中 的 内 容 被 编 译 成 库 libandroid_runtime.so, 这 是 个 普 通 的 动 态 库, 被 放 置 在 目 标 系 统 的 /system/lib 目 录 下 此 外,android 还 有 其 他 的 JNI 库 JNI 中 的 各 个 文 件, 实 际 上 就 是 普 通 的 C++ 源 文 件 ; 在 android 中 实 现 的 JNI 库, 需 要 连 接 动 态 库 libnativehelper.so 文 件 对 于 开 发 者 自 己 实 现 的 JNI 库 *.so 文 件 与 Java 应 用 一 起 打 包 到 apk 文 件 中 应 用 程 序 加 载 动 态 库 后 就 可 以 调 用 本 地 函 数 JNI 在 Android 层 次 结 构 中 的 作 用 如 图 所 示 : 图 JNI 在 Android 层 级 结 构 中 的 作 用

333 通 常 JNI 的 使 用 自 上 至 下 有 4 层, 本 地 库,JNI 库, 声 明 本 地 接 口 的 Java 类,Java 调 用 者 15.2 搭 建 Ndk 编 译 环 境 实 验 目 的 了 解 Ndk 编 译 环 境 中 Cygwin 安 装 与 调 试 ; 了 解 Ndk 的 环 境 变 量 设 置 ; 掌 握 如 何 编 译 运 行 Ndk 例 程 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 在 Android SDK 文 档 里, 找 不 到 任 何 JNI 方 面 的 帮 助 即 使 第 三 方 应 用 开 发 者 使 用 JNI 完 成 了 自 己 的 C 动 态 链 接 库 (so) 开 发, 但 是 so 如 何 和 应 用 程 序 一 起 打 包 成 apk 并 发 布? 这 里 面 也 存 在 技 术 障 碍 虽 然 可 以 通 过 安 装 交 叉 编 译 器, 并 通 过 asset( 资 源 ) 方 式, 实 现 捆 绑 so 发 布 但 这 种 方 式 只 能 属 于 取 巧 的 方 式, 并 非 官 方 支 持 所 以, 在 NDK 出 来 之 前, 我 们 将 Java+C 的 开 发 模 式 称 之 为 灰 色 模 式, 即 官 方 既 不 声 明 支 持 这 种 方 式, 也 不 声 明 不 支 持 这 种 方 式 NDK 集 成 了 交 叉 编 译 器, 并 提 供 了 相 应 的 mk 文 件 隔 离 CPU 平 台 ABI 等 差 异, 开 发 人 员 只 需 要 简 单 修 改 mk 文 件 ( 指 出 哪 些 文 件 需 要 编 译 编 译 特 性 要 求 等 ), 就 可 以 创 建 出 so NDK 可 以 自 动 地 将 so 和 Java 应 用 一 起 打 包, 极 大 地 减 轻 了 开 发 人 员 的 打 包 工 作 比 较 简 单 的 说,NDK 是 一 套 交 叉 编 译 工 具, 它 可 以 帮 你 把 你 用 C 或 C++ 书 写 的 代 码, 编 译 为.so( 类 似 与 win 下 的.dll) 格 式 的 文 件, 使 你 可 以 在 你 的 Android 程 序 当 中 用 Java 语 言 (JNI) 调 用 这 些 代 码 实 验 步 骤 Cygwin 安 装 与 调 试 : 下 面 将 介 绍 Cygwin 安 装 与 调 试 :

334 由 于 NDK 编 译 代 码 时 必 须 要 用 到 make 和 gcc, 所 以 你 必 须 先 搭 建 一 个 linux 环 境,cygwin 是 一 个 在 windows 平 台 上 运 行 的 unix 模 拟 环 境 1 ) 从 出 厂 光 盘 得 到 ndk 的 安 装 文 件 (DISK-S210XA80\04- 常 用 工 具 \Android\ android-ndk-r8d-windows), 解 压 到 D 盘 根 目 录 下 2) 从 出 厂 光 盘 得 到 cygwin 的 安 装 文 件 (DISK-S210XA80\04-Tools\Android\cygwin), 解 压 到 D 盘 根 目 录 下 3) 双 击 cygwin 目 录 下 的 cygwin.reg 导 入 注 册 信 息 ; 4) 双 击 cygwin 目 录 下 的 cygwin.bat 运 行 cygwin, 默 认 进 入 到 NDK 的 根 目 录 ; 附 注 : 复 制 zbuild.bat 到 你 的 android 工 程 目 录, 双 击 zbuild.bat 运 行 即 可 自 动 编 译 你 的 工 程 5) 进 入 cygwin 界 面 后, 检 查 make 和 gcc 安 装 是 否 成 功, 分 别 键 入 make -v 和 gcc -v, 如 出 现 红 框 中 内 容, 则 安 装 成 功 : 图 检 查 cygwin 是 否 安 装 成 功 NDK 的 环 境 变 量 设 置 1) 设 置 NDK 的 运 行 环 境 变 量 : 右 键 单 击 我 的 电 脑 -> 属 性 -> 高 级 -> 环 境 变 量, 在 系 统 变 量 中 新 建 NDK 变 量, 内 容 为 D:\android-ndk-r8d 图 新 建 NDK 变 量 2) 设 置 Android 的 运 行 环 境 变 量 : 右 键 单 击 我 的 电 脑 -> 属 性 -> 高 级 -> 环 境 变 量, 编 辑 系 统 变 量 中 的 path 变 量, 在 后 面 添 加 :

335 ;D:\android-ndk-r8d; 3) 打 开 cygwin, 输 入 cd $NDK pwd, 如 果 输 出 如 图 /cygdrive/d/android-ndk-r8d 信 息, 则 表 明 环 境 变 量 设 置 成 功 了 图 NDK 环 境 变 量 配 置 成 功 编 译 NDK 例 程 现 在 我 们 用 安 装 好 的 NDK 来 编 译 一 个 简 单 的 程 序, 我 们 选 择 ndk 自 带 的 例 子 hello-jni 运 行 cygwin( 双 击 cygwin.bat), 操 作 如 下 : $ cd $NDK/samples/hello-jni/ $ ndk-build 执 行 成 功 后, 它 会 自 动 生 成 一 个 libs 目 录, 并 在 目 录 下 生 成 的.so 文 件 此 时 去 hello-jni 的 libs 目 录 下 看 有 没 有 生 成 的.so 文 件, 如 果 有,ndk 就 运 行 正 常 了 运 行 NDK 例 程 先 将 hello-jni 文 件 夹 拷 贝 到 sdk ( 比 如 D:\adt-bundle-windows\sdk ) 下 的 extras\android\support\samples 目 录 下, 打 开 eclipse, 选 择 File->New->Android Sample Project, Build Target 选 项 选 择 Android 2.3.1, 在 samples 的 下 拉 窗 体 中 选 择 hello-jni, 配 置 如 图 所 示 :

336 图 Create an Android Sample Project 图 select Build Target

337 图 select sample 将 开 发 平 台 通 过 usb 与 PC 连 接, 右 键 点 击 例 程 HelloJni, 选 择 Run As->Android Application 在 平 台 的 Android 应 用 界 面 找 到 HelloJni 图 标, 运 行 后 如 下 图 所 示 图 运 行 NDK 例 程 HelloJNI

338 15.3 Ndk 开 发 LED 实 例 实 验 目 的 了 解 Ndk 开 发 LED 实 例 的 过 程 与 方 法 ; 了 解 通 过 超 级 终 端 控 制 系 统 LED 驱 动 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 NDK 原 理 1)NDK 下 JNI 文 件 不 需 要 去 注 册 方 法, 只 需 要 本 地 函 数 有 标 准 的 命 名 规 则, 例 如 一 个 串 口 JNI 的 Opendevice() 函 数 在 java 文 件 中 的 native 声 明 如 下 : public static native int opendevice(); 对 应 的 JNI 源 文 件 中, 需 要 如 下 所 示 的 定 义 方 式 : JNIEXPORT static jint JNICALL Java_com_android_EMobile_LedDevice_opendevice(JNIEnv *env, jobject obj){} 这 里 的 命 名 规 则 为 类 型 :JNIEXPORT <JNI 函 数 类 型 > JNICALL 函 数 名 :Java_PackageName_ClassName_FunctionName PackageName 是 包 名, 其 中 的. 用 _ 代 替, 如 果 包 名 中 本 身 含 有 _ 字 符, 则 用 _1 代 替 ; ClassName 是 类 名, 同 样 如 果 类 名 中 包 含 _, 则 用 _2 代 替 ; FunctionName 即 为 Java 中 用 native 声 明 的 函 数 名 参 数 :JNIENV *env 与 jobject obj 为 默 认 参 数, 必 须 得 有 2)NDK 实 现 的 JNI 函 数 只 是 靠 命 名 规 则 识 别, 而 不 是 方 法 实 现 与 注 册,JNI 只 能 查 找 到 C style 的 Symbol 3)NDK 实 现 JNI 时, 如 果 要 使 用 LOGD 函 数, 在 源 文 件 中 必 须 包 含 如 下 头 文 件 : #include <android/log.h> #define LOGD(...) android_log_print(android_log_debug, "keymatch", VA_ARGS )

339 另 外, 在 脚 本 文 件 Android.mk 编 译 对 应 文 件 处 加 上 : LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib llog 4)NDK 在 实 现 双 库 更 加 简 单, 在 Android 源 码 编 译 下, 硬 件 抽 象 层 的 so 和 JNI 的 so 两 个 库, JNI 的 so 可 以 打 包 到 apk 中 去, 而 硬 件 抽 象 层 的 so 只 能 通 过 ADB 的 push 指 令 添 加 到 system/lib 目 录 下, 整 个 程 序 才 能 运 行 在 NDK 中, 可 以 实 现 将 硬 件 抽 象 层 的 函 数 编 译 成 静 态 库.a 文 件 并 引 用 到 JNI 编 译 成 的 共 享 库.so 里, 那 么 在 so 打 包 进 apk 后, 直 接 安 装 apk 程 序 就 可 以 运 行 起 来 双 库 的 实 现 需 要 编 写 对 应 的 Android.mk 脚 本 : LOCAL_PATH:= $(call my-dir) # 文 件 路 径 include $(CLEAR_VARS) # 清 除 变 量 LOCAL_MODULE := xxx1 # 静 态 库 名 LOCAL_SRC_FILES := xxx1 # 编 译 成 此 库 的 源 文 件 include $(BUILD_STATIC_LIBRARY) # 编 译 成 静 态 库 include $(CLEAR_VARS) # 清 除 变 量 LOCAL_MODULE :=xxx2 # 共 享 库 名 LOCAL_SRC_FILES := xxx2 # 编 译 成 此 库 的 源 文 件 LOCAL_STATIC_LIBRARIES := xxx1 include $(BUILD_SHARED_LIBRARY) # 引 用 静 态 库 # 编 译 成 共 享 库 创 建 NDK 工 程 1) 首 先 在 ndk 的 samples 目 录 下 创 建 自 己 的 工 程 ndk-projcet, 然 后 在 这 个 文 件 夹 下, 创 建 两 个 目 录 jni 和 src,jni 用 来 放 我 们 的 c/c++ 文 件,src 是 调 用 库 的 java 接 口 文 件 2) 在 jni 目 录 下 创 建 你 的 c/c++ 文 件 和 Andriod.mk 文 件 c/c++ 文 件 参 考 上 面 的 前 三 条 编 写, 主 要 是 JNI 函 数 名 的 规 则, 一 定 要 按 照 下 面 的 标 准 写 : JNIEXPORT <JNI 函 数 类 型 > JNICALL Java_PackageName_ClassName_FunctionName(JNIEnv *env, jobject obj,...){} Andriod.mk 文 件 描 述 该 如 何 编 译 你 的 源 文 件, 这 里 需 要 描 述 你 所 有 c/c++ 文 件 的 编 译 方 法, 哪 些 编 译 为 静 态 库, 哪 些 编 译 为 动 态 库, 哪 些 需 要 被 引 用 例 如 例 程 里 的 com_android_emobile_leddevice.c 文 件 是 JNI 文 件, 这 里 之 所 以 用 c 而 不 是 c++, 是 因 为 JNI 编 译 的 共 享 库 需 要 引 用 led_hal.c 编 译 成 的 静 态 库, 同 时 c 文 件 引 用 会 比 较 简 单 对 应 的 Andriod.mk 描 述, 可 参 照 上 面 编 译 双 库 的 mk 文 件 参 考 看 : 3) 前 面 讲 过, 在 工 程 的 src 夹 子 下 用 来 放 置 Java 文 件 我 们 打 开 Eclipse, 然 后 新 建 一 个 Android 工 程, 工 程 路 径 选 择 我 们 创 建 的 NDK 的 路 径 这 里 需 要 注 意 的 是, 工 程 名, 包 名 等, 需 要 和 上 面 的 c 文 件 中 的 保 持 一 致

340 4)Eclipse 工 程 建 立 好 后, 编 辑 src/< 包 名 >/ndk-projcet.java 文 件, 注 意 用 native 声 明 JNI 函 数, 可 参 照 前 几 节 例 程 的 Java 函 数 例 如 例 程 里 的 src/com/android/emobile/leddevice.java 有 : public static native int opendevice(); public static native int closedevice(); public static native int switchonoff(int num,int on_off); public static native int getstate(int num); 这 里 用 native 声 明 的 opendevice 函 数 对 应 JNI 文 件 里 函 数 名 Java_com_android_emo bile_leddevice_opendevice 最 尾 部 的 部 分,java 里 其 余 的 内 容 与 源 码 编 译 时 的 java 文 件 内 容 一 致 5) 建 立 好 整 个 工 程, 再 次 编 译, 先 将 工 程 文 件 夹 拷 贝 到 D:\android-ndk-r8d\samples 目 录 下 在 cygwin 中 进 入 工 程 目 录 下 运 行 $NDK/ndk-build 这 时 应 该 可 以 看 到 生 成 lib 目 录, 其 下 有 so 文 件 代 码 如 图 : $ cd $NDK/samples/ndk_led/ $ ndk-build 实 验 步 骤 移 植 LED 驱 动 模 块 1) 首 先, 通 过 开 始 -> 运 行 -> 输 入 cmd, 打 开 DOS 窗 口, 将 13.2 章 节 的 led 驱 动 模 块 led.ko 文 件 push 到 android 系 统 data 文 件 目 录 下, 代 码 如 下 : C:\ >adb push led.ko /data/ # 事 先 将 led.ko 拷 贝 到 C 盘 根 目 录 1708 KB/s (87456 bytes in 0.050s) 2) 将 开 发 平 台 通 过 串 口 线 与 PC 连 接, 打 开 超 级 终 端 后, 上 电 启 动 Android 系 统, 系 统 完 全 启 动 后 在 超 级 终 端 通 过 insmod 命 令 将 led.ko 模 块 载 入 到 系 统 /dev/ 下, 通 过 lsmod 查 看 载 入 是 否 成 功 如 图 所 示 : # insmod /data/led.ko # lsmod led Live 0xbf ) 确 保 能 够 在 /dev/ 下 找 到 led_light 这 个 驱 动, 并 改 变 led_light 的 权 限, 如 图 所 示 : # cd /dev/ # ls -l led_light crw root root 250, :12 led_light # chmod 777 led_light 运 行 led 实 例 1) 将 实 验 板 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 ndk_led 通 过 Import->Existing Projects into

341 Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上 如 图 所 示 : 图 ndk_led 实 例 运 行 界 面 2) 单 击 界 面 上 的 Turn ON LED2 按 钮, 可 以 使 led2 被 点 亮, 单 击 Turn OFF LED2 可 以 使 led2 熄 灭, 单 击 Get LED2 State 可 以 获 得 当 前 led2 的 状 态 并 显 示 在 屏 幕 下 方 3) 单 击 界 面 上 的 Turn ON LED4 按 钮, 可 以 使 led4 被 点 亮, 单 击 Turn OFF LED4 可 以 使 led4 熄 灭, 单 击 Get LED4 State 可 以 获 得 当 前 led4 的 状 态 并 显 示 在 屏 幕 下 方 15.4 Ndk 开 发 串 口 实 例 实 验 目 的 了 解 Ndk 开 发 串 口 实 例 的 过 程 与 方 法 ; 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 SerialPortData 实 现 原 理 串 口 中 间 件 对 应 的 JNI 源 文 件 中 定 义 了 如 何 得 到 各 种 波 特 率, 如 何 打 开 和 关 闭 串 口,SerialPort.c

342 中 实 现 具 体 功 能 的 函 数 定 义 如 下 所 示 : static speed_t getbaudrate (jint baudrate) {} JNIEXPORT jobject JNICALL Java_com_x210_android_serialPortData_SerialPort_open(JNIEnv *env,jobject thiz,jstring path,jint baudrate) {} JNIEXPORT jobject JNICALL Java_com_x210_android_serialPortData_SerialPort_close(JNIEnv *env,jobject thiz,jstring path,jint baudrate) {} JNI 中 对 应 的 Android.mk 脚 本 : LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) TARGET_PLATFORM := android-3 LOCAL_MODULE := serial_port LOCAL_SRC_FILES := SerialPort.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) JNI 层 程 序 (SerialPort.c) 中 的 串 口 open() 函 数 和 close() 函 数 在 串 口 应 用 程 序 (SerialPort.java) 中 声 明 本 地 接 口, 具 体 代 码 如 下 : // JNI private native static FileDescriptor open(string path, int baudrate); public native void close(); static { System.loadLibrary("serial_port"); } 串 口 程 序 所 实 现 的 JNI 库 *.so 文 件 与 Java 应 用 一 起 打 包 到 apk 文 件 中, 应 用 程 序 加 载 动 态 库 后 就 可 以 调 用 本 地 函 数 实 验 步 骤 NDK-SerialPortData 编 译 例 程 先 将 SerialPortSample 工 程 文 件 夹 拷 贝 到 D:\android-ndk-r8d\samples 目 录 下 在 cygwin 中 进 入 工 程 目 录 下 运 行 $NDK/ndk-build 这 时 应 该 可 以 看 到 生 成 lib 目 录, 其 下 有 so 文 件 代 码 如 图 : $ cd $NDK/samples/SerialPortSample/ $ ndk-build

343 修 改 s3c2410_serial0 的 权 限 通 过 开 始 -> 运 行 -> 输 入 cmd, 打 开 DOS 窗 口, 执 行 adb shell 进 入 到 Linux 的 命 令 行 界 面, 执 行 命 令 修 改 串 口 驱 动 s3c2410_serial0 的 权 限 : C:\ > adb shell # chmod 777 /dev/s3c2410_serial0 eclipse 运 行 SerialPortSample 实 例 1) 将 实 验 板 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 SerialPortSample 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上 如 图 所 示 : 图 SerialPortSample 界 面 2) 在 超 级 终 端 中 输 入 字 符,Reception 编 辑 框 中 会 显 示 这 些 输 入 的 字 符 在 Emission 编 辑 框 中 输 入 字 符, 这 些 字 符 会 显 示 在 超 级 终 端 上 图 接 收 数 据 和 发 送 数 据 3) 触 摸 Clear 按 钮, 会 清 除 输 入 编 辑 框 和 输 入 编 辑 框 中 的 数 据

344 图 清 除 数 据 4) 按 下 实 验 平 台 的 MENU 按 键, 会 弹 出 ABOUT 和 EXIT 菜 单 选 项 触 摸 ABOUT 按 钮, 会 弹 出 ABUOT 信 息, 触 摸 EXIT 按 钮, 会 退 出 SerialPortSample 例 程 图 MENU 菜 单

345 第 十 六 章 Android 硬 件 接 口 Android & linux 系 统 与 应 用 开 发 本 章 节 根 据 x210 开 发 实 验 平 台 的 硬 件 配 置, 由 浅 入 深 地 安 排 了 按 键 / 键 盘 移 植 存 储 设 备 移 植 (SD 卡 /U 盘 ) WIFI 设 备 移 植 GPS 设 备 移 植 蓝 牙 设 备 移 植 摄 像 头 设 备 移 植 电 话 ril 层 移 植 等 实 验, 重 点 讲 述 了 硬 件 原 理 以 及 Android 下 的 驱 动 开 发 以 及 应 用 程 序 开 发 的 方 法 16.1 按 键 / 键 盘 移 植 实 验 目 的 了 解 按 键 电 路 原 理 ; 了 解 linux 下 按 键 驱 动 的 编 写 ; 掌 握 android 应 用 程 序 如 何 使 用 按 键 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 按 键 电 路 原 理 按 键 同 样 使 用 GPIO 接 口, 但 按 键 本 身 需 要 外 部 的 输 入, 按 键 硬 件 驱 动 原 理 图 如 图 所 示 在 下 图 的 1 6 矩 阵 按 键 (SW4~SW9) 电 路 中, 使 用 6 个 输 入 (EINT2 EINT3 EINT4 EINT8 EINT9 和 EINT11)

346 中 断 入 口 对 应 的 核 心 板 接 口 电 路 如 下 图 所 示 : 图 按 键 电 路 图 核 心 板 接 口 电 路 按 键 入 口 对 应 于 核 心 板 的 GPHO 接 口, 当 其 中 一 个 SW 按 键 被 按 下, 通 过 查 询 方 式 就 可 以 检 测 到 是 哪 一 个 接 口 有 输 入 信 号, 从 而 控 制 相 应 的 操 作 以 上 的 讨 论 都 是 在 按 键 的 理 想 状 态 下 进 行 的, 但 实 际 的 按 键 动 作 会 在 短 时 间 ( 几 毫 秒 至 几 十 毫 秒 ) 内 产 生 信 号 抖 动 例 如, 当 按 键 被 按 下 时, 其 动 作 就 像 弹 簧 的 若 干 次 往 复 运 动, 将 产 生 几 个 脉 冲 信 号 一 次 按 键 操 作 将 会 产 生 若 干 次 按 键 中 断, 从 而 会 产 生 抖 动 现 象 因 此 驱 动 程 序 中 必 须 要 解 决 去 除 抖 动 所 产 生 的 毛 刺 信 号 的 问 题 Linux 系 统 下 按 键 驱 动 的 编 写 设 备 驱 动 程 序 首 先 应 包 含 设 备 的 注 册 和 释 放 函 数, 即 static int init s3c_button_init(void) 和 static void exit s3c_button_exit(void) /* 模 块 的 初 始 化 */

347 static int init s3c_button_init(void) { platform_device_register(&s3c_device_button); return platform_driver_register(&s3c_button_device_driver); } /* 模 块 的 退 出 */ static void exit s3c_button_exit(void) { platform_driver_unregister(&s3c_button_device_driver); platform_device_unregister(&s3c_device_button); } 首 先 定 义 platform_device 函 数 接 着 注 册 platform_device 再 定 义 platform_driver, 最 后 注 册 platform_driver static struct platform_driver s3c_button_device_driver = {.probe = s3c_button_probe,.remove = s3c_button_remove,.suspend = s3c_button_suspend,.resume = s3c_button_resume,.driver = {.name = "s3c-button",.owner = THIS_MODULE, } static struct platform_device s3c_device_button = { };.name.id = -1, = "s3c-button", 在 s3c_button_probe 函 数 中 设 置 相 关 按 键 的 寄 存 器 : static int s3c_button_probe(struct platform_device *pdev) { int i; int ret; /* gph0_1 (power) */ ret = gpio_request(s5pv210_gph0(1), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(1) fail"); /* gph0_2 (menu) */ ret = gpio_request(s5pv210_gph0(2), "GPH0");

348 if(ret) printk("button-smdkv210: request gpio GPH0(2) fail"); /* gph0_3 (home) */ ret = gpio_request(s5pv210_gph0(3), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(3) fail"); /* gph0_4 (back) */ ret = gpio_request(s5pv210_gph0(4), "GPH0"); if(ret) printk("button-smdkv210: request gpio GPH0(4) fail"); /* gph1_0 (vol-) */ ret = gpio_request(s5pv210_gph1(0), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(0) fail"); /* gph1_1 (vol+) */ ret = gpio_request(s5pv210_gph1(1), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(1) fail"); /* gph1_3 (camera) */ ret = gpio_request(s5pv210_gph1(3), "GPH1"); if(ret) printk("button-smdkv210: request gpio GPH1(3) fail"); s3c_gpio_setpull(s5pv210_gph0(1), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(1), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(2), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(2), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(3), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(3), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph0(4), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph0(4), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph1(0), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(0), S3C_GPIO_SFN(0)); s3c_gpio_setpull(s5pv210_gph1(1), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(1), S3C_GPIO_SFN(0));

349 s3c_gpio_setpull(s5pv210_gph1(3), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(s5pv210_gph1(3), S3C_GPIO_SFN(0)); s3c_button_history[0] = gpio_get_value(s5pv210_gph0(1)); s3c_button_history[1] = gpio_get_value(s5pv210_gph0(2)); s3c_button_history[2] = gpio_get_value(s5pv210_gph0(3)); s3c_button_history[3] = gpio_get_value(s5pv210_gph0(4)); s3c_button_history[4] = gpio_get_value(s5pv210_gph1(0)); s3c_button_history[5] = gpio_get_value(s5pv210_gph1(1)); s3c_button_history[6] = gpio_get_value(s5pv210_gph1(3));}; 再 开 启 定 时 器 定 时 扫 描 ; init_timer(&timer); timer.function = s3cbutton_timer_handler; timer.expires = jiffies + (HZ/100); add_timer(&timer); printk("s3c button Initialized!!\n"); return 0; 在 定 时 器 中 断 函 数 s3cbutton_timer_handler 中 判 断 相 应 IO 口 的 电 平, 达 到 监 控 按 键 的 作 用 static void s3cbutton_timer_handler(unsigned long data) { int flag; /* POWER */ flag = gpio_get_value(s5pv210_gph0(1)); if(flag!= s3c_button_history[0]) { if(flag) input_report_key(input, s3c_keycode[0], 0); else input_report_key(input, s3c_keycode[0], 1); s3c_button_history[0] = flag; } /* MENU */ flag = gpio_get_value(s5pv210_gph0(2)); if(flag!= s3c_button_history[1]) { if(flag) input_report_key(input, s3c_keycode[1], 0); else

350 input_report_key(input, s3c_keycode[1], 1); s3c_button_history[1] = flag; } /* VOLUME_UP */ flag = gpio_get_value(s5pv210_gph1(1)); if(flag!= s3c_button_history[5]) { if(flag) input_report_key(input, s3c_keycode[5], 0); else input_report_key(input, s3c_keycode[5], 1); s3c_button_history[5] = flag; } /* CAMERA */ flag = gpio_get_value(s5pv210_gph1(3)); if(flag!= s3c_button_history[6]) { if(flag) input_report_key(input, s3c_keycode[6], 0); else input_report_key(input, s3c_keycode[6], 1); s3c_button_history[6] = flag; } /* Kernel Timer restart */ mod_timer(&timer,jiffies + HZ/100); }; 向 内 核 申 请 一 个 input_dev, 再 对 其 作 些 简 单 的 初 始 化 然 后 驱 动 再 对 返 回 的 input_dev 作 进 一 步 的 初 始 化, 函 数 set_bit(ev_key, serkbd_dev->evbit) 用 来 设 定 其 支 持 的 事 件 input_register_device(serkbd_dev), 把 设 备 注 册 进 input 子 系 统 input = input_allocate_device(); if(!input) return -ENOMEM; set_bit(ev_key, input->evbit); for(i = 0; i < MAX_BUTTON_CNT; i++) set_bit(s3c_keycode[i], input->keybit);

351 input->name = "s3c-button"; input->phys = "s3c-button/input0"; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; input->keycode = s3c_keycode; if(input_register_device(input)!= 0) { printk("s3c-button input register device fail!!\n"); input_free_device(input); return -ENODEV; } 由 于 按 键 驱 动 在 android 内 核 文 件 中 已 经 编 译 好, 源 码 存 放 的 路 径 为 /usr/local/src/s210x/x210_android-2.3/kernel/arch/arm/mach-s5pv210, 因 此 本 实 验 只 需 要 编 写 按 键 测 试 程 序 进 行 测 试 即 可 实 验 步 骤 1) 将 实 验 板 通 过 Min USB 连 接 上 电 脑, 将 范 例 程 序 KeyDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上 图 KeyDemo 效 果 图 2) 最 上 方 的 EditText 控 件 是 输 入 字 符 的 区 域 用 来 显 示 按 键 硬 件 编 码 信 息, 最 下 方 的 TextView 控 件 用 来 显 示 按 键 事 件 的 详 细 信 息, 包 括 按 键 动 作 按 键 代 码 重 复 次 数 硬 件 编 码 和 按 键 标 志

352 3) 按 下 VOL+ 按 键, 最 下 方 的 TextView 控 件 显 示 了 按 键 的 详 细 信 息, 按 键 硬 件 编 码 将 显 示 在 EditText 控 件 中, 如 图 所 示 : 图 VOL+ 按 键 详 细 信 息 4) 按 下 VOL- 按 键, 最 下 方 的 TextView 控 件 显 示 了 按 键 的 详 细 信 息, 按 键 硬 件 编 码 将 显 示 在 EditText 控 件 中, 如 图 所 示 : 图 VOL- 按 键 详 细 信 息 5) 按 下 CAM 按 键, 最 下 方 的 TextView 控 件 显 示 了 按 键 的 详 细 信 息, 按 键 硬 件 编 码 将 显 示 在 EditText 控 件 中, 如 图 所 示 :

353 图 CAM 按 键 详 细 信 息 16.2 存 储 设 备 移 植 -SD 卡 实 验 目 的 了 解 SD 卡 工 作 原 理 ; 了 解 linux 下 SD 卡 驱 动 的 设 计 ; 了 解 android 下 SD 卡 访 问 的 原 理 ; 掌 握 android 应 用 程 序 中 如 何 应 用 SD 卡 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 SD 卡 的 工 作 原 理 SD 卡 (Secure Digital Memory Card) 是 一 种 为 满 足 安 全 性 容 量 性 能 和 使 用 环 境 等 各 方 面 的 需 求 而 设 计 的 一 种 新 型 存 储 器 件,SD 卡 允 许 在 两 种 模 式 下 工 作 即 SD 模 式 和 SPI 模 式 如 图 所 示 SD 卡 内 部 结 构 和 引 脚 图

354 图 SD 卡 内 部 结 构 和 引 脚 其 主 要 引 脚 和 功 能 的 说 明 如 下 : CLK: 每 个 时 钟 周 期 传 输 一 个 命 令 或 数 据 位 频 率 可 在 0~25MHz 之 间 变 化 SD 卡 的 总 线 管 理 器 可 以 不 受 任 何 限 制 自 由 产 生 0~25MHz 的 频 率 CMD: 命 令 从 该 CMD 线 上 串 行 传 输 一 个 命 令 是 一 次 主 机 到 从 卡 操 作 的 开 始 命 令 可 以 以 单 机 寻 址 ( 寻 址 命 令 ) 或 呼 叫 所 有 卡 ( 广 播 命 令 ) 方 式 发 送 回 复 从 该 CMD 线 上 串 行 传 输 一 个 命 令 是 对 之 前 命 令 的 回 答 回 复 可 以 来 自 单 机 或 所 有 卡 DAT0~3: 数 据 可 以 从 卡 传 向 主 机 或 副 versa, 数 据 通 过 数 据 线 传 输 S210X 开 发 平 台 的 SD 卡 硬 件 原 理 图 如 下 图 所 示 :

355 图 SD 卡 内 部 结 构 和 引 脚 Linux 下 的 SD 卡 驱 动 设 计 在 Linux 系 统 中,SD 卡 驱 动 用 到 的 block_device_operations 结 构 已 经 定 义 struct block_device_operations { int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); long (*compat_ioctl) (struct file *, unsigned, unsigned long); int (*direct_access) (struct block_device *, sector_t, unsigned long *); int (*media_changed) (struct gendisk *); int (*revalidate_disk) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); struct module *owner; }; 内 核 启 动 时, 首 先 执 行 core/core.c 的 mmc_init, 注 册 mmc sd 总 线, 以 及 一 个 host class 设 备 接 着 执 行 card/block.c 中, 申 请 一 个 块 设 备 mmc 总 线 操 作 相 关 函 数, 由 于 mmc 卡 支 持 多 种 总 数 据 线, 如 SPI SDIO 8LineMMC, 而 不 同 的 总 线 的 操 作 控 制 方 式 不 尽 相 同, 所 以 通 过 此 结 构 与 相 应 的 总 线 回 调 函 数 相 关 联 总 线 操 作 结 构 如 下 struct mmc_bus_ops { void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);

356 void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card); void (*suspend)(struct mmc_host *); void (*resume)(struct mmc_host *); }; mmc 卡 的 总 线 操 作 core/mmc.c 定 义 如 下 static const struct mmc_bus_ops mmc_ops = {.remove = mmc_remove,.detect = mmc_detect,.sysfs_add = mmc_sysfs_add,.sysfs_remove = mmc_sysfs_remove,.suspend = mmc_suspend,.resume = mmc_resume, }; sd 卡 的 总 线 操 作 core/sd.c 定 义 如 下 static const struct mmc_bus_ops mmc_sd_ops = {.remove = mmc_sd_remove,.detect = mmc_sd_detect,.sysfs_add = mmc_sd_sysfs_add,.sysfs_remove = mmc_sd_sysfs_remove,.suspend = mmc_sd_suspend,.resume = mmc_sd_resume, }; sdio 的 总 线 操 作 core/sdio.c 定 义 如 下 static const struct mmc_bus_ops mmc_sdio_ops = {.remove = mmc_sdio_remove,.detect = mmc_sdio_detect, }; 驱 动 程 序 经 常 需 要 调 用 此 函 数 去 检 测 mmc 卡 的 状 态, 具 体 实 现 是 发 送 CMD13 命 令, 并 读 回 响 应, 如 果 响 应 错 误, 则 依 次 调 用.remove detach_bus 来 移 除 卡 及 释 放 总 线 kernel 启 动 时, 先 后 执 行 mmc_init() 及 mmc_blk_init(), 以 对 mmc 设 备 及 mmc 块 模 块 进 行 初 始 化 然 后 在 挂 载 mmc 设 备 驱 动 时, 执 行 驱 动 程 序 中 的 xx_mmc_probe(), 检 测 host 设 备 中 挂 载 的 sd 设 备 此 时 probe 函 数 会 创 建 一 个 host 设 备, 然 后 开 启 一 个 延 时 任 务 mmc_rescan() 驱 动 挂 载 成 功 后,mmc_rescan() 函 数 被 执 行, 然 后 对 卡 进 行 初 始 化 ( 步 骤 后 面 详 细 讲 述 ) 假 如 扫 描 到 总 线 上 挂 有 有 效 的 设 备, 就 调 用 相 对 应 的 函 数 把 设 备 装 到 系 统 中, mmc_attach_sdio() mmc_attach_sd() mmc_attach_mmc() 这 三 个 函 数 分 别 是 装 载 sdio 设 备,sd

357 卡 和 mmc 卡 的 在 sd 卡 中, 驱 动 循 环 发 送 ACMD41 CMD55 给 卡, 读 取 OCR 寄 存 器, 成 功 后, 依 次 发 送 CMD2( 读 CID) CMD3( 得 到 RCA) CMD9( 读 CSD) CMD7( 选 择 卡 ) 后 面 还 有 几 个 命 令 分 别 是 ACMD41&CMD51, 使 用 CMD6 切 换 一 些 功 能, 如 切 换 到 高 速 模 式 经 过 上 述 步 骤, 已 经 确 定 当 前 插 入 的 卡 是 一 张 有 效 可 识 别 的 存 储 卡 然 后 调 用 mmc_add_card() 把 存 储 卡 加 到 系 统 中 正 式 与 系 统 驱 动 连 接 在 一 起 SD 卡 设 备 加 到 系 统 中 后, 通 知 mmc 块 设 备 驱 动 块 设 备 驱 动 此 时 调 用 probe 函 数, 即 mmc_blk_probe() 函 数,mmc_blk_probe() 首 先 分 配 一 个 新 的 mmc_blk_data 结 构 变 量, 然 后 调 用 mmc_init_queue, 初 始 化 blk 队 列 然 后 建 立 一 个 线 程 mmc_queue_thread() 在 S210X 开 发 平 台 上 的 Linux 系 统 中 开 发 SD 卡 驱 动 首 先 要 在 平 台 设 备 中 注 册 struct platform_device s3c_device_hsmmc0 = {.name = "s3c-sdhci",.id = 0,.num_resources = ARRAY_SIZE(s3c_hsmmc_resource),.resource = s3c_hsmmc_resource,.dev = {.dma_mask = &s3c_device_hsmmc_dmamask,.coherent_dma_mask = 0xffffffffUL,.platform_data = &s3c_hsmmc0_def_platdata, }, }; void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; if (pd->max_width) set->max_width = pd->max_width; if (pd->host_caps) set->host_caps = pd->host_caps; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->cfg_ext_cd) set->cfg_ext_cd = pd->cfg_ext_cd; if (pd->ext_cd) set->ext_cd = pd->ext_cd;

358 if (pd->cfg_wp) set->cfg_wp = pd->cfg_wp; if (pd->get_ro) set->get_ro = pd->get_ro; } struct platform_device s3c_device_hsmmc1 = {.name = "s3c-sdhci",.id = 1,.num_resources = ARRAY_SIZE(s3c_hsmmc1_resource),.resource = s3c_hsmmc1_resource,.dev = {.dma_mask = &s3c_device_hsmmc1_dmamask,.coherent_dma_mask = 0xffffffffUL,.platform_data = &s3c_hsmmc1_def_platdata, }, }; void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; if (pd->max_width) set->max_width = pd->max_width; if (pd->host_caps) set->host_caps = pd->host_caps; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->cfg_ext_cd) set->cfg_ext_cd = pd->cfg_ext_cd; if (pd->ext_cd) set->ext_cd = pd->ext_cd; if (pd->cfg_wp) set->cfg_wp = pd->cfg_wp; if (pd->get_ro) set->get_ro = pd->get_ro; } struct platform_device s3c_device_hsmmc2 = {

359 .name = "s3c-sdhci",.id = 2,.num_resources = ARRAY_SIZE(s3c_hsmmc2_resource),.resource = s3c_hsmmc2_resource,.dev = {.dma_mask = &s3c_device_hsmmc2_dmamask,.coherent_dma_mask = 0xffffffffUL,.platform_data = &s3c_hsmmc2_def_platdata, }, }; void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; if (pd->max_width) set->max_width = pd->max_width; if (pd->host_caps) set->host_caps = pd->host_caps; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->cfg_ext_cd) set->cfg_ext_cd = pd->cfg_ext_cd; if (pd->ext_cd) set->ext_cd = pd->ext_cd; if (pd->cfg_wp) set->cfg_wp = pd->cfg_wp; if (pd->get_ro) set->get_ro = pd->get_ro; } static struct platform_device *smdkv210_devices[] initdata = {.. #ifdef CONFIG_S3C_DEV_HSMMC &s3c_device_hsmmc0, #endif #ifdef CONFIG_S3C_DEV_HSMMC1 &s3c_device_hsmmc1,

360 #endif #ifdef CONFIG_S3C_DEV_HSMMC2 &s3c_device_hsmmc2, #endif } 在 SD 卡 的 驱 动 程 序 中 要 注 册 SD 卡 的 平 台 驱 动, 并 实 现 其 probe 和 remove 函 数 static struct platform_driver s3cmci_driver = {.driver = {.name = "s3c-sdi",.owner = THIS_MODULE,.pm = s3cmci_pm_ops, },.id_table = s3cmci_driver_ids,.probe = s3cmci_probe,.remove = devexit_p(s3cmci_remove),.shutdown = s3cmci_shutdown, }; static int init s3cmci_init(void) { return platform_driver_register(&s3cmci_driver); } static void exit s3cmci_exit(void) { platform_driver_unregister(&s3cmci_driver); } 在 Linux 配 置 选 项 中 Device Drivers/MMC/SD/SDIO Card support 目 录 下 勾 选 上 对 SD 卡 的 支 持 图 在 Linux 内 核 中 配 置 SD 卡 驱 动

361 Android 下 SD 卡 的 访 问 原 理 在 Android 系 统 的 启 动 脚 本 init.rc 文 件 中 加 入 SD 卡 的 环 境 变 量 # setup the global environment export EXTERNAL_STORAGE /mnt/sdcard export EXTERNAL_STORAGE_SD /mnt/sdcard symlink /mnt/sdcard /sdcard 还 需 要 修 改 SD 卡 挂 载 的 配 置 ## vold configuration file for the emulator/sdk volume_sdcard { ## This is the direct uevent device path to the SD slot on the device media_path /devices/platform/s3c-sdhci.0/mmc_host/mmc0 } media_type mmc mount_point /sdcard ## ums_path /sys/devices/platform/s3c-usbgadget/gadget/lun0/file ums_path /devices/platform/s3c-usbgadget/gadget/lun0 在 Android 应 用 程 序 中 访 问 SDCard, 你 需 要 申 请 访 问 SDCard 的 权 限 在 Android 应 用 程 序 工 程 中 的 AndroidManifest.xml 中 加 入 访 问 SDCard 的 权 限 如 下 <!-- 在 SDCard 中 创 建 与 删 除 文 件 权 限 --> <uses-permission android:name="android.permission.mount_unmount_filesystems"/> <!-- 往 SDCard 写 入 数 据 权 限 --> <uses-permission android:name="android.permission.write_external_storage"/> 在 进 行 读 写 之 前, 应 该 先 判 断 该 手 机 环 境 是 否 具 备 SD 卡 Environment 用 于 得 到 手 机 环 境, 其 getexternalstoragestate() 方 法 用 于 获 取 手 机 外 部 存 储 设 备 (SD 卡 ) 的 状 态,false 为 不 具 备 SD 卡 使 用 环 境 // 判 断 手 机 是 否 存 在 SD 卡, 并 是 可 读 写 的 Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 然 后 可 以 写 入 文 件 到 SD 卡 中 public void savefiletosdcard(string filename, String content) throws Exception { Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); // File file = new File("/sdcard", filename); File file = Environment.getExternalStorageDirectory(); FileOutputStream fos = new FileOutputStream(file); fos.write(content.getbytes()); fos.close(); }

362 实 验 步 骤 查 看 和 配 置 SD 卡 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 给 开 发 平 台 上 电 启 动 Android, 运 行 应 用 程 序 ES 文 件 浏 览 器 浏 览 SD 卡 内 的 文 件 SD 卡 中 的 内 容 显 示 2) 卸 载 SD 卡 设 备, 建 议 不 要 热 插 拔 SD 卡, 拔 出 SD 卡 之 前, 在 Android 主 界 面 按 一 下 MENU, 弹 出 菜 单 栏 SD 卡 SD 卡 操 作 3) 依 次 单 击 选 择 设 置 -> 存 储 -> 卸 载 SD 卡, 状 态 栏 提 示 SD 卡 已 安 全 移 除 后 再 拔 出

363 SD 卡 卸 载 向 SD 卡 中 写 入 文 件 1) 将 范 例 程 序 SDcardFileDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上, 如 图 所 示 : 图 SDcardFileDemo 示 例 界 面 2) 单 击 生 成 随 机 数 按 钮, 随 机 数 显 示 在 下 方, 单 击 写 入 SD 卡 按 钮, 随 机 数 将 被 保 存 到 /sdcard/ 目 录 下 一 个 txt 文 件 内 图 写 入 SD 卡 界 面 3) 可 运 行 应 用 程 序 ES 文 件 浏 览 器 浏 览 SD 卡 内 被 写 入 的 txt 文 件, 如 图 所 示 :

364 图 应 用 程 序 写 入 到 SD 卡 的 txt 文 件 16.3 WIFI 设 备 移 植 实 验 目 的 了 解 WIFI 的 基 本 原 理 ; 了 解 linux 下 WIFI 驱 动 的 设 计 ; 了 解 android 下 WIFI 软 件 设 计 原 理 及 应 用 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 无 线 局 域 网 WIFI 简 介 Wi-Fi 是 一 种 可 以 将 个 人 电 脑 手 持 设 备 ( 如 PDA 手 机 ) 等 终 端 以 无 线 方 式 互 相 连 接 的 技 术 Wi-Fi 是 一 个 无 线 网 路 通 信 技 术 的 品 牌, 由 Wi-Fi 联 盟 (Wi-Fi Alliance) 所 持 有 目 的 是 改 善 基 于 IEEE 标 准 的 无 线 网 路 产 品 之 间 的 互 通 性 现 时 一 般 人 会 把 Wi-Fi 及 IEEE 混 为 一 谈 甚 至 把 Wi-Fi 等 同 于 无 线 网 际 网 路 WiFi(Wireless Fidelity) 使 用 了 IEEE 协 议 的 技 术, 目 前 在 智 能 手 机 中 使 用 WiFi 已 经 成

365 为 智 能 手 机 的 核 心 功 能 之 一 无 线 局 域 网 的 底 层 硬 件 通 常 是 WiFi 芯 片, 这 个 芯 片 通 常 提 供 了 集 成 化 的 WiFi 功 能 Wi-Fi 是 一 种 帮 助 用 户 访 问 电 子 邮 件 Web 和 流 式 媒 体 的 互 联 网 技 术 它 为 用 户 提 供 了 无 线 的 宽 带 互 联 网 访 问 同 时, 它 也 是 在 家 里 办 公 室 或 在 旅 途 中 上 网 的 快 速 便 捷 的 途 径 能 够 访 问 Wi-Fi 网 络 的 地 方 被 称 为 热 点 Wi-Fi 或 G 在 2.4Ghz 频 段 工 作, 所 支 持 的 速 度 最 高 达 54Mbps 另 外 还 有 两 种 空 间 的 协 议, 包 括 (a) 和 (b) 它 们 也 是 公 开 使 用 的, 但 G 在 世 界 上 最 为 常 用 Wi-Fi 热 点 是 通 过 在 互 联 网 连 接 上 安 装 访 问 点 来 创 建 的 这 个 访 问 点 将 无 线 信 号 通 过 短 程 进 行 传 输, 一 般 覆 盖 300 英 尺 当 一 台 支 持 Wi-Fi 的 设 备 ( 例 如 Pocket PC) 遇 到 一 个 热 点 时, 这 个 设 备 可 以 用 无 线 方 式 连 接 到 那 个 网 络 大 部 分 热 点 都 位 于 供 大 众 访 问 的 地 方, 例 如 机 场 咖 啡 店 旅 馆 书 店 以 及 校 园 等 等 许 多 家 庭 和 办 公 室 也 拥 有 Wi-Fi 网 络 虽 然 有 些 热 点 是 免 费 的, 但 是 大 部 分 稳 定 的 公 共 Wi-Fi 网 络 是 由 私 人 互 联 网 服 务 提 供 商 (ISP) 提 供 的, 因 此 会 在 用 户 连 接 到 互 联 网 时 收 取 一 定 费 用 Wi-Fi 也 是 无 线 局 域 网 联 盟 (WLANA) 的 一 个 商 标, 该 商 标 仅 保 障 使 用 该 商 标 的 商 品 互 相 之 间 可 以 合 作, 与 标 准 本 身 实 际 上 没 有 关 系 但 是 后 来 人 们 逐 渐 习 惯 用 WIFI 来 称 呼 b 协 议 它 的 最 大 优 点 就 是 传 输 速 度 较 高, 可 以 达 到 11Mbps, 另 外 它 的 有 效 距 离 也 很 长, 同 时 也 与 已 有 的 各 种 DSSS 设 备 兼 容 linux 中 WIFI 驱 动 设 计 Linux 内 核 方 面,WiFi 在 Linux 内 核 中 有 标 准 的 网 络 协 议, 各 个 硬 件 平 台 相 差 别 的 部 分 只 有 WiFi 芯 片 的 驱 动 程 序 这 些 驱 动 程 序 是 针 对 芯 片 级 别 的,Android 中 的 实 现 和 其 他 Linux 系 统 中 的 实 现 基 本 上 是 相 同 的 在 Linux 中,Wlan 设 备 驱 动 是 网 络 设 备, 使 用 网 络 接 口 Wlan 在 用 户 空 间 使 用 标 准 的 socket 接 口 进 行 控 制 WIFI 协 议 部 分 头 文 件 : include/net/wireless.h WIFI 协 议 部 分 源 文 件 : net/wireless/* WIFI 驱 动 程 序 部 分 : drivers/net/wireless/* 在 Linux 中 使 用 make menuconfig 配 置 编 译 选 项, 在 Networking support/wireless 目 录 下 勾 选 上 无 线 网 络 wifi 的 协 议

366 图 配 置 Linux 内 核 Android 下 WIFI 软 件 设 计 原 理 Android 系 统 中 WiFi 对 上 层 的 接 口 包 括 了 数 据 部 分 和 控 制 部 分, 数 据 部 分 就 是 一 个 通 常 的 网 络 设 备 ( 与 以 太 网 非 常 类 似 ), 控 制 部 分 主 要 用 于 接 入 点 操 作 和 安 全 验 证 等 下 图 为 Android 系 统 中 WiFi 架 构 框 图 图 Android 系 统 中 WiFi 架 构 框 图

367 在 软 件 层 面 上,Android 的 WiFi 系 统 包 括 Linux 内 核 中 的 驱 动 程 序 和 协 议, 本 地 部 分,Java 框 架 类 WiFi 向 Java 应 用 程 序 层 主 要 提 供 控 制 类 的 接 口 对 于 无 线 局 域 网 部 分, 由 于 实 现 相 对 标 准, 针 对 特 定 的 硬 件 平 台, 这 部 分 需 要 移 植 和 改 动 的 内 容 不 多 Android 用 户 空 间, 使 用 了 标 准 的 wpa_supplicant, 这 是 一 个 Linux 中 的 标 准 实 现 在 Android 中, 一 般 不 需 要 为 WiFi 增 加 单 独 的 硬 件 抽 象 层 代 码, 但 是 可 以 进 行 部 分 配 置 工 作 Wpa_supplicant 的 配 置 文 件 wpa_supplicant.conf wpa_supplicant 中 使 用 了 几 种 驱 动 作 为 插 件 来 使 用, 通 常 使 用 wext(linux wireless extension,linux 无 限 扩 展 ) 作 为 WiFi 的 标 准 实 现 连 接 AP 其 中, 开 启 WiFi 的 过 程 包 括 了 初 始 化, 加 载 驱 动, 运 行 wpa_supplicant 等 步 骤, 而 查 找 AP 和 连 接 AP 步 骤 则 是 通 过 发 送 命 令, 等 待 下 层 回 应 的 方 式 来 完 成 的 在 应 用 程 序 中 使 用 WiFi, 首 先 需 要 进 行 初 始 化, 在 SystemServer 启 动 的 时 候, 会 生 成 一 个 ConnectivityService 的 实 例 try { Slog.i(TAG, "Connectivity Service"); connectivity = ConnectivityService.getInstance(context); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); } catch (Throwable e) { Slog.e(TAG, "Failure starting Connectivity Service", e); } ConnectivityService 的 构 造 函 数 会 创 建 WifiService switch (mnetattributes[nettype].mradio) { case ConnectivityManager.TYPE_WIFI: if (DBG) Slog.v(TAG, "Starting Wifi Service."); WifiStateTracker wst = new WifiStateTracker(context, mhandler); WifiService wifiservice = new WifiService(context, wst); ServiceManager.addService(Context.WIFI_SERVICE, wifiservice); wifiservice.startwifi(); mnettrackers[connectivitymanager.type_wifi] = wst; wst.startmonitoring(); break; } WifiStateTracker 会 创 建 WifiMonitor 接 收 来 自 底 层 的 事 件,WifiService 和 WifiMonitor 是 整 个 模 块 的 核 心 WifiService 负 责 启 动 关 闭 wpa_supplicant 启 动 关 闭 WifiMonitor 监 视 线 程 和 把 命 令 下 发 给 wpa_supplicant, 而 WifiMonitor 则 负 责 从 wpa_supplicant 接 收 事 件 通 知 紧 接 着 连 接 AP, 使 能 WiFi,WirelessSettings 在 初 始 化 的 时 候 配 置 了 由 WifiEnabler 来 处 理 Wifi 按 钮

368 当 用 户 按 下 Wifi 按 钮 后,Android 会 调 用 WifiEnabler 的 onpreferencechange, 再 由 WifiEnabler 调 用 WifiManager 的 setwifienabled 接 口 函 数, 通 过 AIDL, 实 际 调 用 的 是 WifiService 的 setwifienabled 函 数,WifiService 接 着 向 自 身 发 送 一 条 MESSAGE_ENABLE_WIFI 消 息, 在 处 理 该 消 息 的 代 码 中 做 真 正 的 使 能 工 作 : 首 先 装 载 WIFI 内 核 模 块 ( 该 模 块 的 位 置 硬 编 码 为 /system/lib/modules/wlan.ko ), 然 后 启 动 wpa_supplicant ( 配 置 文 件 硬 编 码 为 /data/misc/wifi/wpa_supplicant.conf ), 再 通 过 WifiStateTracker 来 启 动 WifiMonitor 中 的 监 视 线 程 privatebooleansetwifienabledblocking(booleanenable){ finalinteventualwifistate=enable?wifi_state_enabled: WIFI_STATE_DISABLED; updatewifistate(enable?wifi_state_enabling:wifi_state_disabling); if(enable){ if(!wifinative.loaddriver()){ Log.e(TAG,"FailedtoloadWi-Fidriver."); updatewifistate(wifi_state_unknown); returnfalse; } if(!wifinative.startsupplicant()){ WifiNative.unloadDriver(); Log.e(TAG,"Failedtostartsupplicantdaemon."); updatewifistate(wifi_state_unknown); returnfalse; } mwifistatetracker.starteventloop(); } //Success! persistwifienabled(enable); updatewifistate(eventualwifistate); returntrue; } 当 使 能 成 功 后, 会 广 播 发 送 WIFI_STATE_CHANGED_ACTION 这 个 Intent 通 知 外 界 WIFI 已 经 成 功 使 能 了 WifiEnabler 创 建 的 时 候 就 会 向 Android 注 册 接 WIFI_STATE_CHANGED_ACTION, 因 此 它 会 收 到 该 Intent, 从 而 开 始 扫 描 privatevoidhandlewifistatechanged(intwifistate){ if(wifistate==wifi_state_enabled){ loadconfiguredaccesspoints(); attemptscan();

369 } 查 找 AP, 扫 描 的 入 口 函 数 是 WifiService 的 startscan, 它 其 实 也 就 是 往 wpa_supplicant 发 送 SCAN 命 令 staticjbooleanandroid_net_wifi_scancommand(jnienv*env,jobjectclazz) { jbooleanresult; //Ignoreanyerrorfromsettingthescanmode. //Thescanwillstillwork. (void)dobooleancommand("driverscan-active","ok"); result=dobooleancommand("scan","ok"); (void)dobooleancommand("driverscan-passive","ok"); returnresult; } 当 wpa_supplicant 处 理 完 SCAN 命 令 后, 它 会 向 控 制 通 道 发 送 事 件 通 知 扫 描 完 成, 从 而 wifi_wait_for_event 函 数 会 接 收 到 该 事 件, 由 此 WifiMonitor 中 的 MonitorThread 会 被 执 行 voidhandleevent(intevent,stringremainder){ casescan_results: mwifistatetracker.notifyscanresultsavailable(); break; WifiStateTracker 则 接 着 广 播 发 送 SCAN_RESULTS_AVAILABLE_ACTION 这 个 Intent caseevent_scan_results_available: mcontext.sendbroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); WifiLayer 注 册 了 接 收 SCAN_RESULTS_AVAILABLE_ACTION 这 个 Intent, 所 以 它 的 相 关 处 理 函 数 handlescanresultsavailable 会 被 调 用, 在 该 函 数 中, 先 会 去 拿 到 SCAN 的 结 果 ( 最 终 是 往 wpa_supplicant 发 送 SCAN_RESULT 命 令 并 读 取 返 回 值 来 实 现 的 ) List<ScanResult>list=mWifiManager.getScanResults(); 对 每 一 个 扫 描 返 回 的 AP,WifiLayer 会 调 用 WifiSettings 的 onaccesspointsetchanged 函 数, 从 而 最 终 把 该 AP 加 到 GUI 显 示 列 表 中 publicvoidonaccesspointsetchanged(accesspointstateap,booleanadded){ AccessPointPreferencepref=mAps.get(ap); if(added){ if(pref==null){ pref=newaccesspointpreference(this,ap); maps.put(ap,pref); }else{ pref.setenabled(true);

370 } mapcategory.addpreference(pref); } } 配 置 AP 参 数, 当 用 户 在 WifiSettings 界 面 上 选 择 了 一 个 AP 后, 会 显 示 配 置 AP 参 数 的 一 个 对 话 框 publicbooleanonpreferencetreeclick(preferencescreenpreferencescreen,preference preference){ if(preferenceinstanceofaccesspointpreference){ AccessPointStatestate=((AccessPointPreference) preference).getaccesspointstate(); showaccesspointdialog(state,accesspointdialog.mode_info); } } 连 接 AP, 当 用 户 在 AcessPointDialog 中 选 择 好 加 密 方 式 和 输 入 密 钥 之 后, 再 点 击 连 接 按 钮, Android 就 会 去 连 接 这 个 AP privatevoidhandleconnect(){ Stringpassword=getEnteredPassword(); if(!textutils.isempty(password)){ mstate.setpassword(password); } mwifilayer.connecttonetwork(mstate); } WifiLayer 会 先 检 测 这 个 AP 是 不 是 之 前 被 配 置 过, 这 个 是 通 过 向 wpa_supplicant 发 送 LIST_NETWORK 命 令 并 且 比 较 返 回 值 来 实 现 的 //NeedWifiConfigurationfortheAP WifiConfigurationconfig=findConfiguredNetwork(state); 如 果 wpa_supplicant 没 有 这 个 AP 的 配 置 信 息, 则 会 向 wpa_supplicant 发 送 ADD_NETWORK 命 令 来 添 加 该 AP if(config==null){ //Connectingforthefirsttime,needtocreateit config=addconfiguration(state, ADD_CONFIGURATION_ENABLE ADD_CONFIGURATION_SAVE); } ADD_NETWORK 命 令 会 返 回 一 个 ID,WifiLayer 再 用 这 个 返 回 的 ID 作 为 参 数 向 wpa_supplicant 发 送 ENABLE_NETWORK 命 令, 从 而 让 wpa_supplicant 去 连 接 该 AP //Makesurethatnetworkisenabled,anddisableothers

371 mreenableapsonnetworkstatechange=true; if(!mwifimanager.enablenetwork(state.networkid,true)){ Log.e(TAG,"CouldnotenablenetworkID"+state.networkId); error(r.string.error_connecting); returnfalse; } 配 置 IP 地 址, 当 wpa_supplicant 成 功 连 接 上 AP 之 后, 它 会 向 控 制 通 道 发 送 事 件 通 知 连 接 上 AP 了, 从 而 wifi_wait_for_event 函 数 会 接 收 到 该 事 件, 由 此 WifiMonitor 中 的 MonitorThread 会 被 执 行 voidhandleevent(intevent,stringremainder){ caseconnected: handlenetworkstatechange(networkinfo.detailedstate.connected, remainder); break; WifiMonitor 再 调 用 WifiStateTracker 的 notifystatechange,wifistatetracker 则 接 着 会 往 自 身 发 送 EVENT_DHCP_START 消 息 来 启 动 DHCP 去 获 取 IP 地 址 privatevoidhandleconnectedstate(){ setpolltimer(); mlastsignallevel=-1; if(!mhaveipaddress&&!mobtainingipaddress){ mobtainingipaddress=true; mdhcptarget.obtainmessage(event_dhcp_start).sendtotarget(); } } 然 后 再 广 播 发 送 NETWORK_STATE_CHANGED_ACTION 这 个 Intent caseevent_network_state_changed: if(result.state!=detailedstate.disconnected!mdisconnectpending){ intent=new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); intent.putextra(wifimanager.extra_network_info, mnetworkinfo); if(result.bssid!=null) intent.putextra(wifimanager.extra_bssid,result.bssid); mcontext.sendstickybroadcast(intent); } break; WifiLayer 注 册 了 接 收 NETWORK_STATE_CHANGED_ACTION 这 个 Intent, 所 以 它 的 相 关 处

372 理 函 数 handlenetworkstatechanged 会 被 调 用, 当 DHCP 拿 到 IP 地 址 之 后, 会 再 发 送 EVENT_DHCP_SUCCEEDED 消 息 privateclassdhcphandlerextendshandler{ publicvoidhandlemessage(messagemsg){ switch(msg.what){ caseevent_dhcp_start: if(networkutils.rundhcp(minterfacename,mdhcpinfo)){ event=event_dhcp_succeeded; } WifiLayer 处 理 EVENT_DHCP_SUCCEEDED 消 息, 会 再 次 广 播 发 送 NETWORK_STATE_CHANGED_ACTION 这 个 Intent, 这 次 带 上 完 整 的 IP 地 址 信 息 caseevent_dhcp_succeeded: mwifiinfo.setipaddress(mdhcpinfo.ipaddress); setdetailedstate(detailedstate.connected); intent=new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); intent.putextra(wifimanager.extra_network_info,mnetworkinfo); mcontext.sendstickybroadcast(intent); break; Android 的 wifi 适 配 器 会 加 载 无 线 网 卡 的 驱 动 rt3070sta.ko 并 通 过 socket 调 用 应 用 程 序 wpa_supplicant 建 立 wifi 连 接, 所 以 我 们 需 要 添 加 wpa_supplicant 的 配 置 文 件 wpa_supplicant.conf, 并 在 Android 启 动 脚 本 init.rc 文 件 中 中 添 加 WIFI 的 配 置 #Forwifi mkdir/data/misc/wpa_supplicant0771wifiwifi mkdir/data/misc/wifi/sockets0771wifiwifi chownwifiwifi/data/misc/wifi/sockets chmod0771/data/misc/wifi/sockets #Defineserviceforwifi servicewpa_supplicant/system/bin/wpa_supplicant-dwext-ira0-c/data/misc/wifi/wpa_supplicant.conf disabled oneshot 实 验 步 骤 系 统 WIFI 应 用 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 把 无 线 WIFI 模 块 (USB 接 口 ) 连 接 于

373 S210X 开 发 平 台 的 相 应 接 口 上 2) 给 开 发 平 台 上 电, 启 动 Android 系 统, 启 动 后 WIFI 模 块 的 灯 会 闪 动 3) 设 置 WIFI, 按 菜 单 -> 设 置 -> 无 线 和 网 络 -> 点 击 Wi-Fi 选 项, 并 顺 利 打 开 Wi-Fi 图 打 开 无 线 网 络 设 置 4) 点 击 设 置 Wi-Fi 设 置 菜 单 ( 确 保 你 的 附 近 有 可 上 网 的 无 线 网 络 ), 如 果 有 无 线 网 络, 会 自 动 搜 索 到, 并 自 动 获 取 电 脑 IP 等 ( 如 果 需 要 密 码 需 正 确 输 入 ) Android 下 WIFI 应 用 程 序 设 计 1) 将 范 例 程 序 WiFi 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上, 如 图 所 示 : 图 打 开 无 线 网 络 设 置 2) 单 击 打 开 WiFi 按 钮 和 关 闭 WiFi 按 钮 可 以 实 现 对 网 卡 的 开 与 关, 单 击 查 看 WiFi 状 态 按 钮, 可 以 查 看 网 卡 此 时 的 状 态 如 图 所 示 :

374 图 WiFi 的 开 与 关 3) 单 击 扫 描 网 络 按 钮 可 以 对 当 前 网 络 进 行 扫 描, 单 击 扫 描 结 果 按 钮 可 以 查 看 当 前 网 络 如 图 所 示 : 图 当 前 可 用 网 络 4) 单 击 连 接 指 定 网 络 按 钮, 进 入 WiFi 设 置 页 面 可 以 进 行 指 定 网 络 连 接, 单 击 断 开 指 定 网 络 按 钮 连 接 的 指 定 网 络 将 被 断 开, 单 击 网 络 连 接 状 态 按 钮 可 查 看 当 前 WiFi 指 定 网 络 连 接 状 态 如 图 所 示 : 图 连 接 指 定 网 络 及 查 看 其 状 态

375 16.4 GPS 设 备 移 植 实 验 目 的 了 解 GPS 的 基 本 概 念 ; 了 解 linux 下 GPS 驱 动 的 设 计 ; 了 解 GPS 硬 件 抽 象 层 开 发 ; 掌 握 android 下 GPS 软 件 设 计 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 全 球 定 位 系 统 GPS 简 介 GPS 是 英 文 GlobalPositioningSystem( 全 球 定 位 系 统 ) 的 简 称, 而 其 中 文 简 称 为 球 位 系 GPS 是 20 世 纪 70 年 代 由 美 国 陆 海 空 三 军 联 合 研 制 的 新 一 代 空 间 卫 星 导 航 定 位 系 统 其 主 要 目 的 是 为 陆 海 空 三 大 领 域 提 供 实 时 全 天 候 和 全 球 性 的 导 航 服 务, 并 用 于 情 报 收 集 核 爆 监 测 和 应 急 通 讯 等 一 些 军 事 目 的, 是 美 国 独 霸 全 球 战 略 的 重 要 组 成 经 过 20 余 年 的 研 究 实 验, 耗 资 300 亿 美 元, 到 1994 年 3 月, 全 球 覆 盖 率 高 达 98% 的 24 颗 GPS 卫 星 星 座 己 布 设 完 成 在 机 械 领 域 GPS 则 有 另 外 一 种 含 义 : 产 品 几 何 技 术 规 范 (GeometricalProductSpecifications)- 简 称 GPS GPS 的 空 间 部 分 是 由 24 颗 工 作 卫 星 组 成, 它 位 于 距 地 表 20200km 的 上 空, 均 匀 分 布 在 6 个 轨 道 面 上 ( 每 个 轨 道 面 4 颗 ), 轨 道 倾 角 为 55 此 外, 还 有 3 颗 有 源 备 份 卫 星 在 轨 运 行 卫 星 的 分 布 使 得 在 全 球 任 何 地 方 任 何 时 间 都 可 观 测 到 4 颗 以 上 的 卫 星, 并 能 在 卫 星 中 预 存 的 导 航 信 息 GPS 的 卫 星 因 为 大 气 摩 擦 等 问 题, 随 着 时 间 的 推 移, 导 航 精 度 会 逐 渐 降 低 地 面 控 制 系 统 由 监 测 站 (MonitorStation) 主 控 制 站 (MasterMonitorStation) 地 面 天 线 (GroundAntenna) 所 组 成, 主 控 制 站 位 于 美 国 科 罗 拉 多 州 春 田 市 (ColoradoSpring) 地 面 控 制 站 负 责 收 集 由 卫 星 传 回 之 讯 息, 并 计 算 卫 星 星 历 相 对 距 离, 大 气 校 正 等 数 据 用 户 设 备 部 分 即 GPS 信 号 接 收 机 其 主 要 功 能 是 能 够 捕 获 到 按 一 定 卫 星 截 止 角 所 选 择 的 待 测 卫 星, 并 跟 踪 这 些 卫 星 的 运 行 当 接 收 机 捕 获 到 跟 踪 的 卫 星 信 号 后, 就 可 测 量 出 接 收 天 线 至 卫 星 的 伪 距 离 和 距 离 的 变 化 率, 解 调 出 卫 星 轨 道 参 数 等 数 据 根 据 这 些 数 据, 接 收 机 中 的 微 处 理 计 算 机 就 可 按

376 定 位 解 算 方 法 进 行 定 位 计 算, 计 算 出 用 户 所 在 地 理 位 置 的 经 纬 度 高 度 速 度 时 间 等 信 息 接 收 机 硬 件 和 机 内 软 件 以 及 GPS 数 据 的 后 处 理 软 件 包 构 成 完 整 的 GPS 用 户 设 备 GPS 接 收 机 的 结 构 分 为 天 线 单 元 和 接 收 单 元 两 部 分 接 收 机 一 般 采 用 机 内 和 机 外 两 种 直 流 电 源 设 置 机 内 电 源 的 目 的 在 于 更 换 外 电 源 时 不 中 断 连 续 观 测 在 用 机 外 电 源 时 机 内 电 池 自 动 充 电 关 机 后, 机 内 电 池 为 RAM 存 储 器 供 电, 以 防 止 数 据 丢 失 目 前 各 种 类 型 的 接 受 机 体 积 越 来 越 小, 重 量 越 来 越 轻, 便 于 野 外 观 测 使 用 其 次 则 为 使 用 者 接 收 器, 现 有 单 频 与 双 频 两 种, 但 由 于 价 格 因 素, 一 般 使 用 者 所 购 买 的 多 为 单 频 接 收 器 Linux 下 GPS 驱 动 设 计 嵌 入 式 Linux 平 台 下 的 GPS 数 据 采 集 涉 及 到 Linux 串 口 编 程 技 术, 因 此 首 先 介 绍 Linux 串 口 编 程 的 相 关 知 识, 再 给 出 一 个 简 单 的 代 码 段, 实 现 GPS 定 位 信 息 的 获 取 在 Linux 操 作 系 统 中, 所 有 的 设 备 都 是 被 当 作 文 件 来 进 行 操 作 的, 所 有 的 设 备 以 设 备 文 件 的 形 式 存 储 在 目 录 /dev/ 下, 串 口 的 设 备 文 件 为 /dev/ttys*, 其 中,ttyS0 为 串 口 一,ttyS1 为 串 口 二, 以 此 类 推 Linux 下 定 义 了 一 个 查 询 和 操 纵 终 端 的 标 准 接 口, 该 接 口 被 称 为 termios, 在 系 统 头 文 件 <termios.h> 中 定 义. 它 包 括 一 个 数 据 结 构 和 一 系 列 操 纵 这 些 数 据 结 构 的 函 数 组 成. 有 关 串 口 的 所 有 参 数 配 置 都 保 存 在 接 口 termios 的 结 构 structtermios 中, 该 结 构 定 义 如 下 struettermios { unsignedshortc_iflag;/* 输 入 模 式 标 志 */ unsignedshortc_oflag;/* 输 出 模 式 标 志 */ unsignedshortc_cflag;/* 控 制 模 式 标 志 */ unsignedshortc_lflag;/* 本 地 模 式 标 志 */ unsignedcharc_line;/* 控 制 协 议 */ unsignedcharc_cc[nccs];/* 控 制 字 符 */} 其 中 的 c_flag 成 员 是 用 来 控 制 输 入 处 理 选 项 的, 它 将 影 响 到 终 端 驱 动 程 序 在 把 输 入 发 送 给 程 序 前 是 否 对 其 进 行 处 理, 及 怎 样 对 其 进 行 处 理 c_oflag 成 员 是 用 来 控 制 输 出 数 据 的 处 理, 并 决 定 在 发 送 输 出 数 据 到 显 示 屏 和 其 他 输 出 设 备 之 前, 终 端 驱 动 程 序 是 否 以 及 如 何 来 处 理 它 们 c_oflag 用 于 存 放 各 种 决 定 终 端 设 备 硬 件 特 性 的 控 制 标 志 存 放 在 c_lflag 中 的 本 地 模 式 标 志 用 来 操 纵 这 样 的 一 些 终 端 特 性, 比 如 是 否 将 输 入 字 符 显 示 到 显 示 屏 上 c_cc 包 含 了 特 殊 字 符 序 列 的 值, 比 如 ^( 退 出 ) 和 ^H( 删 除 ), 以 及 它 们 所 代 表 的 操 作 除 了 上 面 的 这 个 包 含 串 口 参 数 配 置 的 数 据 结 构 之 外,termios 中 还 包 含 许 多 控 制 串 口 特 性 的 函 数 其 中 基 本 的 函 数 如 :tcgetattr() 和 tcsetattr() tcgetattr() 用 来 初 始 化 一 个 termios 数 据 结 构, 之 后 可 使 用 其 它 的 函 数 来 操 纵 由 tcgetattr() 返 回 的 数 据 结 构 完 成 这 些 操 作 后, 使 用 tcsetattr() 来 更 新 串 口 的 设 置 其 它 对 串 口 的 打 开 关 闭 读 取 功 能 与 其 它 的 文 件 操 作 一 致, 使 用 open() close() read() 函

377 数 完 成 在 采 集 GPS 数 据 的 过 程 中, 需 对 所 读 取 的 数 据 进 行 鉴 别 区 分, 只 选 取 其 中 有 用 的 信 息 进 行 处 理 而 忽 略 其 余 的 信 息, 这 需 要 根 据 NMEA0183 协 议 中 规 定 的 语 句 格 式 来 进 行 筛 选 GPS 硬 件 设 备 的 驱 动 程 序 通 常 是 串 口 驱 动 程 序, 在 Linux 系 统 的 用 户 空 间 中 表 示 为 tty 设 备 在 板 级 文 件 中 添 加 串 口 驱 动 : staticstructs3c2410_uartcfgsmdkv210_uartcfgs[] initdata={ [0]={.hwport =0,.flags =0,.ucon =S5PV210_UCON_DEFAULT,.ulcon =S5PV210_ULCON_DEFAULT,.ufcon =S5PV210_UFCON_DEFAULT, }, [1]={.hwport =1,.flags =0,.ucon =S5PV210_UCON_DEFAULT,.ulcon =S5PV210_ULCON_DEFAULT,.ufcon =S5PV210_UFCON_DEFAULT, }, [2]={.hwport =2,.flags =0,.ucon =S5PV210_UCON_DEFAULT,.ulcon =S5PV210_ULCON_DEFAULT,.ufcon =S5PV210_UFCON_DEFAULT, }, [3]={.hwport =3,.flags =0,.ucon =S5PV210_UCON_DEFAULT,.ulcon =S5PV210_ULCON_DEFAULT,.ufcon =S5PV210_UFCON_DEFAULT, }, }; staticvoid initsmdkv210_map_io(void) { s5p_init_io(null,0,s5p_va_chipid);

378 s3c24xx_init_clocks( ); s3c24xx_init_uarts(smdkv210_uartcfgs,array_size(smdkv210_uartcfgs)); s5pv210_reserve_bootmem(); } GPS 硬 件 抽 象 层 开 发 针 对 GPS 的 硬 件 抽 象 层, Android 系 统 提 供 了 gps.cpp 的 标 准 实 现 sgpsinterface =gps_get_interface(); 我 们 只 需 要 实 现 gps_get_interface, 返 回 定 义 的 GpsInterface 接 口 即 可 Android 给 出 了 模 拟 器 GPS 的 参 考 实 现 gps.c, 基 本 结 构 可 以 重 新 使 用 const GpsInterface* gps get_gps_interface(struct gps_device_t* dev) { return gps_get_hardware_interface(); } static const GpsInterface freerunnergpsinterface = { sizeof(gpsinterface), freerunner_gps_init, freerunner_gps_start, freerunner_gps_stop, freerunner_gps_cleanup, freerunner_gps_inject_time, 0, //inject_location freerunner_gps_delete_aiding_data, freerunner_gps_set_position_mode, freerunner_gps_get_extension, }; 在 Android 启 动 脚 本 里 配 置 GPS 用 到 的 串 口 setpropro.kernel.android.gps s3c2410_serial1 Android 下 GPS 软 件 设 计 原 理 要 实 用 Adnroid 平 台 的 GPS 设 备, 首 先 需 要 添 加 上 权 限, 所 以 需 要 添 加 如 下 权 限 <uses-permissionandroid:name="android.permission.access_fine_location"></uses-permission> 如 果 开 启 正 常, 则 会 直 接 进 入 到 显 示 页 面, 如 果 开 启 不 正 常, 则 会 进 行 到 GPS 设 置 页 面 privatevoidgetlocation(){ // 获 取 位 置 管 理 服 务 LocationManagerlocationManager; StringserviceName=Context.LOCATION_SERVICE; locationmanager=(locationmanager)this.getsystemservice(servicename); // 查 找 到 服 务 信 息 Criteriacriteria=newCriteria();

379 criteria.setaccuracy(criteria.accuracy_fine);// 高 精 度 criteria.setaltituderequired(false); criteria.setbearingrequired(false); criteria.setcostallowed(true); criteria.setpowerrequirement(criteria.power_low);// 低 功 耗 Stringprovider=locationManager.getBestProvider(criteria,true);// 获 取 GPS 信 息 Locationlocation=locationManager.getLastKnownLocation(provider);// 通 过 GPS 获 取 位 置 updatetonewlocation(location);// 设 置 监 听 器, 自 动 更 新 的 最 小 时 间 为 间 隔 N 秒 (1 秒 为 1*1000, 这 样 写 主 要 为 了 方 便 ) 或 最 小 位 移 变 化 超 过 N 米 locationmanager.requestlocationupdates(provider,100*1000,500, locationlistener); } 用 下 面 的 方 法 进 行 显 示 : privatevoidupdatetonewlocation(locationlocation){ TextViewtv1; tv1=(textview)this.findviewbyid(r.id.tv1); if(location!=null){ doublelatitude=location.getlatitude(); doublelongitude=location.getlongitude(); tv1.settext(" 维 度 :"+latitude+" 经 度 "+longitude); }else{ tv1.settext(" 无 法 获 取 地 理 信 息 "); } } 这 样 子 就 能 获 取 到 当 前 使 用 者 所 在 的 地 理 位 置 了 实 验 步 骤 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 把 GPS 卫 星 定 位 模 块 连 接 于 S210X 开 发 平 台 的 相 应 接 口 上,GPS 天 线 连 接 好, 天 线 的 另 一 头 放 窗 外 2) 给 开 发 平 台 上 电 启 动 Android 系 统 启 动 后 指 示 灯 GPS_RUN 会 闪 动, 电 源 指 示 灯 会 常 亮 3) 设 置 GPS, 按 菜 单 -> 设 置 -> 位 置 和 安 全 -> 点 击 使 用 GPS 卫 星 选 项, 并 顺 利 打 开 GPS 如 图 所 示 :

380 图 打 开 设 置 选 择 位 置 和 安 全 图 选 中 使 用 GPS 卫 星 4) 将 范 例 程 序 GPSDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 显 示 当 前 位 置 信 息

381 16.5 蓝 牙 设 备 移 植 实 验 目 的 了 解 蓝 牙 的 基 本 知 识 ; 了 解 linux 下 蓝 牙 驱 动 的 设 计 ; 掌 握 android 下 蓝 牙 应 用 程 序 的 开 发 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 蓝 牙 简 介 蓝 牙, 是 一 种 支 持 设 备 短 距 离 通 信 ( 一 般 10m 内 ) 的 无 线 电 技 术 能 在 包 括 移 动 电 话 PDA 无 线 耳 机 笔 记 本 电 脑 相 关 外 设 等 众 多 设 备 之 间 进 行 无 线 信 息 交 换 利 用 蓝 牙 技 术, 能 够 有 效 地 简 化 移 动 通 信 终 端 设 备 之 间 的 通 信, 也 能 够 成 功 地 简 化 设 备 与 因 特 网 Internet 之 间 的 通 信, 从 而 数 据 传 输 变 得 更 加 迅 速 高 效, 为 无 线 通 信 拓 宽 道 路 蓝 牙 采 用 分 散 式 网 络 结 构 以 及 快 跳 频 和 短 包 技 术, 支 持 点 对 点 及 点 对 多 点 通 信, 工 作 在 全 球 通 用 的 2.4GHzISM( 即 工 业 科 学 医 学 ) 频 段 其 数 据 速 率 为 1Mbps 采 用 时 分 双 工 传 输 方 案 实 现 全 双 工 传 输 蓝 牙, 对 于 手 机 乃 至 整 个 IT 业 而 言 已 经 不 仅 仅 是 一 项 简 单 的 技 术, 而 是 一 种 概 念 当 蓝 牙 联 盟 信 誓 旦 旦 地 对 未 来 前 景 作 着 美 好 的 憧 憬 时, 整 个 业 界 都 为 之 震 动 抛 开 传 统 连 线 的 束 缚, 彻 底 地 享 受 无 拘 无 束 的 乐 趣, 蓝 牙 给 予 我 们 的 承 诺 足 以 让 人 精 神 振 奋 蓝 牙 技 术 是 一 种 无 线 数 据 与 语 音 通 信 的 开 放 性 全 球 规 范, 它 以 低 成 本 的 近 距 离 无 线 连 接 为 基 础, 为 固 定 与 移 动 设 备 通 信 环 境 建 立 一 个 特 别 连 接 其 程 序 写 在 一 个 9x9mm 的 微 芯 片 中 例 如, 如 果 把 蓝 牙 技 术 引 入 到 移 动 电 话 和 膝 上 型 电 脑 中, 就 可 以 去 掉 移 动 电 话 与 膝 上 型 电 脑 之 间 的 令 人 讨 厌 的 连 接 电 缆 而 通 过 无 线 使 其 建 立 通 信 打 印 机 PDA 桌 上 型 电 脑 传 真 机 键 盘 游 戏 操 纵 杆 以 及 所 有 其 它 的 数 字 设 备 都 可 以 成 为 蓝 牙 系 统 的 一 部 分 除 此 之 外, 蓝 牙 无 线 技 术 还 为 已 存 在 的 数 字 网 络 和 外 设 提 供 通 用 接 口 以 组 建 一 个 远 离 固 定 网 络 的 个 人 特 别 连 接 设 备 群 蓝 牙 工 作 在 全 球 通 用 的 2.4GHzISM( 即 工 业 科 学 医 学 ) 频 段 蓝 牙 的 数 据 速 率 为 1Mb/s 时 分 双 工 传 输 方 案 被 用 来 实 现 全 双 工 传 输 使 用 IEEE 协 议

382 ISM 频 带 是 对 所 有 无 线 电 系 统 都 开 放 的 频 带, 因 此 使 用 其 中 的 某 个 频 段 都 会 遇 到 不 可 预 测 的 干 扰 源 例 如 某 些 家 电 无 绳 电 话 汽 车 房 开 门 器 微 波 炉 等 等, 都 可 能 是 干 扰 为 此, 蓝 牙 特 别 设 计 了 快 速 确 认 和 跳 频 方 案 以 确 保 链 路 稳 定 跳 频 技 术 是 把 频 带 分 成 若 干 个 跳 频 信 道 (hopchannel), 在 一 次 连 接 中, 无 线 电 收 发 器 按 一 定 的 码 序 列 ( 即 一 定 的 规 律, 技 术 上 叫 做 伪 随 机 码, 就 是 假 的 随 机 码 ) 不 断 地 从 一 个 信 道 跳 到 另 一 个 信 道, 只 有 收 发 双 方 是 按 这 个 规 律 进 行 通 信 的, 而 其 他 的 干 扰 不 可 能 按 同 样 的 规 律 进 行 干 扰 ; 跳 频 的 瞬 时 带 宽 是 很 窄 的, 但 通 过 扩 展 频 谱 技 术 使 这 个 窄 带 宽 成 百 倍 地 扩 展 成 宽 频 带, 使 干 扰 可 能 的 影 响 变 成 很 小 与 其 它 工 作 在 相 同 频 段 的 系 统 相 比, 蓝 牙 跳 频 更 快, 数 据 包 更 短, 这 使 蓝 牙 比 其 它 系 统 都 更 稳 定 FEC(ForwardErrorCorrection, 前 向 纠 错 ) 的 使 用 抑 制 了 长 距 离 链 路 的 随 机 噪 音 应 用 了 二 进 制 调 频 (FM) 技 术 的 跳 频 收 发 器 被 用 来 抑 制 干 扰 和 防 止 衰 落 蓝 牙 基 带 协 议 是 电 路 交 换 与 分 组 交 换 的 结 合 在 被 保 留 的 时 隙 中 可 以 传 输 同 步 数 据 包, 每 个 数 据 包 以 不 同 的 频 率 发 送 一 个 数 据 包 名 义 上 占 用 一 个 时 隙, 但 实 际 上 可 以 被 扩 展 到 占 用 5 个 时 隙 蓝 牙 可 以 支 持 异 步 数 据 信 道 多 达 3 个 的 同 时 进 行 的 同 步 话 音 信 道, 还 可 以 用 一 个 信 道 同 时 传 送 异 步 数 据 和 同 步 话 音 每 个 话 音 信 道 支 持 64kb/s 同 步 话 音 链 路 异 步 信 道 可 以 支 持 一 端 最 大 速 率 为 721kb/s 而 另 一 端 速 率 为 57.6kb/s 的 不 对 称 连 接, 也 可 以 支 持 43.2kb/s 的 对 称 连 接 Linux 下 蓝 牙 驱 动 设 计 在 Linux 中, 蓝 牙 系 统 的 底 层 硬 件 是 蓝 牙 硬 件, 通 常 可 以 使 用 UART,SDIO 或 者 USB 接 口 作 为 连 接 在 Linux 中, 蓝 牙 设 备 驱 动 是 网 络 设 备, 使 用 网 络 接 口 蓝 牙 设 备 的 网 络 协 议 : 协 议 族 :AF_BLUETOOTH(31) 蓝 牙 协 议 部 分 头 文 件 : include/net/bluetooth/hci_core.h include/net/bluetooth/bluetooth.h 蓝 牙 协 议 源 代 码 文 件 : net/bluetooth/* 蓝 牙 驱 动 程 序 部 分 的 文 件 : drivers/bluetooth/* net/hci_core.c HCI 在 主 机 端 的 驱 动 主 要 是 为 上 层 提 供 一 个 统 一 的 接 口, 让 上 层 协 议 不 依 赖 于 具 体 硬 件 的 实 现 HCI 在 硬 件 中 的 固 件 与 HCI 在 主 机 端 的 驱 动 通 信 方 式 有 多 种, 比 如 像 UART USB 和 PCCard 等 等 hci_core.c 相 当 于 一 个 框 架, 用 于 把 各 种 具 体 通 信 方 式 结 合 起 来, 并 提 供 一 些 公 共 函 数 的 实 现 hci_cmd_task 是 负 责 发 送 CMD 的 任 务, 它 从 hdev->cmd_q 队 列 中 取 CMD, 然 后 调 用 hci_send_frame 把 CMD 发 送 出 去,hci_send_frame 又 会 调 用 实 际 的 HCI 驱 动 的 send 函 数 发 送 数

383 据 hci_rx_task 是 负 责 接 收 数 据 的 任 务, 它 从 hdev->rx_q 队 列 中 取 数 据, 然 后 根 据 数 据 的 类 型 调 用 上 层 函 数 处 理 数 据 包 有 三 种 类 型 : HCI_EVENT_PKT: 用 于 处 理 一 些 通 信 事 件, 比 如 连 接 建 立, 连 接 断 开, 认 证 和 加 密 等 事 件, 这 些 事 件 控 制 协 议 状 态 的 改 变 HCI_ACLDATA_PKT: 异 步 非 连 接 的 数 据 包, 通 过 hci_acldata_packet 提 交 给 上 层 的 L2CAP 协 议 处 理 (hci_proto[hci_proto_l2cap]) HCI_SCODATA_PKT: 同 步 面 向 连 接 的 数 据 包, 通 过 hci_scodata_packet 提 供 给 上 层 的 SCO 协 议 处 理 (hci_proto[hci_proto_sco]) hci_tx_task 是 负 责 发 送 数 据 的 任 务, 发 送 所 有 connection 中 的 ACL 和 SCO 数 据, 以 及 hdev->raw_q 中 的 数 据 包 HCI 为 上 层 提 供 的 接 口 主 要 有 : hci_send_sco: 发 送 SCO 数 据 包, 把 要 发 送 的 数 据 包 放 入 connection 的 发 送 队 列 中, 然 后 调 度 发 送 任 务 去 发 送 hci_send_acl: 发 送 ACL 数 据 包, 把 要 发 送 的 数 据 包 放 入 connection 的 发 送 队 列 中, 然 后 调 度 发 送 任 务 去 发 送 hci_send_cmd: 发 送 命 令 数 据, 把 要 发 送 的 数 据 包 放 入 hdev->cmd_q 队 列 中, 然 后 调 度 命 令 发 送 任 务 去 发 送 hci_register_proto/hci_unregister_proto: 注 册 / 注 销 上 层 协 议,HCI 会 把 接 收 到 的 数 据 转 发 给 这 些 上 层 协 议 hci_register_dev/hci_unregister_dev: 注 册 / 注 销 设 备,HCI 会 把 要 发 送 的 数 据 通 过 这 些 设 备 发 送 出 去 其 它 一 些 公 共 函 数 : net/hci_conn.c: 提 供 了 一 些 连 接 管 理, 论 证 和 加 密 的 函 数 net/hci_event.c: 事 件 处 理 函 数, 负 责 状 态 机 的 维 护, 这 些 事 件 通 常 会 使 连 接 从 一 个 状 态 转 换 另 一 个 状 态 hci_si_event: 用 于 发 送 事 件 hci_event_packet: 用 于 处 理 底 层 上 报 的 事 件, 从 hci_rx_task 处 调 用 过 来 net/hci_sock.c: 给 上 层 提 供 一 个 socket 接 口, 应 用 程 序 可 以 通 过 socket 的 方 式 来 访 问 HCI hci_sock_init: 中 注 册 了 BTPROTO_HCI 类 型 family hci_sock_create: 创 建 sock 的 函 数, 它 的 sock 的 ops 指 向 hci_sock_ops hci_sock_setsockopt/hci_sock_getsockopt: 设 置 / 获 取 sock 的 一 些 选 项 hci_sock_sendmsg: 发 送 消 息, 根 据 消 息 的 类 型 把 消 息 放 到 适 当 的 队 列 中

384 hci_sock_recvmsg: 接 收 消 息, 从 接 收 队 列 中 取 消 息 hci_sock_recvmsg:ioctl 函 数 net/hci_sysfs.c: 提 供 一 些 sysfs 文 件 系 统 接 口 net/l2cap.c:l2cap 是 HCI 之 上 的 协 议, 提 供 诸 如 QoS, 分 组, 多 路 复 用, 分 段 和 组 装 之 类 的 功 能 通 过 bt_sock_register 为 上 层 提 供 一 个 sock 接 口 : l2cap_sock_create: 创 建 sock 的 函 数, 它 的 sock 的 ops 指 向 l2cap_sock_ops l2cap_sock_setsockopt/l2cap_sock_getsockopt: 设 置 / 获 取 sock 的 一 些 选 项 l2cap_sock_sendmsg: 发 送 消 息, 通 过 HCI 提 供 hci_send_acl 函 数 把 消 息 传 递 给 下 层 的 设 备 bt_sock_recvmsg: 接 收 消 息, 从 接 收 队 列 中 取 消 息 通 过 hci_register_proto 向 其 下 的 HCI 注 册 协 议 : l2cap_connect_ind: 处 理 连 接 请 求 l2cap_connect_cfm: 确 认 连 接 l2cap_disconn: 处 理 断 开 请 求 l2cap_auth_cfm: 认 证 确 认 l2cap_encrypt_cfm: 加 密 确 认 l2cap_recv_acldata: 处 理 来 自 HCI 的 数 据 net/sco.c:sco 也 是 运 行 在 HCI 之 上 的 协 议, 它 是 面 向 连 接 的 可 靠 的 传 输 方 式, 主 要 用 于 声 音 数 据 传 输 通 过 bt_sock_register 为 上 层 提 供 一 个 sock 接 口 : sco_sock_create: 创 建 sock 的 函 数, 它 的 sock 的 ops 指 向 sco_sock_ops sco_sock_setsockopt/sco_sock_getsockopt 设 置 / 获 取 sock 的 一 些 选 项 sco_sock_sendmsg: 发 送 消 息, 通 过 HCI 提 供 sco_send_frame 函 数 把 消 息 传 递 给 下 层 的 设 备 bt_sock_recvmsg: 接 收 消 息, 从 接 收 队 列 中 取 消 息 通 过 hci_register_proto 向 其 下 的 HCI 注 册 协 议 : sco_connect_ind: 处 理 连 接 请 求 sco_connect_cfm: 确 认 连 接 sco_disconn_ind: 处 理 断 开 请 求 sco_recv_scodata: 处 理 来 自 HCI 数 据 rfcomm/* rfcomm 是 基 于 l2cap 之 上 的 协 议, 它 在 蓝 牙 协 议 之 上 封 装 传 统 的 RS232 串 口 drivers/bluetooth

385 前 面 我 们 介 绍 的 都 是 HCI 及 其 上 层 的 协 议,HCI 下 层 的 实 现 就 是 HCI 驱 动 程 序, 这 些 驱 动 程 序 用 于 与 蓝 牙 硬 件 通 信, 通 信 的 方 式 常 见 的 有 USB,UART 和 PCcard 等 几 种 这 里 我 们 看 看 USB 的 方 式 : drivers/bluetooth/hci_usb.c hci_usb_probe: 调 用 hci_register_dev 向 前 面 说 的 hci_core 注 册 HCI 设 备 hci_usb_send_frame : 用 于 提 供 给 HCI 去 发 送 数 据 包 它 把 数 据 包 放 到 传 输 队 列 transmit_q(husb,bt_cb(skb)->pkt_type) 之 中, 然 后 调 用 hci_usb_tx_process 去 传 输 数 据 hci_usb_tx_process : 根 据 数 据 的 类 型 去 调 用 hci_usb_send_ctrl /hci_usb_send_isoc /hci_usb_send_bulk 把 数 据 通 过 USB 发 送 给 硬 件 在 Linux 内 核 配 置 中 Networkingsupport/Bluetoothsubsystemsupport 的 目 录 下 添 加 蓝 牙 协 议 栈 的 支 持 图 添 加 蓝 牙 协 议 栈 蓝 牙 的 驱 动 部 分 包 含 针 对 硬 件 接 口 的 USB,SDIO 或 UART 驱 动,S210X 开 发 平 台 的 蓝 牙 使 用 的 是 USB 接 口, 所 以 需 要 在 Linux 内 核 配 置 Networkingsupport /Bluetoothsubsystemsupport/Bluetoothdevicedrivers 目 录 下 添 加 USB 蓝 牙 驱 动 的 支 持 图 添 加 USB 蓝 牙 驱 动 蓝 牙 的 电 源 管 理 系 统 开 发 开 启 蓝 牙 对 整 个 系 统 来 说 耗 电 量 很 大, 所 以 要 对 蓝 牙 系 统 进 行 电 源 管 理, 在 Android 系 统 的 启 动 脚 本 中 添 加 蓝 牙 的 电 源 管 理 #Defineforbluetooth

386 write/sys/class/rfkill/rfkill0/state0 chownbluetoothbluetooth/sys/class/rfkill/rfkill0/type chownbluetoothbluetooth/sys/class/rfkill/rfkill0/state chmod0777/sys/class/rfkill/rfkill0/state Android 使 用 标 准 的 Linuxrfkill 接 口 进 行 蓝 牙 芯 片 电 源 管 理 staticstructusb_driverbtusb_driver={.name ="btusb",.probe =btusb_probe,.disconnect =btusb_disconnect, #ifdefconfig_pm.suspend =btusb_suspend,.resume =btusb_resume, #endif.id_table =btusb_table,.supports_autosuspend=1, }; staticint initbtusb_init(void) { BT_INFO("GenericBluetoothUSBdriverver%s",VERSION); returnusb_register(&btusb_driver); } staticvoid exitbtusb_exit(void) { usb_deregister(&btusb_driver); } 蓝 牙 硬 件 抽 象 层 开 发 蓝 牙 的 驱 动 程 序 一 般 都 通 过 标 准 的 HCI 控 制 实 现 但 根 据 硬 件 接 口 和 初 始 化 流 程 的 不 同, 又 存 在 一 些 差 别 这 类 初 始 化 动 作 一 般 是 一 些 晶 振 频 率, 波 特 率 等 基 础 设 置 比 如 CSR 的 芯 片 一 般 通 过 BCSP 协 议 完 成 最 初 的 初 始 化 配 置, 再 激 活 标 准 HCI 控 制 流 程 对 Linux 来 说, 一 旦 bluez 可 以 使 用 HCI 与 芯 片 建 立 起 通 信 ( 一 般 是 hciattach+hciconfig), 便 可 以 利 用 其 上 的 标 准 协 议 (SCO,L2CAP 等 ), 与 蓝 牙 通 信, 使 其 正 常 工 作 了 S210X 开 发 平 台 使 用 的 蓝 牙 模 块 是 用 USB 驱 动 的, 而 hciattach 连 接 时 使 用 的 串 口, 所 以 需 要 删 除 system/bluetooth/bluedroid/bluetooth.c 中 有 关 使 用 串 口 进 行 蓝 牙 通 信 的 内 容 将 bluetooth.c 文 件 中 以 下 内 容 删 除 //Tryfor10seconds,thiscanonlysucceedoncehciattachhassentthe //firmwareandthenturnedonhcideviceviahciuartsetprotoioctl for(attempt=1000;attempt>0;attempt--){

387 hci_sock=create_hci_sock(); if(hci_sock<0)gotoout; if(!ioctl(hci_sock,hcidevup,hci_dev_id)){ break; } } Android 下 蓝 牙 软 件 设 计 原 理 蓝 牙 系 统 对 上 层 的 接 口 通 过 比 较 通 用 的 接 口 传 递 给 Java 层, 在 Android 的 应 用 程 序 层 通 过 调 用 蓝 牙 系 统 的 接 口 实 现 蓝 牙 的 各 种 规 范 蓝 牙 系 统 的 核 心 是 BlueZ, 因 此 JNI 和 上 层 都 围 绕 跟 BlueZ 的 沟 通 进 行 在 SystemServer 启 动 的 时 候, 会 生 成 一 个 BluetoothDeviceService 的 实 例 //SkipBluetoothifwehaveanemulatorkernel //TODO:Useamorereliablechecktoseeifthisproductshould //supportbluetooth-seebug if(systemproperties.get("ro.kernel.qemu").equals("1")){ Log.i(TAG,"RegisteringnullBluetoothService(emulator)"); ServiceManager.addService(Context.BLUETOOTH_SERVICE,null); }elseif(factorytest==systemserver.factory_test_low_level){ Log.i(TAG,"RegisteringnullBluetoothService(factorytest)"); ServiceManager.addService(Context.BLUETOOTH_SERVICE,null); }else{ Log.i(TAG,"StartingBluetoothService."); bluetooth=newbluetoothdeviceservice(context); bluetooth.init(); ServiceManager.addService(Context.BLUETOOTH_SERVICE,bluetooth); intbluetoothon=settings.system.getint(mcontentresolver, Settings.System.BLUETOOTH_ON,0); if(bluetoothon>0){ bluetooth.enable(null); } } BluetoothDeviceService 会 生 成 一 个 BluetoothEventLoop 实 例, 它 们 两 者 均 通 过 DBUS 来 和 BlueZ 通 信 BluetoothDeviceService 是 通 过 DBUS 向 BlueZ 发 送 命 令, 而 命 令 的 返 回 结 果 则 是 由 BlueZ 通 过 DBUS 传 回 给 BluetoothEventLoop 的 ( 具 体 交 互 请 参 见 BlueZ 的 dbus_api.txt),bluez 也 会 通 过 DBUS 向 BluetoothEventLoop 发 送 一 些 事 件 通 知 BluetoothEventLoop 和 外 部 的 接 口 是 通 过 预 先 定 义 的 Intent, 初 始 的 时 候 蓝 牙 是 没 有 使 能 的,

388 要 通 过 BluetoothSettings 或 者 WirelessSettings 来 打 开 蓝 牙 设 备, 然 后 通 过 BluetoothSettings 去 查 找 附 近 的 其 他 蓝 牙 设 备, 找 到 后 可 以 建 立 RFCOMM 连 接 和 配 置 实 验 步 骤 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 插 入 SD 卡, 把 蓝 牙 模 块 (USB 接 口 ) 连 接 于 S210X 开 发 平 台 的 相 应 接 口 上 2) 给 开 发 平 台 上 电 启 动 Android 系 统 将 范 例 程 序 BlueToothTest01 通 过 Import-> Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上, 如 图 所 示 : 图 BlueToothTest01 示 例 运 行 界 面 3) 单 击 本 机 蓝 牙 可 见 按 钮, 本 机 的 蓝 牙 地 址 将 被 显 示, 如 图 所 示 : 图 本 机 蓝 牙 可 见 4) 单 击 打 开 按 钮, 蓝 牙 设 备 将 被 打 开, 单 击 搜 索 设 备 下 方 将 显 示 搜 索 的 蓝 牙 设 备 名 称, 如 图 所 示 :

389 图 搜 索 到 的 蓝 牙 设 置 5) 单 击 退 出 程 序 按 钮, 可 以 退 出 本 程 序 16.6 摄 像 头 设 备 移 植 实 验 目 的 了 解 COMS 摄 像 头 基 本 知 识 ; 了 解 linux 下 摄 像 头 驱 动 的 设 计 ; 掌 握 android 下 摄 像 头 软 件 的 开 发 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 CMOS 摄 像 头 简 介 CMOS 摄 像 头 是 一 种 镜 头 的 名 称, 是 数 码 设 备 用 来 感 光 成 像 的 部 件 CMOS 被 看 作 未 来 的 成 像 器 件 因 为 CMOS 摄 像 头 构 件 相 对 简 单, 与 现 有 的 大 规 模 集 成 电 路 生 产 工 艺 相 同, 从 而 生 产 成 本 可 以 降 低 从 原 理 上,CMOS 的 信 号 是 以 点 为 单 位 的 电 荷 信 号, 速 度 很 快, 也 很 省 电

390 CMOS 摄 像 头 利 用 矽 感 光 二 极 体 (photodiode) 进 行 光 与 电 的 转 换 这 种 转 换 的 原 理 与 各 位 手 上 具 备 太 阳 电 能 电 子 计 算 机 的 太 阳 能 电 池 效 应 相 近, 光 线 越 强 电 力 越 强 ; 反 之, 光 线 越 弱 电 力 也 越 弱 的 道 理, 将 光 影 像 转 换 为 电 子 数 字 信 号 CMOS 应 用 半 导 体 工 业 常 用 的 MOS 制 程, 可 以 一 次 整 合 全 部 周 边 设 施 于 单 晶 片 中, 节 省 加 工 晶 片 所 需 负 担 的 成 本 和 效 率 的 损 失 CMOS 的 影 像 电 荷 驱 动 方 式 为 主 动 式, 感 光 二 极 体 所 产 生 的 电 荷 会 直 接 由 旁 边 的 电 晶 体 做 放 大 输 出 CMOS 具 有 低 成 本 低 耗 电 以 及 高 整 合 度 的 特 性 CMOS 系 列 开 始 朝 向 大 尺 寸 面 积 与 高 速 影 像 处 理 晶 片 统 合, 藉 由 后 续 的 影 像 处 理 修 正 噪 点 以 及 画 质 表 现, 特 别 是 Canon 系 列 的 EOSD30 EOS300D 的 成 功, 足 见 高 速 影 像 处 理 晶 片 已 经 可 以 胜 任 高 像 素 CMOS 所 产 生 的 影 像 处 理 时 间 与 能 力 的 缩 短 CMOS 未 来 跨 足 高 阶 的 影 像 市 场 产 品, 前 景 可 期 目 前, 市 场 销 售 的 数 码 摄 像 头 中 以 CMOS 感 光 器 件 的 为 主 在 采 用 CMOS 为 感 光 元 器 件 的 产 品 中, 通 过 采 用 影 像 光 源 自 动 增 益 补 强 技 术, 自 动 亮 度 白 平 衡 控 制 技 术, 色 饱 和 度 对 比 度 边 缘 增 强 以 及 伽 马 矫 正 等 先 进 的 影 像 控 制 技 术 Linux 下 摄 像 头 驱 动 设 计 在 Linux 下 编 写 摄 像 头 驱 动 主 要 是 编 写 ISI(ImageSensorInterface) 驱 动 ISI 驱 动 的 主 要 流 程 如 下 在 Linux 内 核 中 配 置 DeviceDrivers /Multimediasupport /Videocaptureadapters /OV2655 2M camera support 图 配 置 camera 驱 动 使 用 I2C 总 线 挂 载 摄 像 头 驱 动 staticconststructi2c_device_idcam8000_id[]={ {CAM8000_DRIVER_NAME,0}, {}, }; MODULE_DEVICE_TABLE(i2c,cam8000_id); staticstructv4l2_i2c_driver_datav4l2_i2c_data={.name=cam8000_driver_name,.probe=cam8000_probe,.remove= devexit_p(cam8000_remove),

391 .id_table=cam8000_id, }; 在 板 级 文 件 中 加 载 CAM8000 #ifdefconfig_video_cam8000 staticintcam8000_power_en(intonoff) { interr; err=gpio_request(s5pv210_gpj4(3),"gpj4"); //err=gpio_request(s5pv210_gph1(3),"gph1"); if(err) printk(kern_err"####failedtopower(gpj4)formipicam\n"); err=gpio_request(s5pv210_gpe1(4),"gpe1"); if(err) printk(kern_err"####failedtoreset(gpe1)formipicam\n"); s3c_gpio_setpull(s5pv210_gpj4(3),s3c_gpio_pull_none); //s3c_gpio_setpull(s5pv210_gph1(3),s3c_gpio_pull_none); s3c_gpio_setpull(s5pv210_gpe1(4),s3c_gpio_pull_none); if(onoff){ gpio_direction_output(s5pv210_gpj4(3),0); //gpio_direction_output(s5pv210_gph1(3),0); gpio_direction_output(s5pv210_gpe1(4),0); mdelay(5); gpio_set_value(s5pv210_gpe1(4),1); }else{ gpio_direction_output(s5pv210_gpe1(4),0); mdelay(5); gpio_direction_output(s5pv210_gpj4(3),1); //gpio_direction_output(s5pv210_gph1(3),1); } gpio_free(s5pv210_gpj4(3)); //gpio_free(s5pv210_gph1(3)); gpio_free(s5pv210_gpe1(4)); return0; } #endif #ifdefcam8000_enabled staticstructcam8000_platform_datacam8000_plat={.default_width=800,

392 .default_height=480,.pixelformat=v4l2_pix_fmt_uyvy,.freq= *16,.is_mipi=0, }; staticstructi2c_board_infocam8000_i2c_info={ I2C_BOARD_INFO("CAM8000",(0x60>>1)),.platform_data=&cam8000_plat, }; staticstructs3c_platform_cameracam8000={.id =CAMERA_PAR_A,.type =CAM_TYPE_ITU,.fmt =ITU_601_YCBCR422_8BIT,.order422 =CAM_ORDER422_8BIT_CBYCRY,.i2c_busnum =1,.info =&cam8000_i2c_info,.pixelformat =V4L2_PIX_FMT_UYVY,.srclk_name ="mout_mpll", /*.srclk_name ="xusbxti",*/.clk_name ="sclk_cam0",.clk_rate = *16,.line_length =1920,.width =800,.height =480,.window ={.left =0,.top =0,.width =800,.height =480, }, /*Polarity*/.inv_pclk =0,.inv_vsync =1,.inv_href =0,.inv_hsync =0,.initialized =0, };.cam_power =cam8000_power_en,

393 #endif staticstructs3c_platform_fimcfimc_plat={.srclk_name ="mout_mpll",.clk_name ="fimc",.clk_rate = , #ifdefined(s5k4ea_enabled) defined(s5k6aa_enabled).default_cam =CAMERA_CSI_C, #else #ifdefwriteback_enabled.default_cam =CAMERA_WB, #elifcam_8000_ch_a.default_cam =CAMERA_PAR_A, #else.default_cam =CAMERA_PAR_B, #endif #endif.camera ={ #ifdefs5k3ba_enabled &s5k3ba, #endif #ifdefs5k4ba_enabled &s5k4ba, #endif #ifdefs5k4ea_enabled &s5k4ea, #endif #ifdefs5k6aa_enabled &s5k6aa, #endif #ifdefcam8000_enabled &cam8000, #endif #ifdefwriteback_enabled &writeback, #endif },.hw_ver =0x43, }; #endif

394 Android 下 摄 像 头 软 件 设 计 原 理 在 Android 的 照 相 机 系 统 中, 使 用 宏 USE_CAMERA_STUB 来 标 识 是 否 使 用 真 的 Camera, 如 果 宏 为 真, 则 使 用 CameraHardwareStub.cpp 和 FakeCamera.cpp 构 造 一 个 假 的 Camera, 如 果 为 假 则 使 用 libcamera 来 构 造 一 个 实 际 上 的 Camera 服 务 由 于 在 我 们 的 S210X 开 发 平 台 上 使 用 了 真 的 Camera 硬 件, 所 以 在 编 译 选 项 中 需 要 修 改 如 下 USE_CAMERA_STUB:=false ifeq($(use_camera_stub),false) BOARD_CAMERA_LIBRARIES:=libcamera endif 在 Android 系 统 运 行 时, 在 应 用 程 序 中 使 用 摄 像 头 快 门 按 下 的 时 候 onshutter() 被 回 调 privatefinalclassshuttercallback implementsandroid.hardware.camera.shuttercallback{ publicvoidonshutter(){ mshuttercallbacktime=system.currenttimemillis(); mshutterlag=mshuttercallbacktime-mcapturestarttime; Log.v(TAG,"mShutterLag="+mShutterLag+"ms"); clearfocusstate();}} 返 回 照 片 的 JPEG 格 式 的 数 据 privatefinalclassjpegpicturecallbackimplementspicturecallback{ LocationmLocation; publicjpegpicturecallback(locationloc){ mlocation=loc; } publicvoidonpicturetaken( finalbyte[]jpegdata,finalandroid.hardware.cameracamera){ if(mpausing){ return; } mjpegpicturecallbacktime=system.currenttimemillis(); //Ifpostviewcallbackhasarrived,thecapturedimageisdisplayed //inpostviewcallback.ifnot,thecapturedimageisdisplayedin //rawpicturecallback. if(mpostviewpicturecallbacktime!=0){ mshuttertopicturedisplayedtime= mpostviewpicturecallbacktime-mshuttercallbacktime; mpicturedisplayedtojpegcallbacktime= mjpegpicturecallbacktime-mpostviewpicturecallbacktime; }else{

395 mshuttertopicturedisplayedtime= mrawpicturecallbacktime-mshuttercallbacktime; mpicturedisplayedtojpegcallbacktime= mjpegpicturecallbacktime-mrawpicturecallbacktime; } Log.v(TAG,"mPictureDisplayedToJpegCallbackTime=" +mpicturedisplayedtojpegcallbacktime+"ms"); mheadupdisplay.setenabled(true); if(!misimagecaptureintent){ //Wewanttoshowthetakenpictureforawhile,sowewait //foratleast1.2secondbeforerestartingthepreview. longdelay=1200-mpicturedisplayedtojpegcallbacktime; if(delay<0 mquickcapture){ restartpreview(); }else{ mhandler.sendemptymessagedelayed(restart_preview,delay); } } mimagecapture.storeimage(jpegdata,camera,mlocation); //Calculatethisinadvanceofeachshotsowedon'taddtoshutter //latency.it'struethatsomeoneelsecouldwritetothesdcardin //themeantimeandfillit,butthatcouldhavehappenedbetweenthe //shutterpressandsavingthejpegtoo. calculatepicturesremaining(); if(mpicturesremaining<1){ updatestoragehint(mpicturesremaining); } if(!mhandler.hasmessages(restart_preview)){ longnow=system.currenttimemillis(); mjpegcallbackfinishtime=now-mjpegpicturecallbacktime; Log.v(TAG,"mJpegCallbackFinishTime=" +mjpegcallbackfinishtime+"ms"); mjpegpicturecallbacktime=0;} }} 可 以 通 过 以 下 方 法 实 现 照 片 预 览 privatevoidstartpreview()throwscamerahardwareexception{ if(mpausing isfinishing())return; ensurecameradevice(); //Ifwe'repreviewingalready,stopthepreviewfirst(thiswillblank

396 //thescreen). if(mpreviewing)stoppreview(); setpreviewdisplay(msurfaceholder); setcameraparameters(update_param_all); finallongwalltimestart=systemclock.elapsedrealtime(); finallongthreadtimestart=debug.threadcputimenanos(); mcameradevice.seterrorcallback(merrorcallback); try{ Log.v(TAG,"startPreview"); mcameradevice.startpreview(); }catch(throwableex){ closecamera(); thrownewruntimeexception("startpreviewfailed",ex); } mpreviewing=true; mzoomstate=zoom_stopped; mstatus=idle; } 实 验 步 骤 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 把 无 线 Camera 模 块 连 接 于 S210X 开 发 平 台 的 相 应 接 口 上 2) 给 开 发 平 台 上 电, 启 动 Android 系 统 本 实 验 是 实 现 一 个 Camera 拍 照 应 用, 将 范 例 程 序 CameraDemo 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上 ; 3) 单 击 拍 照 键 CAM, 会 听 到 咔 嚓 一 声, 并 将 摄 像 头 捕 获 的 画 面 保 存 成 文 件, 而 在 Device 上 运 行 之 后 可 得 到 如 图 所 示 界 面 :

397 图 拍 照 应 用 在 模 拟 器 上 运 行 效 果 16.7 电 话 ril 层 移 植 实 验 目 的 了 解 电 话 系 统 的 系 统 结 构 ; 了 解 linux 下 电 话 系 统 驱 动 设 计 ; 掌 握 android 下 电 话 系 统 应 用 程 序 的 开 发 实 验 环 境 硬 件 : 电 脑 ( 推 荐 : 主 频 2GHz+, 内 存 :1GB+), S210X 系 列 实 验 平 台 ; 软 件 :Windows 7/Windows XP 实 验 原 理 电 话 系 统 的 系 统 结 构 自 下 而 上,android 的 电 话 部 分 分 为 moderm 驱 动 程 序 RIL 库 RIL 守 护 进 程 电 话 的 java 框 架 电 话 应 用 等 几 个 部 分, 如 图 所 示

398 Java Aplication Calling,SMS Android.telephony. Java Framework Com.android.internal.telephony.* RIL Part Rild deamon Native Framework LibXXXX-ril.so Libril.so Kernel Space RIL Driver (uart sdio usb) 移 植 部 分 1) 驱 动 层 图 电 话 系 统 部 分 的 结 构 Moderm 的 驱 动 程 序 在 linux 内 核 中 的 实 现, 一 般 分 为 AT 命 令 通 道 和 数 据 通 道 这 两 路 接 口 2)RIL 层 RIL 层 由 RIL 守 护 层,libril 库 和 ril 实 现 库 这 三 部 分 组 成 3) 电 话 部 分 的 Java 框 架 层 代 码 的 路 径 为 frameworks/base/telephony/java/, 在 这 个 目 录 中 相 应 的 内 容 为 : Android/telephony: 包 含 GSM 和 CDMA 这 两 个 字 目 录 ; Con/android/internal/telephony: 内 部 实 现 类, 包 含 GSM 和 CDMA 这 两 个 子 目 录 4) 电 话 部 分 的 Java 应 用 层

399 电 话 应 用 的 service 实 现 于 Phone 应 用, 同 时 也 实 现 了 Phone 的 UI 界 面 逻 辑 其 他 如 短 信 网 络 选 择 等 分 别 在 Mms 和 Settings 等 应 用 中 实 现 驱 动 程 序 设 计 S210X 开 发 平 台 通 信 使 用 的 usb 转 串 口 来 驱 动 的 使 用 makemenuconfig 配 置 Linux 内 核, 在 DeviceDriver /USBsupport / USBSerialConventersupport/ 目 录 下 选 择 USBdriverforGSMandCDMAmodems 图 配 置 USBdriverforGSMandCDMAmodems 在 Android 硬 件 抽 象 层 中 添 加 串 口 的 初 始 化 函 数, 即 在 static void*main Loop (void*param) 中 添 加 static void init_ttys(intfd): if(fd>=0){ /*disableechoonserialports*/ structtermiosios; tcgetattr(fd,&ios); ios.c_cflag&=~(csize CSTOPB PARENB PARODD); ios.c_cflag =CREAD CLOCAL CS8; //t.c_cflag&=~(crtscts); ios.c_cflag =CRTSCTS; ios.c_lflag&=~(icanon ECHO ECHOE ECHOK ECHONL ISIG); ios.c_iflag&=~(inpck IGNPAR PARMRK ISTRIP IXANY ICRNL); ios.c_iflag&=~(ixon IXOFF); ios.c_oflag&=~(opost OCRNL); cfsetispeed(&ios,b115200); cfsetospeed(&ios,b115200); tcsetattr(fd,tcsanow,&ios); tcflush(fd,tcioflush); } 设 置 短 信 息 模 式, 即 在 staticvoidinitializecallback(void*param) 中 添 加 如 下 at_send_command("at+cmod=0",null); /*HEXcharacterset*/ at_send_command("at+cscs=\"gsm\"",null);

400 在 intat_handshake() 握 手 连 接 函 数 中 加 入 AT 指 令 并 等 待 响 应, 以 确 保 通 道 已 连 接 并 处 于 激 活 状 态 for(i=0;i<handshake_retry_count;i++){ /*somestacksstartwithverboseoff*/ err=at_send_command_full_nolock("ate0q0v1",no_result, NULL,NULL,HANDSHAKE_TIMEOUT_MSEC,NULL); if(err==0){ break; } } staticvoidonrequest(intrequest,void*data,size_tdatalen,ril_tokent) 中 添 加 RIL_REQUEST_DTMF_START 和 RIL_REQUEST_DTMF_STOP, 并 且 修 改 RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND DTMF 即 双 音 双 频, 手 机 会 将 音 频 传 输 到 网 络, 可 用 来 查 询 答 录 机, 传 输 代 码 等, 利 用 DTMF 信 令 可 选 择 呼 叫 相 应 的 对 讲 机 RIL_REQUEST_HANGUP_FOREGROUND_RES UME_BACKGROUND 表 示 断 开 一 个 正 在 执 行 的 连 接, 也 就 是 挂 断 电 话 : caseril_request_dtmf_start: requestdtmfstart(data,datalen,t); break; caseril_request_dtmf_stop: requestdtmfstop(data,datalen,t); break; caseril_request_hangup_foreground_resume_background: at_send_command("ath",null); Unsolicited 表 示 主 动 上 报 的 消 息, 如 来 电, 来 信 息 等 staticvoidonunsolicited(constchar*s,constchar*sms_pdu) 中 添 加 strstartswith(s, +CMTI: ) 和 strstartswith(s, +CMGR: )AT 指 令 码 的 解 析 其 中 CMTI 是 收 到 新 的 短 信 息,CMGR 是 读 取 新 的 短 信 息 添 加 收 到 短 信 息 的 回 调 函 数 staticvoidonsmsreceived(void*param); elseif(strstartswith(s,"+cmgr")){ RIL_onUnsolicitedResponse( RIL_UNSOL_RESPONSE_NEW_SMS, sms_pdu,strlen(sms_pdu)); }elseif(strstartswith(s,"+cmti:")){ smsbody=strdup(s); RIL_requestTimedCallback(readMessage,NULL,NULL); }

401 配 置 USB 转 串 口 的 脚 本 文 件 #DefinettyUSB2 chownsystemsystem/dev/ttyusb2 chmod777/dev/ttyusb2 数 据 连 接 部 分 数 据 连 接 要 完 成 两 部 分 的 移 植 工 作 :AT 拨 号, 以 及 建 立 PPP 连 接 大 部 分 Moderm 需 要 首 先 通 过 AT 命 令 拨 上 运 营 商 提 供 的 网 关 因 此 在 移 植 过 程 中, 需 要 配 置 相 关 的 处 理 函 数 在 android RIL 中, 该 函 数 为 : staticvoidrequestsetupdatacall(void*data,size_tdatalen,ril_tokent) { constchar*apn; char*cmd; interr; ATResponse*p_response=NULL; char*response[2]={"1",ppp_tty_path}; apn=((constchar**)data)[2]; #ifdefuse_ti_commands //Configformultislotclass10(probablydefaultanywayeh?) err=at_send_command("at%cprim=\"gmm\",\"configmultislot_class=<10>\"", NULL); err=at_send_command("at%data=2,\"uart\",1,,\"ser\",\"uart\",0",null); #endif/*use_ti_commands*/ intfd,qmistatus; size_tcur=0; size_tlen; ssize_twritten,rlen; charstatus[32]={0}; intretry=10; //LOGD("requestingdataconnectiontoAPN'%s'",apn); fd=open("/dev/qmi",o_rdwr); if(fd>=0){/*thedevicedoesn'texistontheemulator*/ //LOGD("openedtheqmidevice\n"); asprintf(&cmd,"up:%s",apn); len=strlen(cmd); while(cur<len){ do{ written=write(fd,cmd+cur,len-cur);

402 }while(written<0&&errno==eintr); if(written<0){ //LOGE("###ERRORwritingto/dev/qmi"); close(fd); gotoerror; } cur+=written; } //waitforinterfacetocomeonline do{ sleep(1); do{ rlen=read(fd,status,31); }while(rlen<0&&errno==eintr); if(rlen<0){ //LOGE("###ERRORreadingfrom/dev/qmi"); close(fd); gotoerror; }else{ status[rlen]='\0'; //LOGD("###status:%s",status); } }while(strncmp(status,"state=up",8)&&strcmp(status,"online")&&--retry); close(fd); if(retry==0){ //LOGE("###Failedtogetdataconnectionup\n"); gotoerror; } qmistatus=system("netcfgrmnet0dhcp"); //LOGD("netcfgrmnet0dhcp:status%d\n",qmistatus); if(qmistatus<0)gotoerror; }else{ asprintf(&cmd,"at+cgdcont=1,\"ip\",\"%s\",,0,0",apn); //FIXMEcheckforerrorhere err=at_send_command(cmd,null); free(cmd); //SetrequiredQoSparamstodefault err=at_send_command("at+cgqreq=1",null); //SetminimumQoSparamstodefault

403 err=at_send_command("at+cgqmin=1",null); //packet-domaineventreporting err=at_send_command("at+cgerep=1,0",null); //Hangupanythingthat'shappeningtherenow err=at_send_command("at+cgact=1,0",null); //StartdataonPDPcontext1 err=at_send_command("atd*99***1#",&p_response); if(err<0 p_response->success==0){ gotoerror; } } RIL_onRequestComplete(t,RIL_E_SUCCESS,response,sizeof(response)); at_response_free(p_response); return; error: RIL_onRequestComplete(t,RIL_E_GENERIC_FAILURE,NULL,0); at_response_free(p_response); } 编 写 PPP 配 置 脚 本 : #!/system/bin/sh /system/bin/setprop"net.interfaces.defaultroute""ppp0" /system/bin/setprop"net.ppp0.dns1""$dns1" /system/bin/setprop"net.ppp0.dns2""$dns2" /system/bin/setprop"net.ppp0.local-ip""$iplocal" /system/bin/setprop"net.ppp0.remote-ip""$ipremote" exit0 android 下 的 电 话 系 统 软 件 设 计 原 理 Android 系 统 的 主 要 使 用 方 面 是 智 能 电 话, 因 此 电 话 部 分 是 Android 的 核 心 系 统 之 一,Android 的 电 话 系 统 围 绕 底 层 使 用 的 Modem 硬 件 来 搭 建 Android 主 要 提 供 了 呼 叫 (Calling), 短 信 息 (SMS) 等 业 务, 此 外 通 过 电 话 系 统 还 可 以 实 现 数 据 连 接 (DataConnection) 实 现 网 络 功 能 Android 的 软 件 系 统 是 Modem 设 备 的 使 用 者 在 Linux 内 核 中 包 含 了 Modem 的 驱 动 程 序 在 用 户 空 间,RIL 库 作 为 本 地 的 实 现 部 分,Java 框 架 电 话 系 统 对 上 层 的 Java 提 供 了 接 口 RIL 实 现 库 的 接 口 比 较 复 杂, 因 为 需 要 包 含 整 个 电 话 功 能 Hardware/ril/include/telephone 目 录 中 的 ril.h 中 定 义 了 该 接 口, 同 时, 该 目 录 下 的 ril_cdma_sms.h 作 为 对 CDMA 协 议 的 补 充 而 存 在 当 我 们 开 始 编 写 Android 的 电 话 应 用 程 序 的 时 候, 如 果 需 要 进 行 电 话 拨 号, 可 以 进 行 如 下 调 用 ITelephonytpCallModule=(ITelephony)ITelephony.Stub.asInterface(ServiceManager.getService("phon"));

404 tpcallmodule.dial(" "); 而 对 于 短 信 的 应 用, 我 们 需 要 调 用 的 则 是 SmsManager SmsManagerSMS=SmsManager.getDefault(); SMS.sendTextMessage(" ",null,"thisisatestsms",null,null); Android 的 RIL 在 这 里 被 做 成 一 个 叫 做 rild 的 库, 通 过 一 个 系 统 环 境 变 量 ro.radio.noril 是 否 为 空 来 决 定 要 不 要 把 RIL 的 代 码 编 译 进 内 核, 如 果 设 置 了 该 变 量, 将 会 有 个 SimulateCommand 的 玩 意 编 译 进 内 核, 它 可 以 在 没 有 实 际 GSM 硬 件 的 情 况 下 模 拟 部 分 实 际 硬 件 的 指 令, 然 后 让 RIL 驱 动 提 供 给 上 层 应 用, 如 果 没 有 设 置 该 系 统 环 境 变 量 就 会 采 用 RIL 通 过 研 究 RIL 的 代 码 可 以 看 到,Android 的 rild 库 是 介 于 HAL 接 口 与 basebandmodem 之 间, 它 同 样 提 供 了 语 音 数 据 短 信 SIM 卡 管 理 以 及 STK 应 用 的 功 能, 实 现 思 路 跟 微 软 的 RIL 有 异 曲 同 工 之 妙, 也 是 把 标 准 的 GSM 中 常 用 的 如 dial 这 些 做 主 动 请 求 的 操 作 称 之 为 request, 一 共 75 个 ; 另 外 一 类 GSM 模 块 主 动 上 报 的 例 如 信 号 强 度 基 站 信 息 等, 称 之 为 unsolicitedresponse, 一 共 17 个 ; 开 发 模 式 也 是 跟 微 软 RIL 开 发 差 不 多, 需 要 针 对 不 同 的 GSM 模 块 进 行 不 同 的 GSM 驱 动 开 发, 公 用 的 部 分 google 给 我 们 做 好 了, 特 定 的 部 分 需 要 你 自 己 去 定 制, 这 样 做 可 以 大 大 地 提 高 开 发 效 率 RIL 跟 上 层 通 讯 主 要 采 用 两 种 方 式, 一 种 是 通 过 Socket 发 送 与 接 收 消 息 的 方 式 来 实 现, 这 个 Socket 在 ril.cpp 里 面 可 以 找 到 它 的 创 建 代 码 : s_fdlisten=android_get_control_socket(socket_name_ril); 还 有 另 外 一 种 方 式 就 是 直 接 通 过 TCP/IP 直 接 访 问 内 核 中 的 sharedmemory, 进 行 RPC 调 用, 这 种 方 式 主 要 应 用 在 数 据 模 式 上, 一 来 由 于 Android 的 每 个 Activity 随 时 都 会 有 可 能 需 要 网 络 连 接 接 收 发 送 数 据, 因 此 必 须 提 供 一 种 实 时 性 较 高 访 问 的 方 式, 二 来 可 以 提 高 通 讯 效 率 Telephony 由 于 是 运 行 在 我 们 的 Dalvik 虚 拟 机 上 面 的, 所 以 它 的 实 现 也 就 更 面 向 对 象 化 了 接 下 来 让 我 们 看 看 怎 么 使 用 这 个 Telephony 库 开 发 我 们 的 电 话 应 用 Telephony 库 主 要 负 责 Android 的 拨 打 与 接 听 电 话 功 能, 其 中 有 两 个 重 要 的 类 分 别 是 IPhone 和 PhoneNumberUtils 是 我 们 实 现 电 话 功 能 必 不 可 少 的 当 我 们 的 应 用 需 要 拨 打 一 个 号 码 的 时 候, Android 默 认 是 没 有 授 予 我 们 这 个 应 用 的 这 个 权 限 的, 因 此 我 们 必 须 在 AndroidManifest.xml 中 去 打 开 这 个 权 限 AndroidManifest.xml 是 每 一 个 应 用 都 需 要 的 文 件, 它 位 于 应 用 的 根 目 录 下, 文 件 里 描 述 了 程 序 包 的 全 局 变 量, 包 括 暴 露 的 应 用 组 件 (activities,services 等 等 ) 和 为 每 个 组 件 的 实 现 类, 以 及 什 么 样 的 数 据 可 以 操 作 和 它 在 什 么 地 方 运 行 现 在 我 们 在 里 面 添 加 一 行 : 从 此 我 们 的 应 用 就 拥 有 了 拨 打 电 话 的 权 限 了, 接 下 来 就 是 建 立 一 个 IPhone 类 的 对 象, 上 次 我 已 经 介 绍 了 必 须 要 通 过 ServiceManager 来 获 得, 以 下 代 码 演 示 了 如 何 建 立 一 个 IPhone 类 对 象 privatestaticiphonegetphoneinterface()throwsdeadobjectexception { IServiceManagersm=ServiceManagerNative.getDefault();

405 IPhonephoneService=IPhone.Stub.asInterface(sm.getService("phone")); returnphoneservice; } 一 旦 建 立 完 了 IPhone 对 象, 即 可 使 用 call 或 者 dail 方 法 来 拨 电 话 了 voidcall(stringnumber) voiddial(stringnumber) 它 们 之 间 的 差 别 就 是 call 是 在 后 台 进 行 的, 一 般 用 于 数 据 传 输 (gprs,edge) 的 应 用, 而 dial 是 会 显 示 一 个 简 单 的 拨 号 界 面, 上 面 预 设 了 你 的 参 数 作 为 拨 号 的 号 码, 如 果 给 dial 的 参 数 传 入 NULL, 则 会 调 用 拨 号 的 界 面 显 示 出 来 还 有 一 种 简 单 的 拨 号 方 法, 有 仔 细 看 Intent 文 档 的 人 就 会 发 现, 对 一 个 电 话 格 式 的 网 址 ( 如 href="tel:(+86) ") 发 送 出 CALL_ACTION, 就 可 以 调 用 拨 号 程 序 对 其 进 行 拨 号 这 种 方 便 的 方 法 可 以 在 开 发 我 们 的 浏 览 器 应 用 的 时 候, 直 接 在 浏 览 网 页 的 时 候 正 则 匹 配 到 电 话 号 码, 然 后 直 接 调 用 拨 号 程 序 对 其 拨 号 获 取 电 话 的 属 性 可 以 通 过 TelephonyProperties 来 实 现, 比 如 SIM 卡,IMEI 等 信 息, 我 们 可 以 通 过 调 用 os.systemproperties.put() 方 法 传 入 TelephonyProperties 的 字 段 来 设 置 对 应 的 参 数, 也 可 以 通 过 os.systemproperties.get() 方 法 获 取 这 些 参 数, 以 下 是 一 些 实 际 引 用 的 例 子 获 取 本 机 号 码, 调 用 android.os.systemproperties.get(property_line1_number); 获 取 IMEI, 调 用 android.os.systemproperties.get(property_imei); 获 取 运 营 商 名 字, 调 用 android.os.systemproperties.get(property_sim_operator_alpha); 获 取 国 家 代 码, 调 用 android.os.systemproperties.get(property_sim_operator_iso_country); 获 取 语 音 信 箱 号 码, 调 用 android.os.systemproperties.get(property_line1_voice_mail_number); 实 验 步 骤 1)S210X 开 发 平 台 固 化 好 出 厂 Android 系 统 映 像 后, 使 用 GSM3G 无 线 通 讯 模 块, 把 GSM3G 无 线 通 讯 模 块 ( 串 行 接 口 ) 连 接 于 S210X 开 发 平 台 的 相 应 接 口 上 2) 给 开 发 平 台 上 电 启 动 Android 系 统 GSM 模 块 将 会 自 动 搜 索 网 络 信 号, 此 时 GSM 模 块 上 的 电 源 指 示 灯 D3 会 常 亮 ( 如 果 启 动 到 Android 界 面, 信 号 仍 然 没 有 搜 索 到 请 按 下 复 位 键 重 启 系 统 ) 3) 将 范 例 程 序 SendSMS 通 过 Import->Existing Projects into Workspace 导 入 到 Java Eclipse

406 集 成 开 发 环 境 中, 并 运 行 在 实 验 板 对 应 的 Device 设 备 上, 运 行 界 面 如 图 所 示 : 图 拨 号 发 短 信 实 例 运 行 界 面 4) 输 入 手 机 号, 单 击 拨 打 此 号 可 以 进 行 拨 号 操 作 输 入 手 机 号 和 短 信 内 容, 单 击 发 送 短 信 按 钮 短 信 将 被 发 送 到 指 定 号 码

I

I 机 电 一 级 注 册 建 造 师 继 续 教 育 培 训 广 东 培 训 点 网 上 报 名 操 作 使 用 手 册 (2013 年 1 月, 第 一 版 ) 第 一 章 个 人 注 册 与 个 人 信 息 管 理 1. 个 人 注 册 ( 请 每 人 只 申 请 一 个 注 册 号, 如 果 单 位 批 量 报 班 单 位 帮 申 请 注 册, 不 需 个 人 再 注 册 ) 首 次 报 班,

More information

修改版-操作手册.doc

修改版-操作手册.doc 职 称 信 息 系 统 升 级 指 南 须 使 用 IE9 及 其 以 上 版 本 浏 览 器 或 谷 歌 浏 览 器 登 录 www.njrs.gov.cn 南 京 市 职 称 ( 职 业 资 格 ) 工 作 领 导 小 组 办 公 室 2016 年 5 月 目 录 一 申 报 人 员 操 作 指 南...1 1.1 职 称 初 定 申 报...1 1.1.1 职 称 初 定 基 础 信 息 填

More information

《C语言基础入门》课程教学大纲

《C语言基础入门》课程教学大纲 C 语 言 开 发 入 门 教 程 课 程 教 学 大 纲 课 程 编 号 :201409210011 学 分 :5 学 分 学 时 :58 学 时 ( 其 中 : 讲 课 学 时 :39 学 时 上 机 学 时 :19 学 时 ) 先 修 课 程 : 计 算 机 导 论 后 续 课 程 :C++ 程 序 设 计 适 用 专 业 : 信 息 及 其 计 算 机 相 关 专 业 开 课 部 门 : 计

More information

评 委 : 李 炎 斌 - 个 人 技 术 标 资 信 标 初 步 审 查 明 细 表 序 号 投 标 单 位 投 标 函 未 按 招 标 文 件 规 定 填 写 漏 填 或 内 容 填 写 错 误 的 ; 不 同 投 标 人 的 投 标 文 件 由 同 一 台 电 脑 或 同 一 家 投 标 单

评 委 : 李 炎 斌 - 个 人 技 术 标 资 信 标 初 步 审 查 明 细 表 序 号 投 标 单 位 投 标 函 未 按 招 标 文 件 规 定 填 写 漏 填 或 内 容 填 写 错 误 的 ; 不 同 投 标 人 的 投 标 文 件 由 同 一 台 电 脑 或 同 一 家 投 标 单 评 委 : 李 炎 斌 - 个 人 清 标 评 审 明 细 表 评 审 因 素 序 号 投 标 单 位 清 标 评 审 1 深 圳 市 创 捷 科 技 有 限 合 格 2 四 川 川 大 智 胜 软 件 股 份 有 限 合 格 3 北 京 航 天 长 峰 科 技 工 业 集 团 有 限 公 司 合 格 4 深 圳 中 兴 力 维 技 术 有 限 合 格 5 深 圳 键 桥 通 讯 技 术 股 份 有

More information

<433A5C446F63756D656E747320616E642053657474696E67735C41646D696E6973747261746F725CD7C0C3E65CC2DBCEC4CFB5CDB3CAB9D3C3D6B8C4CFA3A8BCF2BBAFA3A95CCAB9D3C3D6B8C4CF31302D31392E646F63>

<433A5C446F63756D656E747320616E642053657474696E67735C41646D696E6973747261746F725CD7C0C3E65CC2DBCEC4CFB5CDB3CAB9D3C3D6B8C4CFA3A8BCF2BBAFA3A95CCAB9D3C3D6B8C4CF31302D31392E646F63> ( 一 ) 系 统 整 体 操 作 流 程 简 述 3 ( 二 ) 系 统 中 各 角 色 操 作 功 能 说 明 5 1. 学 院 管 理 员 5 2. 教 学 院 长 8 3. 指 导 教 师 10 4. 答 辩 组 组 长 12 5. 学 生 12 6. 系 统 管 理 员 15 ( 一 ) 论 文 系 统 常 见 问 题 16 ( 二 ) 论 文 查 重 常 见 问 题 22 1 2 主

More information

2 熟 悉 Visual Basic 的 集 成 开 发 环 境 3 了 解 可 视 化 面 向 对 象 编 程 事 件 驱 动 交 互 式 开 发 等 基 本 概 念 4 了 解 Visual Basic 的 特 点 环 境 要 求 与 安 装 方 法 1 Visual Basic 开 发 应 用

2 熟 悉 Visual Basic 的 集 成 开 发 环 境 3 了 解 可 视 化 面 向 对 象 编 程 事 件 驱 动 交 互 式 开 发 等 基 本 概 念 4 了 解 Visual Basic 的 特 点 环 境 要 求 与 安 装 方 法 1 Visual Basic 开 发 应 用 Visual Basic 程 序 设 计 A 级 分 级 班 教 学 大 纲 ( 供 计 算 机 与 信 息 技 术 基 础 课 程 分 级 教 学 A 级 班 使 用 ) I 前 言 Visual Basic 程 序 设 计 课 程 是 一 门 计 算 机 语 言 基 础 课 程 通 过 对 该 课 程 的 学 习, 使 学 生 初 步 掌 握 Visual Basic 的 语 言 特 点, 掌

More information

评 委 : 徐 岩 宇 - 个 人 技 术 标 资 信 标 初 步 审 查 明 细 表 序 号 投 标 单 位 投 标 函 未 按 招 标 文 件 规 定 填 写 漏 填 或 内 容 填 写 错 误 的 ; 不 同 投 标 人 的 投 标 文 件 由 同 一 台 电 脑 或 同 一 家 投 标 单

评 委 : 徐 岩 宇 - 个 人 技 术 标 资 信 标 初 步 审 查 明 细 表 序 号 投 标 单 位 投 标 函 未 按 招 标 文 件 规 定 填 写 漏 填 或 内 容 填 写 错 误 的 ; 不 同 投 标 人 的 投 标 文 件 由 同 一 台 电 脑 或 同 一 家 投 标 单 评 委 : 徐 岩 宇 - 个 人 清 标 评 审 明 细 表 评 审 因 素 序 号 投 标 单 位 清 标 评 审 1 深 圳 市 创 捷 科 技 有 限 合 格 2 四 川 川 大 智 胜 软 件 股 份 有 限 合 格 3 北 京 航 天 长 峰 科 技 工 业 集 团 有 限 公 司 合 格 4 深 圳 中 兴 力 维 技 术 有 限 合 格 5 深 圳 键 桥 通 讯 技 术 股 份 有

More information

目 录 一 系 统 访 问... 1 二 门 户 首 页 申 报 用 户 审 核 用 户... 2 三 系 统 登 录 用 户 名 密 码 登 录 新 用 户 注 册 用 户 登 录 已 注 册 用

目 录 一 系 统 访 问... 1 二 门 户 首 页 申 报 用 户 审 核 用 户... 2 三 系 统 登 录 用 户 名 密 码 登 录 新 用 户 注 册 用 户 登 录 已 注 册 用 水 路 运 输 建 设 综 合 管 理 信 息 系 统 - 门 户 系 统 用 户 手 册 二 零 一 五 年 十 一 月 目 录 一 系 统 访 问... 1 二 门 户 首 页... 1 1. 申 报 用 户... 1 2. 审 核 用 户... 2 三 系 统 登 录... 4 1. 用 户 名 密 码 登 录... 4 1.1 新 用 户 注 册... 4 1.2 用 户 登 录... 7

More information

目 录 关 于 图 标... 3 登 陆 主 界 面... 3 工 单 管 理... 5 工 单 列 表... 5 搜 索 工 单... 5 工 单 详 情... 6 创 建 工 单... 9 设 备 管 理 巡 检 计 划 查 询 详 情 销 售 管

目 录 关 于 图 标... 3 登 陆 主 界 面... 3 工 单 管 理... 5 工 单 列 表... 5 搜 索 工 单... 5 工 单 详 情... 6 创 建 工 单... 9 设 备 管 理 巡 检 计 划 查 询 详 情 销 售 管 宝 汇 德 Turbocare 微 服 务 系 统 客 户 操 作 手 册 Version 2.0 北 京 宝 汇 德 技 术 服 务 器 有 限 公 司 技 术 研 发 部 目 录 关 于 图 标... 3 登 陆 主 界 面... 3 工 单 管 理... 5 工 单 列 表... 5 搜 索 工 单... 5 工 单 详 情... 6 创 建 工 单... 9 设 备 管 理... 10 巡

More information

说 明 为 了 反 映 教 运 行 的 基 本 状 态, 为 校 和 院 制 定 相 关 政 策 和 进 行 教 建 设 与 改 革 提 供 据 依 据, 校 从 程 资 源 ( 开 类 别 开 量 规 模 ) 教 师 结 构 程 考 核 等 维 度, 对 2015 年 春 季 期 教 运 行 基

说 明 为 了 反 映 教 运 行 的 基 本 状 态, 为 校 和 院 制 定 相 关 政 策 和 进 行 教 建 设 与 改 革 提 供 据 依 据, 校 从 程 资 源 ( 开 类 别 开 量 规 模 ) 教 师 结 构 程 考 核 等 维 度, 对 2015 年 春 季 期 教 运 行 基 内 部 资 料 东 北 师 范 大 教 运 行 基 本 状 态 据 报 告 2015 年 春 季 期 教 务 处 2015 年 10 月 27 日 说 明 为 了 反 映 教 运 行 的 基 本 状 态, 为 校 和 院 制 定 相 关 政 策 和 进 行 教 建 设 与 改 革 提 供 据 依 据, 校 从 程 资 源 ( 开 类 别 开 量 规 模 ) 教 师 结 构 程 考 核 等 维 度,

More information

何 秋 琳 张 立 春 视 觉 学 习 研 究 进 展 视 觉 注 意 视 觉 感 知

何 秋 琳 张 立 春 视 觉 学 习 研 究 进 展 视 觉 注 意 视 觉 感 知 第 卷 第 期 年 月 开 放 教 育 研 究 何 秋 琳 张 立 春 华 南 师 范 大 学 未 来 教 育 研 究 中 心 广 东 广 州 随 着 图 像 化 技 术 和 电 子 媒 体 的 发 展 视 觉 学 习 也 逐 步 发 展 为 学 习 科 学 的 一 个 研 究 分 支 得 到 研 究 人 员 和 教 育 工 作 者 的 广 泛 关 注 基 于 此 作 者 试 图 对 视 觉 学 习

More information

0 年 上 半 年 评 价 与 考 核 细 则 序 号 部 门 要 素 值 考 核 内 容 考 核 方 式 考 核 标 准 考 核 ( 扣 原 因 ) 考 评 得 3 安 全 生 产 目 30 无 同 等 责 任 以 上 道 路 交 通 亡 人 事 故 无 轻 伤 责 任 事 故 无 重 大 质 量

0 年 上 半 年 评 价 与 考 核 细 则 序 号 部 门 要 素 值 考 核 内 容 考 核 方 式 考 核 标 准 考 核 ( 扣 原 因 ) 考 评 得 3 安 全 生 产 目 30 无 同 等 责 任 以 上 道 路 交 通 亡 人 事 故 无 轻 伤 责 任 事 故 无 重 大 质 量 0 年 上 半 年 评 价 与 考 核 细 则 序 号 部 门 要 素 值 考 核 内 容 考 核 方 式 考 核 标 准 无 同 等 责 任 以 上 道 路 交 通 亡 人 事 故 3 无 轻 伤 责 任 事 故 目 标 30 及 事 无 重 大 质 量 工 作 过 失 故 管 无 其 他 一 般 责 任 事 故 理 在 公 司 文 明 环 境 创 建 中, 无 工 作 过 失 及 被 追 究 的

More information

国债回购交易业务指引

国债回购交易业务指引 附 件 1 上 海 证 券 交 易 所 新 质 押 式 国 债 回 购 交 易 业 务 指 引 一 总 述 根 据 上 海 证 券 交 易 所 债 券 交 易 实 施 细 则, 上 证 所 将 于 2006 年 5 月 8 日 起 推 出 新 质 押 式 国 债 回 购 新 质 押 式 回 购 与 现 行 质 押 式 回 购 相 比 区 别 主 要 在 以 下 几 个 方 面 :1 新 质 押 式

More information

世华财讯模拟操作手册

世华财讯模拟操作手册 第 一 部 分 : 股 票 模 拟 操 作 部 分 1. 登 录 与 主 界 面 1.1 登 录 学 生 在 桌 面 上, 打 开 世 华 文 件 夹, 直 接 双 击 文 件 夹 中 的 快 捷 图 标, 系 统 弹 出 世 华 财 讯 模 拟 股 票 交 易 系 统 ( 客 户 端 ) 窗 口, 如 图 1.1 所 示 图 1.1 请 输 入 登 录 名 称 及 密 码, 单 击 确 认 登 录

More information

深圳市新亚电子制程股份有限公司

深圳市新亚电子制程股份有限公司 证 券 代 码 :002388 证 券 简 称 : 新 亚 制 程 公 告 编 号 :2016-053 深 圳 市 新 亚 电 子 制 程 股 份 有 限 公 司 2016 年 第 二 次 临 时 股 东 大 会 决 议 公 告 本 公 司 及 董 事 会 全 体 成 员 保 证 公 告 内 容 真 实 准 确 和 完 整, 不 存 在 虚 假 记 载 误 导 性 陈 述 或 者 重 大 遗 漏 特

More information

登录、注册功能的测试用例设计.doc

登录、注册功能的测试用例设计.doc 注 册 登 陆 测 试 用 例 和 修 改 密 码 测 试 用 例 完 整 版 摘 自 网 络, 狗 狗 整 理 zqh139@126.com 修 改 历 史 日 期 版 本 作 者 修 改 内 容 评 审 号 变 更 控 制 号 2010-11-25 1.0 初 稿 2011-09-17 2.0 整 理 一 注 册 测 试 用 例 序 号 : 1 控 件 名 称 : 功 能 描 述 : 注 册 编

More information

乐视云视频发行平台 操作手册 V1.1

乐视云视频发行平台            操作手册 V1.1 乐 视 云 视 频 发 行 平 台 操 作 手 册 V1.1 1 登 录 视 频 发 行 用 户 可 通 过 浏 览 器 访 问 http://vrp.lecloud.com/ 即 可 快 速 进 入 视 频 发 行 一 内 容 商 平 台 : 1 首 页 在 首 页 中, 您 可 以 查 看 视 频 播 放 总 数 被 订 购 商 品 数 订 单 总 数 拥 有 商 品 拥 有 内 容 默 认 查

More information

,,,,, :,, (.,, );, (, : ), (.., ;. &., ;.. &.., ;, ;, ),,,,,,, ( ) ( ),,,,.,,,,,, : ;, ;,.,,,,, (., : - ),,,, ( ),,,, (, : ),, :,

,,,,, :,, (.,, );, (, : ), (.., ;. &., ;.. &.., ;, ;, ),,,,,,, ( ) ( ),,,,.,,,,,, : ;, ;,.,,,,, (., : - ),,,, ( ),,,, (, : ),, :, : 周 晓 虹 : - -., - - - -. :( ), -,.( ),,, -. - ( ).( ) ', -,,,,, ( ).( ),,, -., '.,, :,,,, :,,,, ,,,,, :,, (.,, );, (, : ), (.., ;. &., ;.. &.., ;, ;, ),,,,,,, ( ) ( ),,,,.,,,,,, : ;, ;,.,,,,, (., : - ),,,,

More information

自 服 务 按 钮 无 法 访 问 新 系 统 的 自 服 务 页 面 因 此 建 议 用 户 从 信 网 中 心 (http://nc.tju.edu.cn) 主 页, 右 下 角 位 置 的 常 用 下 载, 或 校 园 网 用 户 自 服 务 (http://g.tju.edu.cn) 首 页

自 服 务 按 钮 无 法 访 问 新 系 统 的 自 服 务 页 面 因 此 建 议 用 户 从 信 网 中 心 (http://nc.tju.edu.cn) 主 页, 右 下 角 位 置 的 常 用 下 载, 或 校 园 网 用 户 自 服 务 (http://g.tju.edu.cn) 首 页 校 园 网 认 证 计 费 系 统 变 更 说 明 及 使 用 帮 助 为 提 高 校 园 网 的 可 靠 性 和 可 用 性, 提 升 用 户 的 上 网 体 验, 同 时 也 为 解 决 近 期 校 园 网 无 法 认 证 或 登 录 页 面 弹 出 缓 慢 的 问 题, 信 网 中 心 于 近 期 对 校 园 网 认 证 计 费 系 统 进 行 升 级 切 换 现 将 升 级 后 新 系 统

More information

第2章 数据类型、常量与变量

第2章  数据类型、常量与变量 第 2 章 数 据 类 型 常 量 与 变 量 在 计 算 机 程 序 中 都 是 通 过 值 (value) 来 进 行 运 算 的, 能 够 表 示 并 操 作 值 的 类 型 为 数 据 类 型 在 本 章 里 将 会 介 绍 JavaScript 中 的 常 量 (literal) 变 量 (variable) 和 数 据 类 型 (data type) 2.1 基 本 数 据 类 型 JavaScript

More information

18 上 报 该 学 期 新 生 数 据 至 阳 光 平 台 第 一 学 期 第 四 周 至 第 六 周 19 督 促 学 习 中 心 提 交 新 增 专 业 申 请 第 一 学 期 第 四 周 至 第 八 周 20 编 制 全 国 网 络 统 考 十 二 月 批 次 考 前 模 拟 题 第 一 学

18 上 报 该 学 期 新 生 数 据 至 阳 光 平 台 第 一 学 期 第 四 周 至 第 六 周 19 督 促 学 习 中 心 提 交 新 增 专 业 申 请 第 一 学 期 第 四 周 至 第 八 周 20 编 制 全 国 网 络 统 考 十 二 月 批 次 考 前 模 拟 题 第 一 学 1 安 排 组 织 全 国 网 络 统 考 九 月 批 次 网 上 考 前 辅 导 第 一 学 期 第 一 周 统 考 考 前 半 个 月 2 下 发 全 国 网 络 统 考 九 月 批 次 准 考 证 第 一 学 期 第 一 周 导 出 下 半 年 成 人 本 科 学 士 学 位 英 语 统 一 考 试 报 考 3 信 息 第 一 学 期 第 一 周 4 教 学 计 划 和 考 试 计 划 上 网,

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc 52 5 天 通 过 职 称 计 算 机 考 试 ( 考 点 视 频 串 讲 + 全 真 模 拟 ) Word 2003 中 文 字 处 理 ( 第 2 版 ) 第 3 章 3 字 符 格 式 需 要 掌 握 的 考 点 字 体 字 形 和 字 号 的 设 置 ; 上 标 下 标 空 心 字 等 字 体 效 果 的 使 用 ; 字 符 间 距 的 调 整 ; 改 变 字 符 颜 色 底 纹 添 加

More information

教师上报成绩流程图

教师上报成绩流程图 教 务 管 理 系 统 使 用 说 明 学 生 端 用 户 1 在 校 内 任 何 一 台 连 接 校 园 网 的 计 算 机 上 登 录 教 务 处 主 页 教 务 处 主 页 地 址 : http://jw.stdu.edu.cn/homepage 随 后 点 击 按 钮 ( 见 下 图 所 示 ), 即 可 进 入 综 合 教 务 管 理 系 统 2 在 综 合 教 务 管 理 区 域 内 键

More information

云信Linux SSH认证代理用户手册

云信Linux SSH认证代理用户手册 Windows 主 机 登 录 保 护 (RDP) 管 理 员 配 置 手 册 V1.0 云 信 事 业 部 飞 天 诚 信 科 技 股 份 有 限 公 司 www.cloudentify.com 章 节 目 录 第 1 章 管 理 平 台 配 置 说 明... 1 1.1 注 册... 1 1.2 登 录... 3 1.3 添 加 应 用... 4 1.4 添 加 用 户... 7 1.5 激 活

More information

HSK( 一 级 ) 考 查 考 生 的 日 常 汉 语 应 用 能 力, 它 对 应 于 国 际 汉 语 能 力 标 准 一 级 欧 洲 语 言 共 同 参 考 框 架 (CEF) A1 级 通 过 HSK( 一 级 ) 的 考 生 可 以 理 解 并 使 用 一 些 非 常 简 单 的 汉 语

HSK( 一 级 ) 考 查 考 生 的 日 常 汉 语 应 用 能 力, 它 对 应 于 国 际 汉 语 能 力 标 准 一 级 欧 洲 语 言 共 同 参 考 框 架 (CEF) A1 级 通 过 HSK( 一 级 ) 的 考 生 可 以 理 解 并 使 用 一 些 非 常 简 单 的 汉 语 新 汉 语 水 平 考 试 HSK 为 使 汉 语 水 平 考 试 (HSK) 更 好 地 服 务 于 汉 语 学 习 者, 中 国 国 家 汉 办 组 织 中 外 汉 语 教 学 语 言 学 心 理 学 和 教 育 测 量 学 等 领 域 的 专 家, 在 充 分 调 查 了 解 海 外 实 际 汉 语 教 学 情 况 的 基 础 上, 吸 收 原 有 HSK 的 优 点, 借 鉴 近 年 来 国

More information

文 化 记 忆 传 统 创 新 与 节 日 遗 产 保 护 根 据 德 国 学 者 阿 斯 曼 的 文 化 记 忆 理 论 仪 式 与 文 本 是 承 载 文 化 记 忆 的 两 大 媒 体 在 各 种 仪 式 行 为 中 节 日 以 其 高 度 的 公 共 性 有 组 织 性 和 历 史 性 而 特 别 适 用 于 文 化 记 忆 的 储 存 和 交 流 节 日 的 文 化 功 能 不 仅 在 于

More information

全国艺术科学规划项目

全国艺术科学规划项目 全 国 艺 术 科 学 规 划 项 目 网 上 申 报 常 见 问 题 及 解 决 方 法 目 录 一 申 报 流 程...4 二 立 项 流 程...5 三 常 见 问 题 与 处 理...6 (1). 如 何 注 册...6 (2). 系 统 中 没 有 我 的 单 位 怎 么 办?...7 (3). 在 注 册 时 写 错 身 份 证 号 名 字 而 系 统 中 不 能 修 改 怎 么 办?...

More information

目 录 办 公 OA 介 绍... 3 办 公 OA... 4 一. 收 件 箱 发 布 信 件 查 看 个 人 信 件... 7 二. 公 共 留 言 发 布 公 共 留 言 查 看 公 共 留 言... 9 三. 校 长 荐

目 录 办 公 OA 介 绍... 3 办 公 OA... 4 一. 收 件 箱 发 布 信 件 查 看 个 人 信 件... 7 二. 公 共 留 言 发 布 公 共 留 言 查 看 公 共 留 言... 9 三. 校 长 荐 思 库 网 Centricity2 目 录 办 公 OA 介 绍... 3 办 公 OA... 4 一. 收 件 箱... 4 1.1 发 布 信 件... 4 1.2 查 看 个 人 信 件... 7 二. 公 共 留 言... 8 2.1 发 布 公 共 留 言... 8 2.2 查 看 公 共 留 言... 9 三. 校 长 荐 读... 9 3.1 发 布 校 长 荐 读... 9 3.2

More information

<443A5C6D B5C30312EB9A4D7F7CEC4B5B55C30322EBACFCDACCEC4B5B55C C30342EC8CBC9E7CCFC5C31332ECFEEC4BFC5E0D1B55C E30385C322EB2D9D7F7CAD6B2E12E646F63>

<443A5C6D B5C30312EB9A4D7F7CEC4B5B55C30322EBACFCDACCEC4B5B55C C30342EC8CBC9E7CCFC5C31332ECFEEC4BFC5E0D1B55C E30385C322EB2D9D7F7CAD6B2E12E646F63> 浙 江 职 业 能 力 建 设 信 息 系 统 职 业 技 能 鉴 定 考 务 管 理 用 户 操 作 手 册 二 〇 一 五 年 八 月 目 录 0. 系 统 概 述...3 0.0. 简 要 概 述...3 0.1. 业 务 流 程 图... 3 1. 考 生 网 上 报 名... 3 1.0. 考 生 用 户 注 册 登 录... 5 1.1. 报 名 及 下 载 打 印 报 名 申 请 表...7

More information

Cybozu Garoon 3 管理员手册

Cybozu Garoon 3 管理员手册 附 录 D 数 据 的 输 入 样 式 数 据 的 种 类 和 输 入 字 符 的 值 等, 在 Garoon3 的 页 面 输 入 的 数 据 样 式 如 下 所 示 基 本 系 统 客 户 信 息 法 人 姓 名 字 符 串 ( 00 法 人 姓 名 ( 拼 音 ) 字 符 串 ( 00 图 标 (URL) 字 符 串 ( 255 应 用 程 序 新 名 称 字 符 串 ( 00 用 户 姓 名

More information

Template BR_Rec_2005.dot

Template BR_Rec_2005.dot ITU-R BT.1789 建 议 书 1 ITU-R BT.1789 建 议 书 在 分 组 视 频 传 输 中 利 用 传 输 误 码 信 息 重 建 接 收 视 频 的 方 法 (ITU-R 44/6 和 ITU-R 109/6 课 题 ) (2007 年 ) 范 围 本 建 议 书 对 业 务 提 供 商 重 建 接 收 视 频 的 方 法 做 了 详 细 介 绍, 以 便 利 用 传 输

More information

上海证券交易所会议纪要

上海证券交易所会议纪要 附 件 上 海 市 场 首 次 公 开 发 行 股 票 网 下 发 行 实 施 细 则 第 一 章 总 则 第 一 条 为 规 范 拟 在 上 海 证 券 交 易 所 ( 以 下 简 称 上 交 所 ) 上 市 的 公 司 首 次 公 开 发 行 股 票 网 下 发 行 业 务, 提 高 首 次 公 开 发 行 股 票 网 下 申 购 及 资 金 结 算 效 率, 根 据 证 券 发 行 与 承 销

More information

引言

引言 教 育 网 络 视 频 播 控 平 台 用 户 手 册 第 1 页 共 78 页 修 订 记 录 序 号 变 更 日 期 变 更 理 由 变 更 内 容 版 本 编 制 / 修 改 1 2015-1-5 初 稿 初 稿 1.0 代 盈 第 2 页 共 78 页 目 录 修 订 记 录... 2 目 录... 3 1. 引 言... 4 1.1 编 写 目 的... 4 1.2 项 目 背 景...

More information

金 不 少 于 800 万 元, 净 资 产 不 少 于 960 万 元 ; (3) 近 五 年 独 立 承 担 过 单 项 合 同 额 不 少 于 1000 万 元 的 智 能 化 工 程 ( 设 计 或 施 工 或 设 计 施 工 一 体 ) 不 少 于 2 项 ; (4) 近 三 年 每 年

金 不 少 于 800 万 元, 净 资 产 不 少 于 960 万 元 ; (3) 近 五 年 独 立 承 担 过 单 项 合 同 额 不 少 于 1000 万 元 的 智 能 化 工 程 ( 设 计 或 施 工 或 设 计 施 工 一 体 ) 不 少 于 2 项 ; (4) 近 三 年 每 年 工 程 设 计 与 施 工 资 质 标 准 一 总 则 建 筑 智 能 化 工 程 设 计 与 施 工 资 质 标 准 ( 一 ) 为 了 加 强 对 从 事 建 筑 智 能 化 工 程 设 计 与 施 工 企 业 的 管 理, 维 护 建 筑 市 场 秩 序, 保 证 工 程 质 量 和 安 全, 促 进 行 业 健 康 发 展, 结 合 建 筑 智 能 化 工 程 的 特 点, 制 定 本 标

More information

电信系教学大纲的基本规范

电信系教学大纲的基本规范 兰 州 大 学 信 息 科 学 与 工 程 学 院 Java 语 言 程 序 设 计 实 验 教 学 大 纲 一. 课 程 基 本 信 息 : 实 验 课 程 编 号 : 课 程 名 称 : Java 语 言 程 序 设 计 实 验 课 课 程 性 质 : 非 单 列 实 验 课 课 程 类 型 : 必 做 课 程 负 责 人 : 马 俊 等 适 用 专 业 : 计 算 机 科 学 与 技 术 专

More information

微软用户

微软用户 学 生 空 间 用 户 操 作 手 册 目 录 前 言... 2 一 登 录 学 生 空 间... 2 二 学 生 空 间 页 面... 3 三 功 能 区... 3 3.1 课 程 学 习... 5 3.2 学 务 管 理... 7 3.3 学 习 档 案... 7 3.4 资 料 管 理... 8 3.7 课 程 班 级... 11 3.8 我 要 评 价... 11 四 交 流 互 动...

More information

第 一 部 分 MagiCAD for Revit 安 装 流 程

第 一 部 分 MagiCAD for Revit 安 装 流 程 MagiCAD 软 件 安 装 流 程 MagiCAD v2015.4 for Revit 广 联 达 软 件 股 份 有 限 公 司 BIM 中 心 编 写 2015 年 06 月 第 一 部 分 MagiCAD for Revit 安 装 流 程 一 安 装 前 需 要 确 认 的 内 容 安 装 MagiCAD 程 序 之 前, 请 您 先 确 定 以 下 事 宜 1. 当 前 用 户 账 户

More information

全国教师资格认定管理信息系统

全国教师资格认定管理信息系统 操 作 说 明 一 教 师 资 格 认 定 申 请 人 1 : 1. 未 参 加 全 国 统 考 申 请 人 2.1 登 录 未 参 加 全 国 统 考 申 请 人 网 上 报 名 系 统 登 录 中 国 教 师 资 格 网 (http://www.jszg.edu.cn), 未 参 加 全 国 统 考 申 请 人 有 两 种 途 径 进 入 报 名 系 统 第 一 种 途 径 : 点 击 网 站

More information

Microsoft Word - 第7章 图表反转形态.doc

Microsoft Word - 第7章 图表反转形态.doc 第 七 章 图 表 反 转 形 态 我 们 知 道 市 场 趋 势 共 有 三 种 : 上 升 趋 势 下 降 趋 势 和 横 向 整 理 市 场 的 价 格 波 动 都 是 运 行 在 这 三 种 趋 势 中, 所 有 的 走 势 都 是 这 三 种 趋 势 的 排 列 组 合 如 图 市 场 趋 势 结 构 示 意 图 7-1 所 示 市 场 趋 势 结 构 示 意 图 7-1 图 市 场 趋

More information

2006年顺德区高中阶段学校招生录取分数线

2006年顺德区高中阶段学校招生录取分数线 2014 年 顺 德 区 高 中 阶 段 学 校 考 试 提 前 批 第 一 批 第 二 批 学 校 录 取 根 据 佛 山 市 办 提 供 的 考 生 数 据, 现 将 我 区 2014 年 高 中 阶 段 学 校 考 试 提 前 批 第 一 批 第 二 批 学 校 的 录 取 公 布 如 下 : 一 顺 德 一 中 录 取 分 第 1 志 愿, 总 分 585, 综 合 表 现 评 价 A, 考

More information

4 进 入 交 互 区 设 置 的 组 件 管 理, 在 组 件 管 理 中, 教 师 可 以 选 择 课 程 空 间 中 的 所 有 组 件, 并 通 过 点 击 启 用 或 不 启 用 选 定 组 件 在 课 程 空 间 中 的 显 示 5 进 入 工 作 室 管 理 的 工 作 室 首 页,

4 进 入 交 互 区 设 置 的 组 件 管 理, 在 组 件 管 理 中, 教 师 可 以 选 择 课 程 空 间 中 的 所 有 组 件, 并 通 过 点 击 启 用 或 不 启 用 选 定 组 件 在 课 程 空 间 中 的 显 示 5 进 入 工 作 室 管 理 的 工 作 室 首 页, 网 络 教 育 新 平 台 教 师 使 用 简 易 手 册 一 登 录 教 师 工 作 室 1 打 开 西 南 科 技 大 学 网 络 教 育 教 学 教 务 新 平 台 主 页 面 :http://www.swust.net.cn/ 2 在 主 页 面 左 边 的 登 陆 区 中, 用 户 名 和 密 码 处 分 别 输 入 自 己 的 用 户 名 ( 教 师 ID 号 ) 和 密 码 ( 初 始

More information

生产支援功能 使用说明书(IP-110 篇)

生产支援功能 使用说明书(IP-110 篇) 生 产 支 援 功 能 使 用 说 明 书 (IP-110 篇 ) 目 录!. 前 言...1 1. 概 要...1 2. 基 本 操 作 方 法...3 2-1. 信 息 模 式 和 通 常 缝 制 模 式 的 变 换...3 2-2. 信 息 模 式...4 2-3. 通 常 缝 制 模 式...5 @. 设 定 篇...6 1. 首 次 使 用 生 产 支 援 功 能 时 的 设 定 方 法...6

More information

(2015-2016-2)-0004186-04205-1 140242 信 号 与 系 统 Ⅰ 学 科 基 础 必 修 课 37 37 1 教 203 17 周 2016 年 06 月 13 日 (08:00-09:35) (2015-2016-2)-0004186-04205-1 141011

(2015-2016-2)-0004186-04205-1 140242 信 号 与 系 统 Ⅰ 学 科 基 础 必 修 课 37 37 1 教 203 17 周 2016 年 06 月 13 日 (08:00-09:35) (2015-2016-2)-0004186-04205-1 141011 关 于 2015-2016 学 年 第 二 学 期 期 末 周 内 考 试 时 间 地 点 安 排 选 课 课 号 班 级 名 称 课 程 名 称 课 程 性 质 合 考 人 数 实 际 人 数 考 试 教 室 考 试 段 考 试 时 间 (2015-2016-2)-0006178-04247-1 130101 测 试 技 术 基 础 学 科 基 础 必 修 课 35 35 1 教 401 17 周

More information

工 程 造 价 咨 询 企 业 管 理 系 统 操 作 手 册 目 录 1 造 价 企 业 登 录... 1 2 企 业 基 本 信 息 查 看... 3 3 企 业 人 员 信 息 查 看... 4 4 企 业 基 本 信 息 操 作... 5 4.1 企 业 简 介... 5 4.2 企 业 章

工 程 造 价 咨 询 企 业 管 理 系 统 操 作 手 册 目 录 1 造 价 企 业 登 录... 1 2 企 业 基 本 信 息 查 看... 3 3 企 业 人 员 信 息 查 看... 4 4 企 业 基 本 信 息 操 作... 5 4.1 企 业 简 介... 5 4.2 企 业 章 工 程 造 价 咨 询 企 业 管 理 系 统 操 作 手 册 工 程 造 价 咨 询 企 业 管 理 系 统 ( 造 价 企 业 ) 用 户 手 册 工 程 造 价 咨 询 企 业 管 理 系 统 操 作 手 册 目 录 1 造 价 企 业 登 录... 1 2 企 业 基 本 信 息 查 看... 3 3 企 业 人 员 信 息 查 看... 4 4 企 业 基 本 信 息 操 作... 5 4.1

More information

3 月 30 日 在 中 国 证 券 报 上 海 证 券 报 证 券 时 报 证 券 日 报 和 上 海 证 券 交 易 所 网 站 上 发 出 召 开 本 次 股 东 大 会 公 告, 该 公 告 中 载 明 了 召 开 股 东 大 会 的 日 期 网 络 投 票 的 方 式 时 间 以 及 审

3 月 30 日 在 中 国 证 券 报 上 海 证 券 报 证 券 时 报 证 券 日 报 和 上 海 证 券 交 易 所 网 站 上 发 出 召 开 本 次 股 东 大 会 公 告, 该 公 告 中 载 明 了 召 开 股 东 大 会 的 日 期 网 络 投 票 的 方 式 时 间 以 及 审 北 京 市 君 致 律 师 事 务 所 关 于 浪 潮 软 件 股 份 有 限 公 司 2015 年 度 股 东 大 会 的 法 律 意 见 书 致 : 浪 潮 软 件 股 份 有 限 公 司 北 京 市 君 致 律 师 事 务 所 ( 以 下 简 称 本 所 ) 受 浪 潮 软 件 股 份 有 限 公 司 ( 以 下 简 称 公 司 ) 的 委 托, 指 派 律 师 出 席 2016 年 4 月

More information

Microsoft Word - 文件汇编.doc

Microsoft Word - 文件汇编.doc 北 京 市 中 医 管 理 局 二 一 五 年 四 月 ... 1... 18 2015... 30 京 中 医 政 字 [2014]160 号 1 2 一 充 分 认 识 中 医 健 康 乡 村 建 设 工 作 的 重 要 意 义 二 建 立 健 全 工 作 保 障 机 制 2014 12 15 三 做 好 工 作 启 动 的 准 备 事 宜 1 2014 12 15 5-10 2014 12 15

More information

龚 亚 夫 在 重 新 思 考 基 础 教 育 英 语 教 学 的 理 念 一 文 中 援 引 的 观 点 认 为 当 跳 出 本 族 语 主 义 的 思 维 定 式 后 需 要 重 新 思 考 许 多 相 连 带 的 问 题 比 如 许 多 发 音 的 细 微 区 别 并 不 影 响 理 解 和

龚 亚 夫 在 重 新 思 考 基 础 教 育 英 语 教 学 的 理 念 一 文 中 援 引 的 观 点 认 为 当 跳 出 本 族 语 主 义 的 思 维 定 式 后 需 要 重 新 思 考 许 多 相 连 带 的 问 题 比 如 许 多 发 音 的 细 微 区 别 并 不 影 响 理 解 和 语 音 语 篇 语 感 语 域 林 大 津 毛 浩 然 改 革 开 放 以 来 的 英 语 热 引 发 了 大 中 小 学 英 语 教 育 整 体 规 划 问 题 在 充 分 考 虑 地 区 学 校 和 个 体 差 异 以 及 各 家 观 点 的 基 础 上 遵 循 实 事 求 是 逐 级 定 位 逐 层 分 流 因 材 施 教 的 原 则 本 研 究 所 倡 导 的 语 音 语 篇 语 感 语 域

More information

<4D F736F F D D323630D6D0B9FAD3A6B6D4C6F8BAF2B1E4BBAFB5C4D5FEB2DFD3EBD0D0B6AF C4EAB6C8B1A8B8E6>

<4D F736F F D D323630D6D0B9FAD3A6B6D4C6F8BAF2B1E4BBAFB5C4D5FEB2DFD3EBD0D0B6AF C4EAB6C8B1A8B8E6> 中 国 应 对 气 候 变 化 的 政 策 与 行 动 2013 年 度 报 告 国 家 发 展 和 改 革 委 员 会 二 〇 一 三 年 十 一 月 100% 再 生 纸 资 源 目 录 前 言... 1 一 应 对 气 候 变 化 面 临 的 形 势... 3 二 完 善 顶 层 设 计 和 体 制 机 制... 4 三 减 缓 气 候 变 化... 8 四 适 应 气 候 变 化... 20

More information

全国建筑市场注册执业人员不良行为记录认定标准(试行).doc

全国建筑市场注册执业人员不良行为记录认定标准(试行).doc - 1 - - 2 - 附 件 全 国 建 筑 市 场 注 册 执 业 人 员 不 良 记 录 认 定 标 准 ( 试 行 ) 说 明 为 了 完 善 建 筑 市 场 注 册 执 业 人 员 诚 信 体 系 建 设, 规 范 执 业 和 市 场 秩 序, 依 据 相 关 法 律 法 规 和 部 门 规 章, 根 据 各 行 业 特 点, 我 部 制 订 了 全 国 建 筑 市 场 注 册 执 业 人

More information

一 公 共 卫 生 硕 士 专 业 学 位 论 文 的 概 述 学 位 论 文 是 对 研 究 生 进 行 科 学 研 究 或 承 担 专 门 技 术 工 作 的 全 面 训 练, 是 培 养 研 究 生 创 新 能 力, 综 合 运 用 所 学 知 识 发 现 问 题, 分 析 问 题 和 解 决

一 公 共 卫 生 硕 士 专 业 学 位 论 文 的 概 述 学 位 论 文 是 对 研 究 生 进 行 科 学 研 究 或 承 担 专 门 技 术 工 作 的 全 面 训 练, 是 培 养 研 究 生 创 新 能 力, 综 合 运 用 所 学 知 识 发 现 问 题, 分 析 问 题 和 解 决 上 海 市 公 共 卫 生 硕 士 专 业 学 位 论 文 基 本 要 求 和 评 价 指 标 体 系 ( 试 行 ) 上 海 市 学 位 委 员 会 办 公 室 二 O 一 二 年 三 月 一 公 共 卫 生 硕 士 专 业 学 位 论 文 的 概 述 学 位 论 文 是 对 研 究 生 进 行 科 学 研 究 或 承 担 专 门 技 术 工 作 的 全 面 训 练, 是 培 养 研 究 生 创

More information

抗 战 时 期 国 民 政 府 的 银 行 监 理 体 制 探 析 % # % % % ) % % # # + #, ) +, % % % % % % % %

抗 战 时 期 国 民 政 府 的 银 行 监 理 体 制 探 析 % # % % % ) % % # # + #, ) +, % % % % % % % % 抗 战 时 期 国 民 政 府 的 银 行 监 理 体 制 探 析 王 红 曼 抗 战 时 期 国 民 政 府 为 适 应 战 时 经 济 金 融 的 需 要 实 行 由 财 政 部 四 联 总 处 中 央 银 行 等 多 家 机 构 先 后 共 同 参 与 的 多 元 化 银 行 监 理 体 制 对 战 时 状 态 下 的 银 行 发 展 与 经 营 安 全 进 行 了 大 规 模 的 设 计 与

More information

ETF、分级基金规模、份额变化统计20130816

ETF、分级基金规模、份额变化统计20130816 ETF 分 级 基 金 规 模 份 额 变 化 统 计 截 至 上 周 末, 全 市 场 股 票 型 ETF 规 模 约 1451 亿, 份 额 约 1215 亿,ETF 总 份 额 及 规 模 的 周 变 动 值 分 别 为 -23-44 亿, 份 额 与 规 模 均 下 降 ; 分 级 基 金 规 模 约 438 亿, 份 额 572 亿, 总 份 额 及 规 模 的 周 变 动 值 分 别 为

More information

目 录 第 一 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 硬 件 使 用 介 绍... 3 第 二 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 管 理 员 端 功 能 使 用 介 绍... 4 2.1 系 统 管 理 员 登 陆... 4 2.2 班

目 录 第 一 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 硬 件 使 用 介 绍... 3 第 二 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 管 理 员 端 功 能 使 用 介 绍... 4 2.1 系 统 管 理 员 登 陆... 4 2.2 班 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 使 用 说 明 书 制 作 : 北 京 博 导 前 程 信 息 技 术 有 限 公 司 目 录 第 一 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 硬 件 使 用 介 绍... 3 第 二 章 博 星 卓 越 电 子 商 务 营 销 策 划 实 践 平 台 管 理 员 端 功 能 使 用 介 绍... 4 2.1

More information

操作手册

操作手册 企 业 网 上 银 行 使 用 手 册 ( 智 信 版 ) 中 国 农 业 银 行 股 份 有 限 公 司 重 庆 市 分 行 目 录 使 用 网 上 银 行 前 务 必 了 解 的 信 息... 3 1. 基 本 功 能... 3 2. 网 银 操 作 员... 3 3. 登 录 方 式... 3 4. 特 别 提 醒... 3 快 速 使 用 指 南... 4 1. 注 册 用 户... 4 2.

More information

1600 1000 40 50 2030 2000 采 取 行 动 的 机 会 90% 开 拓 成 功 的 道 路 2

1600 1000 40 50 2030 2000 采 取 行 动 的 机 会 90% 开 拓 成 功 的 道 路 2 简 略 版 本 :2015 3 10 2016 2021 全 球 卫 生 部 门 病 毒 性 肝 炎 战 略 2016 2021 2015 3 12 2012 2010 2014 2015 2016 2021 140 55% 35% 5 15% 5 20% 2.4 1.3 1.5 1 1600 1000 40 50 2030 2000 采 取 行 动 的 机 会 90% 开 拓 成 功 的 道 路

More information

 编号:

 编号: 编 号 : 企 业 内 高 技 能 人 才 培 养 评 价 实 施 方 案 ( 仅 适 用 于 企 业 特 有 行 业 特 有 工 种 ) 实 施 单 位 ( 公 章 ) 申 报 日 期 年 _ 月 日 1 企 业 内 高 技 能 人 才 培 养 评 价 项 目 实 施 方 案 申 报 表 项 目 名 称 等 级 项 目 性 质 课 时 申 报 单 位 联 系 人 通 讯 地 址 电 话 手 机 电

More information

联想电子订单操作指南

联想电子订单操作指南 天 威 诚 信 比 亚 迪 数 字 证 书 下 载 及 使 用 手 册 天 威 诚 信 数 字 认 证 中 心 itruschina Co., Ltd 第 1 页 共 14 页 1 概 述 是 经 信 息 产 业 部 批 准 的 全 国 性 PKI/CA 企 业, 是 专 门 从 事 数 字 信 任 服 务 PKI/CA 建 设 服 务 PKI/CA 应 用 服 务 PKI/CA 运 营 管 理 咨

More information

上证指数

上证指数 上 证 与 修 正 方 法 一 ( 一 ) 计 算 公 式 1. 上 证 指 数 系 列 均 采 用 派 许 加 权 综 合 价 格 指 数 公 式 计 算 2. 上 证 180 指 数 上 证 50 指 数 等 以 成 份 股 的 调 整 股 本 数 为 权 数 进 行 加 权 计 算, 计 算 公 式 为 : 报 告 期 指 数 =( 报 告 期 样 本 股 的 调 整 市 值 / 基 期 )

More information

目 录 页 1. 欢 迎 使 用 网 上 预 约 面 谈 访 问 系 统... 3 2. 新 用 户... 4 2.1 新 用 户 登 入 帐 户 程 序... 4 2.2 启 动 网 上 预 约 面 谈 访 问 帐 户... 5 2.2.1 核 对 帐 户 的 地 址 资 料... 5 2.2.2

目 录 页 1. 欢 迎 使 用 网 上 预 约 面 谈 访 问 系 统... 3 2. 新 用 户... 4 2.1 新 用 户 登 入 帐 户 程 序... 4 2.2 启 动 网 上 预 约 面 谈 访 问 帐 户... 5 2.2.1 核 对 帐 户 的 地 址 资 料... 5 2.2.2 网 上 预 约 面 谈 访 问 使 用 指 南 香 港 特 别 行 政 区 政 府 统 计 处 目 录 页 1. 欢 迎 使 用 网 上 预 约 面 谈 访 问 系 统... 3 2. 新 用 户... 4 2.1 新 用 户 登 入 帐 户 程 序... 4 2.2 启 动 网 上 预 约 面 谈 访 问 帐 户... 5 2.2.1 核 对 帐 户 的 地 址 资 料... 5 2.2.2 阅

More information

目 录 版 本 更 新 说 明... 3 1 导 读... 4 1.1 读 者 对 象... 4 1.2 手 册 内 容 简 介... 4 1.3 软 件 简 介... 4 1.4 基 本 术 语... 5 1.5 技 术 支 持... 6 2 基 本 流 程... 6 3 操 作 步 骤... 8

目 录 版 本 更 新 说 明... 3 1 导 读... 4 1.1 读 者 对 象... 4 1.2 手 册 内 容 简 介... 4 1.3 软 件 简 介... 4 1.4 基 本 术 语... 5 1.5 技 术 支 持... 6 2 基 本 流 程... 6 3 操 作 步 骤... 8 地 质 调 查 项 目 统 计 信 息 子 系 统 用 户 手 册 V2.0(2016 简 明 版 ) 技 术 支 持 : 中 国 地 质 调 查 局 发 展 研 究 中 心 http://www.drc.cgs.gov.cn 资 料 版 本 :DRC-CGSTJ-20160619 1 目 录 版 本 更 新 说 明... 3 1 导 读... 4 1.1 读 者 对 象... 4 1.2 手 册

More information

øÕªß∂À≤Ÿ◊˜ ÷≤·

øÕªß∂À≤Ÿ◊˜ ÷≤· 用 户 使 用 手 册 ( 版 本 号 :4.0) 目 录 第 一 章 软 件 安 装... 1 第 二 章 软 件 的 运 行... 4 第 三 章 新 建 文 档... 7 3.1 第 一 部 分 简 表... 7 3.1.1 基 本 信 息... 7 3.1.2 从 事 专 业 关 键 词... 8 3.1.3 教 育 经 历... 8 3.1.4 工 作 经 历... 9 3.1.5 教 育

More information

一、资质申请

一、资质申请 二 工 程 监 理 企 业 资 质 有 关 问 答 111 什 么 样 的 企 业 可 以 在 本 省 申 请 工 程 监 理 企 业 资 质? 答 : 在 鄂 取 得 法 人 营 业 执 照 或 合 伙 企 业 营 业 执 照 的 企 业, 都 可 依 法 向 工 商 注 册 所 在 省 或 市 建 设 行 政 主 管 部 门 行 政 审 批 部 门 申 请 工 程 监 理 企 业 资 质 取 得

More information

珠江钢琴股东大会

珠江钢琴股东大会 证 券 代 码 :002678 证 券 简 称 : 珠 江 钢 琴 公 告 编 号 :2015-038 广 州 珠 江 钢 琴 集 团 股 份 有 限 公 司 2015 年 年 度 股 东 大 会 决 议 公 告 本 公 司 及 董 事 会 全 体 成 员 保 证 信 息 披 露 的 内 容 真 实 准 确 完 整, 没 有 虚 假 记 载 误 导 性 陈 述 或 重 大 遗 漏 特 别 提 示 :

More information

<4D6963726F736F667420576F7264202D20B3D6B2D6CFDEB6EEB1EDB8F1D7EED6D52E646F63>

<4D6963726F736F667420576F7264202D20B3D6B2D6CFDEB6EEB1EDB8F1D7EED6D52E646F63> 国 内 各 期 货 交 易 所 关 于 合 约 限 仓 方 面 的 规 定 上 海 期 货 交 易 所 经 纪 会 员 非 经 纪 会 员 和 客 户 的 期 货 合 约 在 不 同 时 期 限 仓 的 具 体 比 例 和 数 额 如 下 : ( 单 位 : ) 合 约 挂 牌 至 交 割 月 前 第 二 月 的 最 后 一 个 交 易 日 交 割 月 前 第 一 月 交 割 月 份 某 一 期 货

More information

Excel basics

Excel basics Excel 基 础 知 识 Excel 是 功 能 强 大 的 电 子 表 格 和 数 据 分 析 应 用 程 序, 然 而 若 要 最 有 效 地 使 用 它, 必 须 首 先 了 解 这 些 基 础 知 识 本 教 程 介 绍 一 些 可 以 在 所 有 工 作 薄 中 使 用 的 任 务 和 功 能 开 设 之 前... 1 1. 创 建 新 空 白 工 作 薄... 2 2. 浏 览 Excel

More information

<4D6963726F736F667420576F7264202D20B9D8D3DAB0BABBAAA3A8C9CFBAA3A3A9D7D4B6AFBBAFB9A4B3CCB9C9B7DDD3D0CFDEB9ABCBBE32303132C4EAC4EAB6C8B9C9B6ABB4F3BBE1B7A8C2C9D2E2BCFBCAE92E646F6378>

<4D6963726F736F667420576F7264202D20B9D8D3DAB0BABBAAA3A8C9CFBAA3A3A9D7D4B6AFBBAFB9A4B3CCB9C9B7DDD3D0CFDEB9ABCBBE32303132C4EAC4EAB6C8B9C9B6ABB4F3BBE1B7A8C2C9D2E2BCFBCAE92E646F6378> 上 海 德 载 中 怡 律 师 事 务 所 关 于 昂 华 ( 上 海 ) 自 动 化 工 程 股 份 有 限 公 司 二 〇 一 二 年 年 度 股 东 大 会 法 律 意 见 书 上 海 德 载 中 怡 律 师 事 务 所 上 海 市 银 城 中 路 168 号 上 海 银 行 大 厦 1705 室 (200120) 电 话 :8621-5012 2258 传 真 :8621-5012 2257

More information

i 1) 系 统 运 作 前 设 定 *1. [2.1 网 页 主 机 名 称 设 定 ] -- 设 定 校 务 系 统 的 主 机 IP 地 址, 以 供 其 他 个 人 电 脑 连 接 及 使 用 该 系 统 *2. [2.3.1 输 入 / 修 改 学 校 资 料 ] -- 输 入 系 统 使

i 1) 系 统 运 作 前 设 定 *1. [2.1 网 页 主 机 名 称 设 定 ] -- 设 定 校 务 系 统 的 主 机 IP 地 址, 以 供 其 他 个 人 电 脑 连 接 及 使 用 该 系 统 *2. [2.3.1 输 入 / 修 改 学 校 资 料 ] -- 输 入 系 统 使 校 务 系 统 使 用 步 骤 说 明 手 册 简 介 此 手 册 是 配 合 校 务 系 统 使 用 手 册 编 辑 的, 因 此 必 须 同 时 参 考 校 务 系 统 使 用 手 册, 以 获 知 更 详 细 的 使 用 说 明 此 手 册 主 要 记 载 几 项 较 为 复 杂 事 务 的 处 理 步 骤 及 说 明, 以 让 使 用 者 更 容 易 掌 握 及 使 用 校 务 系 统 其

More information

2. 本 次 修 改 后, 投 资 者 申 购 新 股 的 持 有 市 值 要 求 市 值 计 算 规 则 及 证 券 账 户 使 用 的 相 关 规 定 是 否 发 生 了 变 化? 答 : 未 发 生 变 化 投 资 者 申 购 新 股 的 持 有 市 值 是 指, 以 投 资 者 为 单 位

2. 本 次 修 改 后, 投 资 者 申 购 新 股 的 持 有 市 值 要 求 市 值 计 算 规 则 及 证 券 账 户 使 用 的 相 关 规 定 是 否 发 生 了 变 化? 答 : 未 发 生 变 化 投 资 者 申 购 新 股 的 持 有 市 值 是 指, 以 投 资 者 为 单 位 新 股 网 上 网 下 发 行 实 施 细 则 问 答 上 交 所 2016-01-05 一 网 上 发 行 业 务 问 答 1. 本 次 修 改 的 主 要 内 容 是 什 么? 答 : 本 次 修 改 的 主 要 内 容 包 括 : 一 是 取 消 了 投 资 者 在 申 购 委 托 时 应 全 额 缴 纳 申 购 资 金 的 规 定, 明 确 了 投 资 者 应 根 据 最 终 确 定 的 发

More information

目 录 一 激 活 账 号... 2 二 忘 记 密 码 后 如 何 找 回 密 码?... 3 三 如 何 管 理 学 校 信 息 及 球 队 学 生 教 师 等 信 息... 6 四 如 何 发 布 本 校 校 园 文 化?... 11 五 如 何 向 教 师 发 送 通 知?... 13 六

目 录 一 激 活 账 号... 2 二 忘 记 密 码 后 如 何 找 回 密 码?... 3 三 如 何 管 理 学 校 信 息 及 球 队 学 生 教 师 等 信 息... 6 四 如 何 发 布 本 校 校 园 文 化?... 11 五 如 何 向 教 师 发 送 通 知?... 13 六 一 刻 校 园 足 球 管 理 平 台 使 用 说 明 ( 学 校 管 理 员 版 ) 一 刻 软 件 科 技 有 限 公 司 目 录 一 激 活 账 号... 2 二 忘 记 密 码 后 如 何 找 回 密 码?... 3 三 如 何 管 理 学 校 信 息 及 球 队 学 生 教 师 等 信 息... 6 四 如 何 发 布 本 校 校 园 文 化?... 11 五 如 何 向 教 师 发 送

More information

标题

标题 甘 肃 政 务 服 务 网 三 张 清 单 录 入 审 核 发 布 人 员 操 作 手 册 甘 肃 省 人 民 政 府 办 公 厅 2015 年 6 月 目 录 三 张 清 单 录 入 审 核 发 布 总 体 介 绍 3 页 权 责 清 单 信 息 录 入 初 审 终 审 和 发 布 16 页 公 共 服 务 事 项 信 息 录 入 初 审 终 审 和 发 布 38 页 省 政 府 共 性 权 责

More information

证券代码:000066 证券简称:长城电脑 公告编号:2014-000

证券代码:000066         证券简称:长城电脑        公告编号:2014-000 证 券 代 码 :000066 证 券 简 称 : 长 城 电 脑 公 告 编 号 :2016-092 中 国 长 城 计 算 机 深 圳 股 份 有 限 公 司 2016 年 度 第 三 次 临 时 股 东 大 会 决 议 公 告 本 公 司 及 其 董 事 会 全 体 成 员 保 证 信 息 披 露 内 容 的 真 实 准 确 完 整, 没 有 虚 假 记 载 误 导 性 陈 述 或 重 大 遗

More information

关于修订《沪市股票上网发行资金申购

关于修订《沪市股票上网发行资金申购 关 于 修 订 沪 市 股 票 上 网 发 行 资 金 申 购 实 施 办 法 的 通 知 各 有 关 单 位 : 沪 市 股 票 上 网 发 行 资 金 申 购 实 施 办 法 ( 修 订 稿 ) ( 见 附 件 ) 已 经 中 国 证 券 监 督 管 理 委 员 会 批 准, 现 将 修 订 所 涉 主 要 内 容 公 布 如 下 一 第 二 条 ( 二 ) 申 购 单 位 及 上 限 修 改

More information

三门峡市质量技术监督局清单公示

三门峡市质量技术监督局清单公示 附 件 4 卢 氏 县 财 政 局 行 政 职 权 运 行 流 程 图 一 行 政 处 罚 类 1. 第 1 项 一 般 程 序 流 程 图 案 件 来 源 初 步 确 认 违 法 事 实, 责 令 停 止 违 法 行 为 县 财 政 局 立 案 审 批 综 合 股 登 记 立 案 调 查 取 证 不 予 立 案 综 合 股 撰 写 调 查 终 结 报 告 移 送 有 关 部 门 综 合 股 提 出

More information

反 学 校 文 化 与 阶 级 再 生 产 小 子 与 子 弟 之 比 较 周 潇 作 者 通 过 对 北 京 某 打 工 子 弟 学 校 的 田 野 调 查 后 发 现 在 农 民 工 子 弟 中 间 盛 行 着 类 似 学 做 工 中 所 描 述 的 工 人 阶 级 小 子 的 反 学 校 文 化 但 是 由 于 制 度 安 排 与 社 会 条 件 的 差 异 子 弟 与 小 子 的 反 学 校

More information

合 并 计 算 配 售 对 象 持 有 多 个 证 券 账 户 的, 多 个 证 券 账 户 市 值 合 并 计 算 确 认 多 个 证 券 账 户 为 同 一 配 售 对 象 持 有 的 原 则 为 证 券 账 户 注 册 资 料 中 的 账 户 持 有 人 名 称 有 效 身 份 证 明 文 件

合 并 计 算 配 售 对 象 持 有 多 个 证 券 账 户 的, 多 个 证 券 账 户 市 值 合 并 计 算 确 认 多 个 证 券 账 户 为 同 一 配 售 对 象 持 有 的 原 则 为 证 券 账 户 注 册 资 料 中 的 账 户 持 有 人 名 称 有 效 身 份 证 明 文 件 深 圳 市 场 首 次 公 开 发 行 股 票 网 下 发 行 实 施 细 则 ( 征 求 意 见 稿 ) 第 一 章 总 则 第 一 条 为 规 范 深 圳 市 场 首 次 公 开 发 行 股 票 网 下 发 行 行 为, 根 据 证 券 发 行 与 承 销 管 理 办 法 及 相 关 规 定, 制 定 本 细 则 第 二 条 本 细 则 所 称 网 下 发 行 是 指 首 次 公 开 发 行 股

More information

定 位 和 描 述 : 程 序 设 计 / 办 公 软 件 高 级 应 用 级 考 核 内 容 包 括 计 算 机 语 言 与 基 础 程 序 设 计 能 力, 要 求 参 试 者 掌 握 一 门 计 算 机 语 言, 可 选 类 别 有 高 级 语 言 程 序 设 计 类 数 据 库 编 程 类

定 位 和 描 述 : 程 序 设 计 / 办 公 软 件 高 级 应 用 级 考 核 内 容 包 括 计 算 机 语 言 与 基 础 程 序 设 计 能 力, 要 求 参 试 者 掌 握 一 门 计 算 机 语 言, 可 选 类 别 有 高 级 语 言 程 序 设 计 类 数 据 库 编 程 类 全 国 计 算 机 等 级 考 试 调 整 方 案 2011 年 7 月, 教 育 部 考 试 中 心 组 织 召 开 了 第 五 届 全 国 计 算 机 等 级 考 试 (NCRE) 考 委 会 会 议, 会 议 完 成 NCRE 考 委 会 换 届 选 举, 并 确 定 了 下 一 步 改 革 和 发 展 的 目 标 在 新 的 历 史 时 期,NCRE 将 以 保 持 稳 定 为 前 提 以

More information

科 学 出 版 社 科 学 出 版 社 前 言 本 书 是 针 对 普 通 高 等 院 校 经 济 类 和 工 商 管 理 类 本 科 专 业 财 务 管 理 学 的 教 学 需 求, 结 合 教 育 部 经 济 管 理 类 本 科 财 务 管 理 学 课 程 教 学 大 纲 编 写 而 成 的 本 书 执 笔 者 都 是 长 期 工 作 在 财 务 管 理 教 学 一 线 的 专 业 教 师,

More information

中 国 软 科 学 年 第 期!!!

中 国 软 科 学 年 第 期!!! 山 寨 模 式 的 形 成 机 理 及 其 对 组 织 创 新 的 启 示 山 寨 模 式 的 形 成 机 理 及 其 对 组 织 创 新 的 启 示 陶 厚 永 李 燕 萍 骆 振 心 武 汉 大 学 经 济 与 管 理 学 院 武 汉 大 学 中 国 产 学 研 合 作 问 题 研 究 中 心 湖 北 武 汉 北 京 大 学 经 济 研 究 所 光 华 天 成 博 士 后 工 作 站 北 京 本

More information

系统设计文档_样稿管理模块 V1.1_.doc

系统设计文档_样稿管理模块 V1.1_.doc 系 统 设 计 文 档 生 产 资 料 管 理 系 统 (Production Material Management System, PMMS) 样 稿 ( 样 件 ) 管 理 模 块 ( 第 1 期 ) 文 档 版 本 :1.1 文 档 日 期 : 2012-08-30 文 档 作 者 : 曾 勇 松 其 它 参 与 人 : 第 1 页 / 共 16 页 文 档 修 订 记 录 修 订 记 录

More information

·岗位设置管理流程

·岗位设置管理流程 实 施 岗 位 设 置 岗 位 设 置 编 码 受 控 状 态 执 行 心 门 行 政 人 力 资 控 制 门 总 经 办 源 各 职 能 门 行 政 人 力 资 源 总 经 办 总 经 理 根 据 公 司 发 展 战 略 进 行 职 能 分 解 和 机 构 设 置 工 作 分 析 根 据 人 力 资 源 规 划 确 定 编 制 意 见 职 责 划 分 与 岗 位 设 置 制 作 职 务 说 明 书

More information

导 数 和 微 分 的 概 念 导 数 的 几 何 意 义 和 物 理 意 义 函 数 的 可 导 性 与 连 续 性 之 间 的 关 系 平 面 曲 线 的 切 线 和 法 线 导 数 和 微 分 的 四 则 运 算 基 本 初 等 函 数 的 导 数 复 合 函 数 反 函 数 隐 函 数 以

导 数 和 微 分 的 概 念 导 数 的 几 何 意 义 和 物 理 意 义 函 数 的 可 导 性 与 连 续 性 之 间 的 关 系 平 面 曲 线 的 切 线 和 法 线 导 数 和 微 分 的 四 则 运 算 基 本 初 等 函 数 的 导 数 复 合 函 数 反 函 数 隐 函 数 以 2015 年 考 研 数 学 二 考 试 大 纲 考 试 科 目 : 高 等 数 学 线 性 代 数 考 试 形 式 和 试 卷 结 构 一 试 卷 满 分 及 考 试 时 间 试 卷 满 分 为 150 分, 考 试 时 间 为 180 分 钟. 二 答 题 方 式 答 题 方 式 为 闭 卷 笔 试. 三 试 卷 内 容 结 构 高 等 教 学 约 78% 线 性 代 数 约 22% 四 试 卷

More information

工 程 勘 察 资 质 标 准 根 据 建 设 工 程 勘 察 设 计 管 理 条 例 和 建 设 工 程 勘 察 设 计 资 质 管 理 规 定, 制 定 本 标 准 一 总 则 ( 一 ) 本 标 准 包 括 工 程 勘 察 相 应 专 业 类 型 主 要 专 业 技 术 人 员 配 备 技 术

工 程 勘 察 资 质 标 准 根 据 建 设 工 程 勘 察 设 计 管 理 条 例 和 建 设 工 程 勘 察 设 计 资 质 管 理 规 定, 制 定 本 标 准 一 总 则 ( 一 ) 本 标 准 包 括 工 程 勘 察 相 应 专 业 类 型 主 要 专 业 技 术 人 员 配 备 技 术 住 房 和 城 乡 建 设 部 关 于 印 发 工 程 勘 察 资 质 标 准 的 通 知 建 市 [2013]9 号 各 省 自 治 区 住 房 和 城 乡 建 设 厅, 北 京 市 规 划 委, 天 津 上 海 市 建 设 交 通 委, 重 庆 市 城 乡 建 设 委, 新 疆 生 产 建 设 兵 团 建 设 局, 总 后 基 建 营 房 部 工 程 局, 国 务 院 有 关 部 门 建 设 司,

More information

第3章 创建数据库

第3章 创建数据库 第 3 章 创 建 数 据 库 要 点 3.1 Access 2002 开 发 环 境 3.2 数 据 库 的 创 建 3.3 创 建 表 3.4 字 段 操 作 3.5 设 定 表 关 系 3.6 操 作 记 录 3.7 数 据 的 导 入 和 导 出 3.1 Access 2002 开 发 环 境 Access 与 许 多 常 用 的 数 据 库 管 理 系 统, 如 Access 常 用 的

More information

正 规 培 训 达 规 定 标 准 学 时 数, 并 取 得 结 业 证 书 二 级 可 编 程 师 ( 具 备 以 下 条 件 之 一 者 ) (1) 连 续 从 事 本 职 业 工 作 13 年 以 上 (2) 取 得 本 职 业 三 级 职 业 资 格 证 书 后, 连 续 从 事 本 职 业

正 规 培 训 达 规 定 标 准 学 时 数, 并 取 得 结 业 证 书 二 级 可 编 程 师 ( 具 备 以 下 条 件 之 一 者 ) (1) 连 续 从 事 本 职 业 工 作 13 年 以 上 (2) 取 得 本 职 业 三 级 职 业 资 格 证 书 后, 连 续 从 事 本 职 业 1. 职 业 概 况 1.1 职 业 名 称 可 编 程 师 1.2 职 业 定 义 可 编 程 师 国 家 职 业 标 准 从 事 可 编 程 序 控 制 器 (PLC) 选 型 编 程, 并 对 应 用 进 行 集 成 和 运 行 管 理 的 人 员 1.3 职 业 等 级 本 职 业 共 设 四 个 等 级, 分 别 为 : 四 级 可 编 程 师 ( 国 家 职 业 资 格 四 级 ) 三

More information

上海证券交易所会议纪要

上海证券交易所会议纪要 附 件 上 海 市 场 首 次 公 开 发 行 股 票 网 上 发 行 实 施 细 则 第 一 章 总 则 第 一 条 为 规 范 上 海 市 场 首 次 公 开 发 行 股 票 网 上 发 行 行 为, 根 据 证 券 发 行 与 承 销 管 理 办 法 及 相 关 规 定, 制 定 本 细 则 第 二 条 通 过 上 海 证 券 交 易 所 ( 以 下 简 称 上 交 所 ) 交 易 系 统 并

More information

马 克 思 主 义 公 正 观 的 基 本 向 度 及 方 法 论 原 则!! # #

马 克 思 主 义 公 正 观 的 基 本 向 度 及 方 法 论 原 则!! # # 马 克 思 主 义 公 正 观 的 基 本 向 度 及 方 法 论 原 则 马 俊 峰 在 社 会 公 正 问 题 的 大 讨 论 中 罗 尔 斯 诺 齐 克 哈 耶 克 麦 金 泰 尔 等 当 代 西 方 思 想 家 的 论 述 被 反 复 引 用 和 申 说 而 将 马 克 思 恩 格 斯 等 经 典 作 家 的 观 点 置 于 一 种 被 忽 视 甚 至 被 忘 却 的 状 态 形 成 这 种

More information

收 入 支 出 项 目 2016 年 预 算 项 目 2016 年 预 算 预 算 01 表 单 位 : 万 元 ( 保 留 两 位 小 数 ) 一 公 共 财 政 预 算 拨 款 50.06 一 人 员 经 费 23.59 1 一 般 财 力 50.06 1 人 员 支 出 21.95 2 成 品

收 入 支 出 项 目 2016 年 预 算 项 目 2016 年 预 算 预 算 01 表 单 位 : 万 元 ( 保 留 两 位 小 数 ) 一 公 共 财 政 预 算 拨 款 50.06 一 人 员 经 费 23.59 1 一 般 财 力 50.06 1 人 员 支 出 21.95 2 成 品 100.12 2016 年 龙 岩 市 部 门 预 算 表 报 送 日 期 : 年 月 日 单 位 负 责 人 签 章 : 财 务 负 责 人 签 章 : 制 表 人 签 章 : 收 入 支 出 项 目 2016 年 预 算 项 目 2016 年 预 算 预 算 01 表 单 位 : 万 元 ( 保 留 两 位 小 数 ) 一 公 共 财 政 预 算 拨 款 50.06 一 人 员 经 费 23.59

More information

moza_ctc_64021.pdf

moza_ctc_64021.pdf 访 问 CTC 的 多 个 Java 插 件 安 装 目 录 简 介 先 决 条 件 要 求 使 用 的 组 件 规 则 背 景 信 息 多 Java 插 件 版 本 浏 览 器 信 息 Mozilla 安 装 Java 插 件 安 装 与 ONS15454 和 15327 的 JRE 兼 容 性 J2SE JRE 设 置 J2SE JRE 版 本 2 J2SE JRE 版 本 3.1 J2SE JRE

More information

四川省农村义务教育学生

四川省农村义务教育学生 四 川 省 农 村 义 务 教 育 学 生 营 养 改 善 计 划 协 调 小 组 办 公 室 川 学 生 营 养 办 函 2015 7 号 关 于 填 报 2015 年 农 村 义 务 教 育 学 生 营 养 改 善 计 划 受 益 学 生 数 据 的 通 知 各 相 关 市 ( 州 ) 学 生 营 养 办 : 为 了 贯 彻 落 实 国 务 院 办 公 厅 关 于 实 施 农 村 义 务 教 育

More information

Microsoft Word - Disclose.doc

Microsoft Word - Disclose.doc 三 甲 金 融 委 托 终 端 港 股 使 用 说 明 - 1 - 1. 基 本 功 能 介 绍 1.1 登 录 界 面 简 介 1.1.1 登 录 模 式 (1) 嵌 入 行 情 软 件 中 运 行 模 式 : 点 击 大 智 慧 行 情 软 件 顶 端 的 委 托 菜 单 选 项 或 者 登 录 新 一 代 行 情 软 件 后 按 F12 快 捷 键 弹 出 委 托 登 录 窗 口 如 图 1-1

More information

5 436060469-B-002 行 政 处 罚 在 气 象 探 测 环 境 保 护 范 围 内 从 事 危 害 气 象 探 测 环 境 活 动 的 处 罚 中 华 人 民 共 和 国 气 象 法 第 三 十 五 条 第 一 款 第 二 项 6 436060469-B-003 行 政 处 罚 在

5 436060469-B-002 行 政 处 罚 在 气 象 探 测 环 境 保 护 范 围 内 从 事 危 害 气 象 探 测 环 境 活 动 的 处 罚 中 华 人 民 共 和 国 气 象 法 第 三 十 五 条 第 一 款 第 二 项 6 436060469-B-003 行 政 处 罚 在 权 力 清 单 目 录 部 门 ( 公 章 ): 填 表 日 期 :2015-8-10 代 码 权 力 类 型 职 权 名 称 法 定 依 据 工 作 流 程 工 作 时 限 实 施 主 体 承 办 科 室 1 436060469-A-001 行 政 许 可 防 雷 装 置 设 计 审 核 和 竣 工 验 收 国 务 院 对 确 需 保 留 的 行 政 审 批 项 目 设 定 行 政 许 可 的 决

More information

第2部分 操作系统实验

第2部分  操作系统实验 第 2 部 分 操 作 系 统 实 验 实 验 1 Windows XP 的 基 本 操 作 一 实 验 目 的 1. 掌 握 Windows XP 的 启 动 和 退 出 2. 了 解 Windows XP 的 桌 面 组 成 3. 掌 握 窗 口 基 本 操 作 和 菜 单 的 操 作 方 法 4. 掌 握 中 文 输 入 法 的 选 择 5. 掌 握 Windows 帮 助 信 息 的 使 用

More information

黄 金 原 油 总 持 仓 增 长, 同 比 增 幅 分 别 为 4.2% 和 4.1% 而 铜 白 银 以 及 玉 米 则 出 现 减 持, 减 持 同 比 减 少 分 别 为 9.4%,9.4% 以 及 6.5% 大 豆, 豆 粕 结 束 连 续 4 周 总 持 仓 量 增 长, 出 现 小 幅

黄 金 原 油 总 持 仓 增 长, 同 比 增 幅 分 别 为 4.2% 和 4.1% 而 铜 白 银 以 及 玉 米 则 出 现 减 持, 减 持 同 比 减 少 分 别 为 9.4%,9.4% 以 及 6.5% 大 豆, 豆 粕 结 束 连 续 4 周 总 持 仓 量 增 长, 出 现 小 幅 小 麦 净 多 持 仓 增 加, 豆 油 豆 粕 净 多 持 仓 减 少 美 国 CFTC 持 仓 报 告 部 门 : 市 场 研 究 与 开 发 部 类 型 : 量 化 策 略 周 报 日 期 :212 年 5 月 7 日 电 话 :592-5678753 网 址 :www.jinyouqh.com 主 要 内 容 : 根 据 美 国 CFTC 公 布 的 数 据, 本 报 告 中 的 11 个

More information

国家职业标准:网络课件设计师

国家职业标准:网络课件设计师 国 家 职 业 标 准 : 网 络 设 师 1. 职 业 概 况 1.1 职 业 名 称 网 络 设 师 1.2 职 业 定 义 运 用 学 习 理 论 和 教 学 设 原 理, 依 托 多 媒 体 与 网 络 技 术, 从 事 网 络 内 容 分 设 制 作 和 评 价 等 工 作 的 人 员 1.3 职 业 等 级 本 职 业 共 设 三 个 等 级, 分 别 为 : 四 级 网 络 设 师 (

More information

光明乳业股份有限公司

光明乳业股份有限公司 光 明 乳 业 股 份 有 限 公 司 非 公 开 发 行 A 股 股 票 募 集 资 金 存 放 与 实 际 使 用 情 况 的 专 项 报 告 及 审 核 报 告 截 至 2012 年 12 月 31 日 止 审 核 报 告 光 明 乳 业 股 份 有 限 公 司 全 体 股 东 : 德 师 报 ( 核 ) 字 (13) 第 E0019 号 我 们 审 核 了 后 附 的 光 明 乳 业 股 份

More information

目 录 第 一 章 行 政 办 公 介 绍... 4 1.1 行 政 办 公 的 作 用... 4 第 二 章 行 政 办 公 使 用 说 明... 4 2.1 会 议 管 理... 4 2.1.1 会 议 管 理 概 述... 4 2.1.2 如 何 设 置 会 议 室... 4 2.1.3 如

目 录 第 一 章 行 政 办 公 介 绍... 4 1.1 行 政 办 公 的 作 用... 4 第 二 章 行 政 办 公 使 用 说 明... 4 2.1 会 议 管 理... 4 2.1.1 会 议 管 理 概 述... 4 2.1.2 如 何 设 置 会 议 室... 4 2.1.3 如 沃 讯 OA_ 行 政 办 公 沃 讯 OA 行 政 办 公 使 用 说 明 沃 讯 软 件 版 权 所 有 沃 讯 软 件 www.volinfo.com 第 1 页 / 共 32 页 目 录 第 一 章 行 政 办 公 介 绍... 4 1.1 行 政 办 公 的 作 用... 4 第 二 章 行 政 办 公 使 用 说 明... 4 2.1 会 议 管 理... 4 2.1.1 会 议 管 理

More information

2015-2016 学 年 第 二 学 期 集 中 考 试 安 排 (18 周 ) 考 试 日 期 :6 月 27 日 星 期 一 8:10-9:50 第 二 公 共 教 学 楼 A 区 A303 10811046 高 等 数 学 ( 理 二 2) 复 材 1501-2 材 料 科 学 与 工 程

2015-2016 学 年 第 二 学 期 集 中 考 试 安 排 (18 周 ) 考 试 日 期 :6 月 27 日 星 期 一 8:10-9:50 第 二 公 共 教 学 楼 A 区 A303 10811046 高 等 数 学 ( 理 二 2) 复 材 1501-2 材 料 科 学 与 工 程 考 试 时 间 2015-2016 学 年 第 二 学 期 集 中 考 试 安 排 (18 周 ) 考 试 日 期 :6 月 27 日 星 期 一 考 场 所 在 教 学 楼 ( 教 学 区 ) 考 试 教 室 课 程 号 课 程 名 考 生 所 在 专 业 ( 班 级 ) 考 生 所 属 学 院 8:10-9:50 第 二 公 共 教 学 楼 A 区 A101 10811026 高 等 数 学 (

More information

( 此 页 无 正 文, 为 广 东 东 方 精 工 科 技 股 份 有 限 公 司 关 于 提 供 资 料 真 实 准 确 和 完 整 的 承 诺 函 之 签 署 页 ) 广 东 东 方 精 工 科 技 股 份 有 限 公 司 法 定 代 表 人 : 唐 灼 林 2016 年 7 月 28 日

( 此 页 无 正 文, 为 广 东 东 方 精 工 科 技 股 份 有 限 公 司 关 于 提 供 资 料 真 实 准 确 和 完 整 的 承 诺 函 之 签 署 页 ) 广 东 东 方 精 工 科 技 股 份 有 限 公 司 法 定 代 表 人 : 唐 灼 林 2016 年 7 月 28 日 广 东 东 方 精 工 科 技 股 份 有 限 公 司 关 于 提 供 资 料 真 实 准 确 和 完 整 的 承 诺 函 鉴 于 广 东 东 方 精 工 科 技 股 份 有 限 公 司 ( 以 下 简 称 本 公 司 ) 拟 收 购 北 京 普 莱 德 新 能 源 电 池 科 技 有 限 公 司 股 权, 为 保 证 本 次 交 易 的 顺 利 完 成, 按 照 中 国 证 券 监 管 部 门 相

More information

中国石化油品销售企业CRM调研报告

中国石化油品销售企业CRM调研报告 中 国 石 化 化 工 销 售 CRM 电 子 超 市 客 户 操 作 手 册 编 写 : CRM 项 目 组 适 用 范 围 : 化 工 销 售 有 限 公 司 华 北 分 公 司 版 本 : 1.1 日 期 : 2015.04 目 录 1. 会 员 服 务... 3 1.1 会 员 注 册... 3 1.2 会 员 登 陆... 6 1.3 用 户 信 息... 6 1.4 销 售 中 心...

More information

目 录 一 插 入 您 的 保 密 杀 毒 U 盘 3 二 控 制 面 板 8 2-1 USB SECURE ANTIVIRUS 实 时 监 控 9 2-2 USB SECURE ANTIVIRUS 手 动 扫 描 10 2-3 USB SECURE ANTIVIRUS 开 放 空 间 存 取 12

目 录 一 插 入 您 的 保 密 杀 毒 U 盘 3 二 控 制 面 板 8 2-1 USB SECURE ANTIVIRUS 实 时 监 控 9 2-2 USB SECURE ANTIVIRUS 手 动 扫 描 10 2-3 USB SECURE ANTIVIRUS 开 放 空 间 存 取 12 Avira USB Antivirus 保 密 杀 毒 U 盘 - I 使 用 手 册 USB-SAV (Secure Anti-Virus) 此 产 品 具 有 的 杀 毒 保 护, 请 按 照 以 下 步 骤 来 启 用 此 功 能 目 录 一 插 入 您 的 保 密 杀 毒 U 盘 3 二 控 制 面 板 8 2-1 USB SECURE ANTIVIRUS 实 时 监 控 9 2-2 USB

More information