当前位置: 首页 > news >正文

网站建设费用选择网络专业简易手工小制作

网站建设费用选择网络专业,简易手工小制作,潍坊专业联轴器收购价格,网站建设标准简约关于嵌入式开发的一些信息汇总#xff1a;嵌入式C开发人员、嵌入式系统Linux 1 关于嵌入式 C 开发人员1.1 嵌入式 C 开发人员必须具备的一些基本技能是#xff1a;1.2 嵌入式C开发的应用案例 2 如何学习用于嵌入式系统的 Linux2.1 如何学习Linux2.1.1 第一步#xff1a;创建… 关于嵌入式开发的一些信息汇总嵌入式C开发人员、嵌入式系统Linux 1 关于嵌入式 C 开发人员1.1 嵌入式 C 开发人员必须具备的一些基本技能是1.2 嵌入式C开发的应用案例 2 如何学习用于嵌入式系统的 Linux2.1 如何学习Linux2.1.1 第一步创建 VM 并安装桌面 Linux 发行版2.1.2 第二步熟悉命令行、文件系统、目录结构和进程组织2.1.3 第三步使用GCC、GDB、make2.1.4 第四步Linux开发资料来源2.1.5 第五步Linux 内核源代码的组织方式、如何配置内核以及如何使用您选择的选项构建新内核。2.1.6 第六步可加载模块LKM通常用于设备驱动程序2.1.7 第七步构建一个简单的字符设备驱动程序 这篇文章是关于嵌入式开发的一些基本信息供想入行的人参考。有一些作者本人的想法以及来自外网的大拿的文章翻译而来原文链接在此Learning Linux for embedded systems再次感谢支持原创。 1 关于嵌入式 C 开发人员 普通C开发人员和嵌入式C开发人员之间的基本区别在于因为嵌入式C程序被设计为能够与硬件通信并使硬件设备更有意义而普通C开发人员往往只编写桌面应用程序。嵌入式 c 开发人员要使用硬件设备和微处理器例如基于微控制器的应用程序。 1.1 嵌入式 C 开发人员必须具备的一些基本技能是 1、有C语言能力。这是必须的因为没有C的知识就上手嵌入式c编程也是学不会的。 2、有编程基础知识例如面向对象编程及其四个基本概念聚合、封装等以及其他关键功能例如覆盖和重载。 3、嵌入式 C 开发人员必须在计算机体系结构以及数据结构和算法领域具有广泛的知识。 4、操作系统的知识是必须的在 power shell 环境中工作与学习的能力与会基本的 c 语言一样必要。 5、必须具备微处理器基础知识汇编代码和寄存器等和微控制器基础知识DMA、ADC 和定时器等。 6、使用 I2C 和 LIN 等的网络编程基础以及 SATA 和 MOST 等高级网络编程。 7、必须具备并发、并行工作能力熟悉系统调用库函数。 8、嵌入式 C 开发人员必须知道如何处理未收集的垃圾环境例如悬挂指针。 9、了解其他编程语言如 python、Java 和 Android 以及基本 FPGA/ASIC 设计、基本 DSP 的技能 10、最后了解软件工程原理是一个加分项因为它使版本控制、错误跟踪和整体测试等工作变得更加容易。 1.2 嵌入式C开发的应用案例 许多项目由普通的 C 开发人员处理其中包括硬件设备这些硬件设备需要用嵌入式 c 语言编写底层程序才能正常运行。示例如下 1、环境监控系统这是一个内置湿度传感器、金属探测器和火灾传感器的系统。该系统通过用户的命令进行监控通过单个端口发送特殊信号来控制多通道射频发射器。 2、无线医疗监控系统该系统确保通过温度和湿度传感器等传感器检测患者的数据并收集这些数据以发送到控制中心。此类硬件和软件同时通信的应用程序由嵌入式 c 开发人员开发的程序控制。 3、Vehicle Tax pay and access system另一个硬件和软件通过程序通信的系统是由嵌入式c开发人员开发的。在这个系统中收集有关车辆出入信息的过程是自动完成的并使用智能卡技术。 4、基于微控制器的移动干扰器这个工作在 900MHz 到 1200MHz 的项目只是为了确保信号在这些干扰器放置的特定区域被丢弃和完全切断。该技术可用于讨论机密信息且安全是第一要务的地方。蜂窝移动 SIM 卡与其蜂窝基站之间的连接被切断。这些只是一些嵌入了程序的硬件设备这些程序使它们能够阻止传入和传出的信号也是由嵌入式 c 开发人员开发的。 2 如何学习用于嵌入式系统的 Linux 一个人如果具备 8 位处理器如 PIC和 32 位处理器如 PowerPC嵌入式系统编程经验但是没有 Linux 经验那么要如何学习以及如何使用嵌入式 Linux呢 像这样的嵌入式系统程序员推荐的是将嵌入式 Linux 视为两个部分即嵌入式部分和 Linux 部分。 2.1 如何学习Linux 让我们首先考虑 Linux 部分。 无论您使用什么开发主机无论是 Linux、Windows 还是 Mac您都需要学习如何使用目标操作系统进行编程。在这方面使用嵌入式 Linux 与使用 VXworks、WindowCE 或其他操作系统没有太大区别。 1 您需要了解操作系统是如何设计的、如何配置操作系统以及如何使用其应用程序编程接口 (API) 进行编程。 2 Linux 区别于其他操作系统的最重要因素是所有系统都使用相同的内核从最小的嵌入式主板到桌面系统再到大型服务器群。这意味着您可以在桌面环境中学习大量 Linux 编程这比使用目标板连接到目标、下载测试程序和运行测试的所有复杂性要灵活得多。 3 对于桌面 Linux 和嵌入式 Linux所有基本概念和大多数 API 都是相同的。 2.1.1 第一步创建 VM 并安装桌面 Linux 发行版 在您当前的开发系统上创建一个虚拟机环境。 1 对于 Windows 主机您可以安装 VMware Player 或 VirtualBox使用虚拟机可为您提供更大的灵活性。您可以安装桌面 Linux 发行版例如 Ubuntu 或 Fedora。 2 您可以使用此发行版来熟悉基本的 Linux 概念、学习命令 shell 以及如何构建和运行程序。您可以重新配置内核或加载驱动程序而不必担心会使桌面系统崩溃。 3 您可以构建整个内核和应用程序环境类似于您可能对嵌入式 Linux 目标的交叉开发环境所做的事情。 4 如果运行 Linux 的 VM 崩溃您只需重新启动 VM。崩溃不会影响您在开发系统上可能正在做的其他事情例如阅读有关如何构建和安装驱动程序的网页或者向众多支持邮件列表之一发送电子邮件。创建一个您可以轻松学习 Linux 概念和编程的环境。 2.1.2 第二步熟悉命令行、文件系统、目录结构和进程组织 1 大多数 Linux 系统配置和管理是从命令行执行的在桌面系统上这意味着打开一个终端窗口并使用 Bash shell。 命令以命令名称开头通常接受选项通常以连字符开头后跟文件名。许多命令名称都很简洁如 ls 或 cp并且可以有多个选项其中大部分您很少会用到。如果您熟悉 Windows CMD shell或它从中演变而来的 MSDOS shell许多命令是相似的如 cd但经常存在细微差别。至少您需要知道如何列出文件cat、less、file、列出目录并在目录之间移动ls、cd、pwd以及如何获得帮助man、info、apropos。桌面 Linux 系统有数千条命令你只需要知道一小部分。但是如果你想做某事很可能有一个命令可以做到。apropos 命令是查找可能执行您想执行的操作的命令的好方法。尝试从命令行运行“man apropos”。您还需要熟悉可在命令 shell 中使用的编辑器例如 vi。在嵌入式 Linux 系统上您很可能没有窗口系统。您将与 BusyBox 和 Ash shell一个小型​​命令行解释器进行交互BusyBox 将大约 200 个命令打包到了一个可执行程序中。 2Unix 和 Linux 的设计哲学之一是围绕分层文件系统进行组织。 这个文件系统的根名为“/”文件系统中的所有内容都可以从这里开始找到。自然地文件系统保存包含文本或数据的常规文件以及程序。此外它还包含各种特殊的“文件”这些文件可能代表物理设备如硬盘驱动器、驱动程序创建的接口如虚拟终端、网络连接等。其他操作系统可能会为有关进程或内存的内部信息提供编程接口而 Linux 则通过将此信息表示为文本文件来提供一个非常简单的接口。例如常用目录为/boot包含引导程序/bin 和 /sbin包含通常由系统管理员 root 运行的程序/dev包含设备真实的和虚拟的/etc包含系统配置文件/home包含用户文件/proc 和 /sys带有系统信息/lib包含库/usr不包含用户文件而是可以由用户运行的程序/tmp包含临时文件最后是 /var包含系统日志。嵌入式 Linux 系统将具有相同的组织结构尽管有时某些目录可能会合并。它将比桌面系统拥有更少的文件。 3 Linux和 Unix有一个层次化的进程结构。 第一个进程 init 的进程 ID (PID) 为 1由 Linux 内核在系统启动时创建。反过来Init 创建子进程允许您登录系统再依次启动窗口系统或命令 shell这又会产生其他进程。如果在命令窗口中键入“ps”您将看到在该窗口中运行的顶级进程的简要列表通常只是 ps 命令本身和 bash 命令行解释器。键入“ps -l”将为您提供更多信息包括每个进程父进程的进程 ID (PPID)、运行程序的用户 ID (UID) 等更多信息。 2.1.3 第三步使用GCC、GDB、make 几乎每个项目都需要使用 GNU 编译器集合 (GCC)、GNU 二进制实用程序 (Binutils) 和 make用于构建程序和处理依赖项。 1 Linux 确实有几个 IDE集成开发环境如 Eclipse但它们都是围绕这些命令行工具构建的。与通常使用 Visual Studio 的 Windows 开发不同许多 Linux 开发人员不使用 IDE。 要使用 gcc 编译 C 程序请使用您喜欢的文本编辑器vi、emacs、gedit、kwrite 等编写您的程序并使用后缀 .c 保存它在下面的示例中我们使用标准的第一个 C 程序来自 KR 并将其保存为 hello.c)。然后输入以下命令 $ gcc -o hello -g -O1 hello.c gcc将会调用 C 编译器来翻译您的程序如果成功且没有错误它将继续调用具有正确系统库的链接器以创建名为 hello 的可执行文件。 其他操作系统通过后缀识别可执行文件如 .exe。Linux 可执行文件通常没有后缀由文件系统标志指示文件可以执行。 可执行文件的名称遵循 -o 选项- g 选项表示生成调试信息-O1即字母 O 后跟数字 1表示生成优化代码。GCC 有大量不同的选项但这些都是必要的基础。为了便于调试您可能需要指定 -O0字母 O 后跟数字 0或省略 -O 选项以在不进行优化的情况下进行编译。 您可能会发现您的 Linux 安装缺少一些默认情况下未安装的组件如 GCC 或 C 库的头文件。 如果是这种情况您可以使用系统的包管理器来添加这些组件。 在 Fedora 系统上这意味着使用 yum 或者 packagekit GUI在 Ubuntu 系统上您可以使用 apt-get 或 synaptic GUI。这些包管理器将处理您请求的组件的下载和安装以及可能需要的任何依赖项。 您可以通过输入程序名称从命令行执行程序它要在您的路径搜索列表中或者您通过命令行给出文件的路径。 对于我们的示例我们可以执行以下操作 $ ./helloHello World在这种情况下由于我们的当前目录未在 $PATH 环境变量中列出因此我们使用点 (.) 来指示当前目录然后是文件名由目录规范中的斜杠分隔。 这时可以使用 GDB 调试器运行程序无论您是在进行内核、驱动程序还是应用程序开发您都可能需要使用 GDB 调试程序。GDB 有一个命令行界面学习执行基本操作如打印变量值、设置断点和单步执行程序的命令是个好主意。其他 GUI 包括 Eclipse CDT IDE、Insight甚至是 Emacs 文本编辑器的扩展。 您可以SftyE2eCompst $ gdb hello [ start up messages from gdb ] (gdb) break main Breakpoint 1 at 0x400530: file hello.c, line 5. (gdb) run Starting program: /tmp/hello Breakpoint 1, main () at hello.c:5 5 printf (Hello world!n); (gdb) cont Continuing. Hello world! (gdb) quit 在上面的示例中gdb的输出以粗体显示我们的命令是普通类型。 除了来自gdb的初始启动消息之外可能还有一些关于缺少系统库调试信息的其他消息或关于程序退出的消息。 在嵌入式 Linux 环境中您将以类似于本机 Linux 开发的方式使用 GCC、GDB 和 make。 在大多数情况下您将使用针对您正在使用的处理器的不同版本的 GCC 和 GDB。程序名称可能不同例如arm-none-eabi-gcc它使用 EABI嵌入式 ABI为 ARM 生成代码。 另一个区别是您很可能在交叉开发环境中工作您在主机系统上编译并将程序下载到目标系统。如果您有嵌入式编程经验那么您应该熟悉在交叉开发环境中工作。 2.1.4 第四步Linux开发资料来源 Linux 有许多库可用于嵌入式系统要使用包管理器来安装库****和包含标头的相关开发包。一些库有静态和动态两种版本静态库与您的程序链接而动态库是独立的在执行程序时根据需要加载。 除了最简单的应用程序之外每当我编写任何应用程序时多年来我的参考资料一直是 W. Richard Stevens的《UNIX 环境中的高级编程》.Linux 采用了 Unix 的大部分 API 和接口尽管实现可能有所不同。另一个参考是The Linux Programming Interface, 迈克尔·克瑞斯克著。 两者都不会成为床边读物但如果您需要了解文件或进程操作、信号、线程、进程间、或进程内、或网络通信和同步的基本细节等等这些都是很好的起点。还有Stack Overflow等帮助论坛。在桌面和嵌入式环境中有一个广泛的开源基础设施支持 Linux。自由软件基金会的GNU 项目维护着大量广泛使用的实用程序和库。您可以从http://gnu.mirrors.pair.com/gnu下载这些包它会自动将您连接到您附近的镜像。SourceForge拥有超过 300,000 个项目的源代码其中许多非常重要。Freecode还拥有数以千计的开源应用程序。我的候选名单上的最后一个目的地是GitHub它为数千个项目的代码存储库提供托管服务。 大多数库或程序都是使用 GNU make 实用程序以及 bash 脚本或支持实用程序如automake 和autoconf 构建的。最简单的是make 检查哪些文件需要编译并管理使用开发人员编写的 Makefile执行这些编译的顺序。Makefile 可能非常复杂Makefile 调用make 来构建子目录或递归调用自身。Automake 旨在生成 Makefile识别依赖项并调用libtool这是一个创建共享库的实用程序。 自动配置 允许为不同的目标和操作系统或使用不同的选项编译库或程序。 为您的 Linux 系统构建大多数标准库或程序的标准顺序是下载源代码通常以tar 文件的形式可能用gzip、bzip2或xz压缩。如果我想构建自己的diff副本我会首先 从 GNU 镜像下载diffutils包。通常我会使用浏览器来保存包但我也可以使用wget 实用程序 $ cd /tmp $ wget ftp://ftp.gnu.org/gnu/diffutils/diffutils-3.3.tar.xz解压文件并cd 到生成的目录 $ tar xfv diffutils-3.3.tar.xz $ cd diffutils-3.3 如果包有 .gz 或 .tgz 后缀则需要在“xfv”后添加“z”选项。如果它有 .bz 后缀请添加“j”选项。 许多软件包都有一个 README 文件。在构建之前您应该阅读此内容。自述文件将告诉您如何构建包。构建大多数包如 diffutils很简单您输入以下命令 $ ./configure $ make $ make install第一个命令调用 configure 它将分析您的系统并创建一个 Makefile 来构建您的库或为您的系统量身定制的程序。第二个命令调用make它将编译和链接工作目录中的库或程序。第三条命令将安装库或程序。 当然有时这些步骤中的每一步都会出错。Configure 可能会告诉您需要安装其他包或者可能是已安装库的标头。make步骤可能因编译错误而 停止。最后一步可能会尝试将库或程序安装在受保护的系统目录中。如果是这种情况您可以以 root 身份运行最后一步或者在前面加上sudo 命令临时承担 root 权限。或者您可以指定 –prefix 选项来配置并指向未受保护的目录 $ ./configure --prefix~/mydiff当您运行make install时该程序和任何其他文件将安装在前缀选项中提到的目录中在本例中为我的主目录中的 mydiff。 有一些我们将在未来讨论的注意事项这意味着您在本机 x86 Linux 环境上构建的库和程序也可以为其他处理器如 ARM、PowerPC 或 MIPS或其他 Linux 配置构建使用许多相同的工具和技术。 2.1.5 第五步Linux 内核源代码的组织方式、如何配置内核以及如何使用您选择的选项构建新内核。 大多数嵌入式项目都需要配置 Linux 内核并且可能需要开发设备驱动程序以匹配您的硬件。由于我们在虚拟机中运行的桌面 Linux 系统使用的内核与您在嵌入式系统中使用的内核相同因此我们可以在桌面系统上构建自定义内核和简单的驱动程序其方式与开发板的方式大致相同. 每个主要发行版都描述了它们如何构建内核。对于 Fedora描述在Fedora Wiki上对于 Ubuntu在社区站点上也有资源其中每一个都将安装用于构建 VM 系统的源代码。他们使用像 rpmbuild 或脚本这样的程序来使这个过程变得简单尽管可能不足够透明。 我建议您登录到您的 VM 并按照脚本构建并安装新内核。在安装之前您可能需要拍摄 VM 的快照以防万一出现问题时您想返回到已知的稳定系统。 当您按照这些说明进行操作时它们将创建一个目录其中包含用于构建您已安装的版本的内核。 这是“vanilla”内核可以从 kernel.org 下载加上发行版选择的一些补丁。如果你像我一样使用 Fedora你可以在~/rpmbuild/BUILD/kernel-中找到vanilla内核和补丁内核 . 让我们将打过补丁的内核复制到一个单独的目录中 $ cp -r ~/rpmbuild/BUILD/kernel*/linux* ~/linux较早的指南经常会说将内核复制到 /usr/src/linux这是内核的传统存放位置你不需要这样做内核可以构建在任何位置。通常 /usr/src 是一个受保护的目录只能由 root 写入。您无需成为 root 用户即可构建内核。 让我们简单浏览一下 ~/linux 下的一些文件和子目录 Makefile. 用于控制配置和构建内核Arch. 包含体系结构特定文件Drivers. 包含在内核的驱动源码Include. 用于构建内核和驱动程序的头文件Kernel.“核心”目标独立部分README. 目录的描述带有 make 指令的Scripts. 用于构建内核和驱动程序的 Bash 脚本有几个包含内核部分的目录如 net网络、mm内存管理、fs文件系统等。 arch 目录包含超过两打不同处理器架构的子目录包括非常流行的 ARM 和 Intel x86 处理器以及一些鲜为人知的处理器。这些目录包含特定于目标的代码允许 Linux 在如此多的不同处理器上运行。您会发现与内核下名称相同的目录其中包含特定于目标的代码以支持与目标无关的功能。 构建 Linux 内核的核心是 .config 文件。这是一个隐藏文件开头的点表示隐藏但是输入“ls -a”就可以看到这是当前的配置。configs 目录下有示例配置文件。X86 只有两个一个用于 32 位一个用于 64 位。ARM 有几十个用于许多不同的处理器配置。如果你打开 arch/x86/configs/i386_defconfig你会看到这样 CONFIG_EXPERIMENTALy# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPCyCONFIG_POSIX_MQUEUEyCONFIG_BSD_PROCESS_ACCTyCONFIG_TASKSTATSyCONFIG_TASK_DELAY_ACCTyCONFIG_TASK_XACCTy每个 y 都表示启用了一个选项注释掉或丢失的配置选项未启用。 从头开始创建其中一个配置文件将是一项艰巨的任务我们不必这样做。您为VM下载的源包含一个 .config或者可能有关于从 /boot 目录复制与您的安装相对应的配置文件的说明。 要开始构建内核您需要运行 $ make oldconfig如果您想查看所有选项并使用简单的基于文本的实用程序选择要启用或禁用的选项请运行 $ make menuconfig继续探索随后显示的 GUI右图。箭头键允许您在列表中上下移动。要设置或取消设置选项请按空格键。要转到子菜单由 - 箭头指示请按 Enter。左右箭头选择窗口底部的选项。选择帮助会告诉您有关该选项的一些信息。当您想要退出子菜单时选择退出。在顶级菜单中选择保存以保存对 .config 的更改。 在我们构建我们的内核之前让我们给它一个稍微不同的名字。如果您在编辑器中打开 Makefile前几行将指定 VERSION、PATCHLEVEL、SUBLEVEL 和 EXTRAVERSION 值。前三个将与内核版本相同。在我的例子中这是 3.11.9与我下载的内核源 RPM 名称上的值相同。将您的姓名或号码添加到 .config这将用于使新构建的内核与安装的内核不同。 要构建内核最好从头开始 $ make clean如果您希望继续构建可能因编译失败而停止的构建则无需执行此操作。 编译内核需要相当多的时间即使在快速系统上也是如此 $ make每次编译只打印一行。如果您想要详细信息很多详细信息请在 make 命令末尾添加 V1 。 接下来您需要构建未链接到内核的可加载模块。这要快得多 $ make modules在 /lib 下安装模块然后在 /boot 中安装新内核。这两个命令需要以 root 身份执行因为它们会修改受保护的系统目录 $ su Password: make modules_install make install查看 /lib/modules 和 /boot 以查看 Makefile 安装的内容。您现在可以重新启动您的 VM # reboot从 GRUB 引导菜单中选择您的新内核。系统重新启动并登录后您可以通过运行“uname -1”来检查版本。您应该看到新内核的版本号包括您​​的姓名或您添加到 EXTRAVERSION 的编号。您可能会修改配置、重建和安装内核。每次更新 EXTRAVERSION 以帮助跟踪哪个内核是哪个。如果您创建了一个崩溃的内核请不要担心。您始终可以在 GRUB 引导菜单中选择一个旧版本或者如果您听取了我的建议以保存 VM 的快照则可以从快照恢复并从中断的地方继续。 为嵌入式 Linux 构建 Linux 内核时存在一些差异但是构建 Linux 内核的文件组织、配置和整个过程对于桌面 Linux 系统和嵌入式 Linux 系统是相似的。 2.1.6 第六步可加载模块LKM通常用于设备驱动程序 您可能已经注意到构建内核的结果是在 /boot 中安装了三个文件。这些文件中的每一个都在其名称后附加了版本号。 vmlinuz — 压缩内核 initramfs或 initrd——用于引导内核的初始文件系统 System.map — 导出的内核符号及其地址的列表。 解释一下 vmlinuz 是内核的可执行映像已使用 gzip或其他压缩算法压缩。它还包含一个解压缩存根用于在加载内核时解压缩内核。您可以使用可以在内核脚本目录中找到的 extract-vmlinux 解压缩它。临时根文件系统 initramfs或其前身 initrd在引导过程中加载到内存中。此根文件系统包含挂载根文件系统可能需要的设备驱动程序或其他程序但在加载内核后可能不需要它们。这允许创建一个通用内核它可以在具有不同硬件的各种系统上运行。 Linux 内核被设计为一个单体系统具有一个单一的大型二进制映像。组成内核的所有东西都被编译并链接在一起以形成这个映像。例外情况是有些独立的 Linux 内核模块 (LKM)。 LKM 是可以加载到内核中以扩展其功能的代码片段。LKM 可以作为内核构建的一部分进行编译当您选择它们​​作为内核配置的一部分时也可以单独进行编译。它们可能被链接到内核映像在内核配置中指定或者它们可以在系统启动和内核运行后稍后加载。LKM 有多种用途包括支持不同的文件系统添加新功能或系统调用或者最常见的是添加对新硬件的支持。LKM 与特定版本的内核紧密耦合必须为每个版本的内核重新编译。您可以通过运行“lsmod”命令或列出 /proc/modules 查看安装在 Linux 系统上的 LKM 列表。 我们将重点关注 LKM 对设备驱动程序的使用因为这是嵌入式 Linux 中最常见的用途。 Linux 中有几类设备字符、块和网络设备是最常见的类型。字符设备作为连续的字节流读取或写入如键盘或打印机。块设备用于支持文件系统并作为固定大小的块进行读取或写入。网络设备用于与发送或接收数据包的不同系统进行通信。字符设备和块设备由 /dev 下的文件系统条目表示例如网络接口的名称类似于“eth0”。 让我们逐步构建一个简单的 LKM。 我们将从最简单的 LKM 开始我们将其命名为lkm.c — /* Simple Linux Kernel Module */ #include int init_module() { printk(KERN_ALERT LKM initn); return 0; } void cleanup_module() {printk(KERN_ALERT LKM stoppedn); } 它有一个函数 init_module( )当 LKM 加载到内核时调用它。还有另一个函数cleanup_module( )当它被删除时调用它。Printk 类似于printf,只是它将输出定向到系统日志/var/log/messages。 我们的 makefile 名为Makefile也很简单 obj-m lkm.o KERNELDIR/lib/modules/ $(shell uname -r)/buildall: make -C ${KERNELDIR} M$(PWD) modulesclean: make -C ${KERNELDIR} M$(PWD) clean我们的 makefile 设置参数以告知要编译哪些文件并调用内核 Makefile 来完成繁重的工作并实际构建 LKM。结果是一个名为 lkm.ko 的文件“ko”后缀表明这是一个内核模块。 我们可以使用“modinfo”命令查看模块记录的信息 $ modinfo lkm.ko filename: /home/eager/lkm/lkm.ko depends: vermagic: 3.12.8-200.fc19.x86_64 SMP mod_unload我们可以使用 insmod 命令将模块加载到正在运行的内核中 #insmod lkm.ko请注意虽然我们可以在用户模式下编译内核模块这总是一个好主意但您需要以 root 身份运行 insmod。您可以在另一个 shell 中运行此命令在该 shell 中您使用“su”命令假定了超级用户权限或者您可以在 insmod 命令前加上“sudo”前缀假设您已经设置了 /etc/sudoers。 除非出现错误否则 insmod 不会发出任何消息。要查看我们的模块是否已加载到内核中我们使用 lsmod 命令 $ lsmod | grep lkm lkm 12426 0这表明我们的 LKM 安装在内核中其大小为 12426 字节并且没有其他 LKM 依赖于它。一个 LKM 可以依赖于另一个低级驱动程序为更高级别的驱动程序提供服务。如果您运行如下命令您可以看到这一点 $ lsmod | grep par parport_pc 28048 0 parport 40425 2 ppdev,parport_pc在这里我们可以看到 parport并行端口驱动程序被另外两个驱动程序使用——ppdev 和 parport_pc。 我们可以再次以超级用户身份使用 rmmod 命令从内核中删除 LKM # rmmod lkm.ko如果我们查看系统日志我们可以看到 LKM 初始化和删除时发出的消息 # tail -n 2 /var/log/messagesJan 26 17:58:36 fedora19 kernel: [27688.186462] LKM initJan 26 18:00:14 fedora19 kernel: [27786.528267] LKM stopped您可以通过将 LKM 复制到正确的系统目录来将其安装到内核中。如果查看 /lib/modules您将看到已安装的每个内核都有一个子目录。如果查看当前正在执行的内核的目录 /lib/modules/$(uname -r)/kernel您会看到许多用于各种内核模块的子目录例如加密、驱动程序、内存管理和声音。 我们将以 root 身份将 LKM 复制到 drivers/misc 目录 # cp lkm.ko /lib/modules/kernel/$(uname -r)/kernel/drivers/misc接下来我们执行 depmod 命令更新 /lib/modules/$(uname -r) 下的模块映射文件 #depmod -a这将在 modules.dep 中创建一个条目modprobe 使用它来查找 LKM # modprobe lkm我们还可以使用 modprobe 删除模块 # modprobe -r lkmModprobe 是一个更高级别的命令它调用 insmod 和 rmmod 来完成繁重的工作。它理解并解决模块先决条件支持别名并由内核用于根据需要加载 LKM 当您查看系统日志时您可能已经注意到一些事情 Jan 26 18:38:34 fedora19 kernel: [118400.641718] lkm: module license unspecified taints kernel.Jan 26 18:38:34 fedora19 kernel: [118400.641724] Disabling lock debugging due to kernel taintJan 26 18:38:34 fedora19 kernel: [118400.642077] lkm: module verification failed: signature and/or required key missing - tainting kernelJan 26 18:38:34 fedora19 kernel: [118400.642981] LKM initJan 26 18:41:38 fedora19 kernel: [118585.066364] LKM stopped内核模块加载器****检查我们正在加载的 LKM 是否具有与 Linux 内核兼容的许可证。我们简单的 LKM 没有提到许可事实上日志消息说它是“未指定的”还说它“污染”了内核。这不是某种难闻的气味就像太旧的牛奶一样。这意味着内核现在包含一个非开源代码。 如果您向内核开发人员寻求有关错误的帮助并且他或她注意到“受污染的内核”消息您可能会被要求在没有污染内核的 LKM 的情况下重现该问题。 Linux 内核开发人员有兴趣推广开放源代码查看仅包含开放源代码且不包含专有代码的内核中的错误是实现这一目标的一种方式。 对于一个微不足道的内核模块来说就这么多了. 2.1.7 第七步构建一个简单的字符设备驱动程序 LKM 最常见的用途是创建驱动程序以支持新硬件或创建虚拟设备。 最简单的虚拟设备是 /dev/null它会丢弃所有写入它的数据并在读取时立即返回一个 EOF。您可以在 linux/drivers/char/mem.c 中找到 /dev/null 驱动程序的源代码。 我们将编写一个驱动程序来创建一个虚拟设备该设备在读取时将返回一个伪随机数。这是一个类似于 /dev/random 的虚拟设备但更简单并且不用于实际程序中。 这是我们的驱动程序的基本框架名为myrandom.c /* Random number virtual device. */ #include #define DRIVER_AUTHOR Michael J. Eager #define DRIVER_DESC random number generator device /* Declare license and provide authorship and description. */ MODULE_LICENSE(GPL); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC);/* Declare all functions. */ static int init_myrandom(void); static void cleanup_myrandom(void); static int init_myrandom(void){ printk(KERN_ALERT myrandom initn); return 0;} static void cleanup_myrandom(void){ printk(KERN_ALERT myrandom stoppedn);} module_init(init_myrandom); module_exit(cleanup_myrandom); 这看起来很像我们在上一期中创建的简单 LKM我们需要在 Makefile 中更改的只是替换lkm.o 为myrandom.o. 我们添加了一个 MODULE_LICENSE 宏说明该驱动程序是根据 GPL 许可的以及一个列出作者和描述的宏这些将在您运行modinfo myrandom.ko 文件时显示。我们还在末尾添加了两个宏module_init 和 module_exit它们允许我们指定 init 和清理例程的名称而不是使用默认值。 当您运行insmod myrandom.ko 以 root 身份和tail /var/log/messages时您将看到驱动程序在加载时发出的消息。运行rmmod myrandom 将删除驱动程序并将停止消息添加到系统日志中。 1创建设备 接下来让我们告诉内核支持我们的myrandom 设备 在文件顶部添加#include 并添加一些数据结构static int Major;static struct file_operations fops {}; 更新初始化和清理例程如下所示 static int init_myrandom(void) { printk(KERN_ALERT myrandom initn); Major register_chrdev(0, myrandom, fops); if (Major 0) { printk(KERN_ALERT Registering myrandom device failed: %dn, Major); return Major; } printk(Myrandom assigned major number %dn, Major); return 0; } static void cleanup_myrandom(void) { /* Unregister myrandom device. */ unregister_chrdev(Major, myrandom); printk(KERN_ALERT myrandom stoppedn); }当我们使用 insmod 加载这个驱动时它会注册一个字符设备驱动。 设备表示为 /dev 下的特殊文件其中有一个表示设备类别的主设备号和一个表示该类中特定设备的次设备号。 如果运行cat /proc/devices 您将看到系统中定义的设备类别列表包括myrandom. 当我们调用register_chrdev时第一个参数为零我们要求内核分配一个可用的主设备号。 注册设备驱动程序不会在 /dev 下创建设备文件。有几种方法可以做到这一点我们将使用最简单的方法并以 root 身份运行 mknod 命令并使用 chmod 使其可供所有用户访问 # mknod /dev/myrandom c 249 0 # chmod 0666 /dev/myrandom # ls -l /dev/myrandomcrw-rw-rw- 1 root root 249, 0 Mar 25 08:00 /dev/myrandom内核为 my driver 分配了主设备号 249你的号码可能不同。 创建设备文件的其他方法是在我们注册驱动程序时调用内核的 mknod() 函数这与 mknod 命令的作用相同。 一种更优雅、更灵活的方法是使用 udev,Udev 是一个用户空间守护进程在注册新设备时由内核通知, 然后它使用 /etc/udev/rules.d 中的规则来创建设备节点。 添加设备功能 我们希望我们的设备驱动程序支持打开、关闭和读取操作并且我们希望写入我们的设备可以返回错误。 让我们定义将执行这些操作的例程 static int open_myrandom(struct inode *, struct file *); static int close_myrandom(struct inode *, struct file *); static ssize_t read_myrandom(struct file *, char *, size_t, loff_t *); static ssize_t write_myrandom(struct file *, const char *, size_t, loff_t *); static int Major; static struct file_operations fops { .read read_myrandom, .release close_myrandom, .open open_myrandom, .write write_myrandom }; static int myrandom_in_use 0; static int open_myrandom(struct inode *inode, struct file *file) { if (myrandom_in_use) return -EBUSY; myrandom_in_use; return 0; } static int close_myrandom(struct inode *inode, struct file *file) { if (myrandom_in_use) myrandom_in_use--; return 0; } static ssize_t read_myrandom(struct file *filp, char *buf, size_t len, loff_t *ofs) { return 0; } static ssize_t write_myrandom(struct file *filp, const char *buf, size_t len, loff_t *ofs) { return 0; }open 例程增加了一个内部标志以便一次只有一个程序可以打开设备尝试打开设备的第二个程序将收到busy 错误关闭例程重置此标志。目前读取和写入例程是什么都不做的假人。 如果你 insmod 驱动程序你可以使用dd 命令打开设备并从中读取 $ dd if/dev/myrandom00 records in00 records out0 bytes (0 B) copied, 4.5739e-05 s, 0.0 kB/sdd 命令打开设备并立即收到 EOF。 传输数据 让我们通过在读取设备时返回一些数据来完成这个示例驱动程序 在文件顶部附近添加#include static unsigned char myrandom(void); 让我们创建一个简单的随机字符生成器​​每次调用它时返回一个随机字母或数字 /* Generate random letters and numbers. Algorithm from Wikipedia. */ static unsigned char myrandom(void) { static char letters[] ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789; static unsigned int m_w 0x12345678; static unsigned int m_z 0x87654321; int myrand; m_z 36969 * (m_z 65535) (m_z 16); m_w 18000 * (m_w 65535) (m_w 16); myrand (m_z 16) m_w; myrand (myrand 16) % sizeof(letters); return letters[myrand]; }让我们充实read例程 static ssize_t read_myrandom(struct file *filp, char *buf, size_t len, loff_t *ofs) { unsigned char rand_val; int count 0; /* Return EOF when all bytes read. */ if (bytes_read 100) return 0; while (len-- 0 bytes_read 100) { rand_val myrandom(); put_user(rand_val, buf); count; } /* Return number of bytes transferred. */ return count; }最后在 open 例程中让我们在设备打开时将计数清零 static int open_myrandom(struct inode *inode, struct file *file) { if (myrandom_in_use) return -EBUSY; myrandom_in_use; bytes_read 0; return 0; }当我们读取 /dev/myrandom 时我们将收到我们请求的随机字符数最多 100 个。当我们写入设备时我们会立即收到一条设备已满的消息。 $ dd if/dev/myrandom bs10 count1QFF5tmwf3i10 records in10 records out10 bytes (10 B) copied, 0.000252246 s, 39.6 kB/s $ dd if/dev/myrandome9LDb6se6jJZnrS6prxpbkyTwIaaTlU1YDaz7buUtbvDXw1hxSgImzTc84zF28SZqUtS6tfRO8kl1iQCXEXSGjOTftygRqzV01 records in01 records out100 bytes (100 B) copied, 0.000145579 s, 687 kB/s $ dd if/dev/zero of/dev/myrandomdd: writing to /dev/myrandom: No space left on device10 records in00 records out0 bytes (0 B) copied, 0.000461547 s, 0.0 kB/s请注意由于从 /dev/myrandom 返回的字符串不是零终止的因此来自 dd 的消息将附加到输出中。 我们没有讨论的一个主题是将参数传递给驱动程序,可以直接使用 modprobe 或使用 /etc/modprobe.conf 来完成。在我们的示例中我们可能已经指定了随机数种子。 一个真正的驱动程序可能会将设备地址或选项指定为参数。 我们只涉及了编写设备驱动程序的基础知识没有涉及硬件相关的问题。我推荐Alessandro Rubini、Jon Corbet 和 Greg Kroah-Hartman 合写的Linux Device Drivers 由 O’Reilly 出版。第 4 版应该会在 7 月出版作者名单中会添加 Jessica McKeller。 下一篇关于嵌入式开发的一些信息汇总开发模型以及自托管开发一
http://www.zqtcl.cn/news/498856/

相关文章:

  • 烟台建网站wordpress重写规则
  • 上海网站建设怎么赚钱平顶山网站建设服务公司
  • 导航网站如何被百度收录广告设计在线设计
  • 雪域什么网站是做电影的苏州优化方式
  • 设计网站多少钱手机百度助手
  • 驾校网上约车网站开发不会做网站如何做seo
  • 企业做推广可以发哪些网站宜兴埠网站建设
  • 网站后台文章添加成功 不显示公司设计网站建设合同
  • 后端开发需要掌握哪些知识潍坊优化公司
  • 专业手机网站制作哪家好wordpress wp-polls
  • 网站建设前分析网页制作素材按钮
  • 做视频网站怎么对接云盘松江新城网站建设
  • 温州阿里巴巴网站建设企业宣传片怎么拍
  • 淮阳住房城乡建设局网站阿里巴巴做国际网站要多少钱
  • 电子商务个人网站可以备案吗短网址还原
  • 网站内容由什么组成部分组成部分电子商务网站建设主管的策划书
  • 云服务器安装win系统做网站seo三人行论坛
  • 电气网站设计机械设计软件solidworks
  • 内网网站建设所需硬件设备厦门关键词排名提升
  • 网站动态海报效果怎么做的最专业网站建
  • 学校如何建设网站北京市住房及城乡建设部网站
  • 响应式网站制作流程全国城建培训中心官网查询证书
  • 北京工程建设信息网站中国市场网
  • xml做网站源码免费网站是
  • 中国工商建设标准化协会网站织梦app网站模板
  • 怎么做好网络销售文大侠seo博客
  • wish网站应该怎么做网站建设前规划
  • 网站建设目的是什么建筑机械人才培训网官网
  • 建筑建设行业网站大型购物网站开发
  • 手机网站开发用什么设计之家网