第9章 模块的动态加载和系统配置.ppt_第1页
第9章 模块的动态加载和系统配置.ppt_第2页
第9章 模块的动态加载和系统配置.ppt_第3页
第9章 模块的动态加载和系统配置.ppt_第4页
第9章 模块的动态加载和系统配置.ppt_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9章模块的动态加载和系统配置 第9章模块的动态加载和系统配置 本章介绍了Linux内核动态加载功能模块的工作原理 分析了Linux内核中的系统配置结构 解释了Makefile和配置文件的格式以及配置语句的含义 最后给出一个简单的例子 说明如何将自行开发的代码加入到Linux内核中 9 1模块的动态加载 操作系统通常由内核和一些系统服务程序 命令解释 库文件 链接和编译程序等 组成 内核是操作系统的灵魂 它为用户进程提供了一个虚拟机接口 用户进程可以并行运行 公平的占用系统资源而互不干扰 9 1模块的动态加载 操作系统通常由内核和一些系统服务程序 命令解释 库文件 链接和编译程序等 组成 内核是操作系统的灵魂 它为用户进程提供了一个虚拟机接口 用户进程可以并行运行 公平的占用系统资源而互不干扰 从结构上来分 可将操作系统分为微内核结构和单块结构两类 WindowsNT和MINIX是典型的微内核操作系统 而Linux则是单块结构的操作系统 微内核结构可方便地在系统中添加新的组件 而单块结构却不容易做到这一点 为此 Linux系统使用可动态加载和卸载的内核模块 LoadableKernelModules LKMs 可方便地在内核中添加新的组件或卸载不再需要的内核组件 Linux使用insmod来显式加载内核模块 使用rmmod来卸载模块 同时内核自身也可以请求内核后台进程kerneld来加载与卸载模块 Linux模块大多数是设备驱动程序以及伪设备驱动程序模块 如网络设备和文件系统等 动态可加载代码的优点是可以让内核保持很小的尺寸并非常灵活 模块机制可以无需重构内核并频繁重新启动来尝试运行新内核代码 用户可以根据自己系统的需要构筑自己的私有内核 Linux源码的公开更是为改造其内核 重建有特殊要求的操作系统提供了可能 模块必须能够找到其需要使用的内核资源 例如模块需要分配内存时 要调用内核的内存分配例程kmalloc 但在构造模块时并不知道kmalloc 在内存中何处 这样内核必须在使用这些模块前修改模块中对kmalloc 的引用地址 内核在其内核符号表中维护着一个内核资源链表这样当加载模块时它能够解析出模块中对内核资源的引用 Linux还允许存在模块堆栈 它在模块之间相互调用时使用 例如 因为VFAT VirtuaIFileAllocationTable 文件系统是从FAT FileAllocationTable 文件系统中扩展而来 VFAT文件系统模块可能需要FAT文件系统模块的服务 某个模块对其他模块的服务或资源的需求类似于模块对内核本身资源或服务的请求 不过此时所请求的服务是来自另外一个事先已加载的模块 当加载模块时 内核就把新近加载模块输出的所有资源和符号添加到内核符号表 Kernel Symbol Table 中 在 proc ksyms 里面的每一个表项代表着一个公共的内核符号 这就是内核符号表 这些内核符号是可以被LKM引用的 LKM中所存取的每一个符号 像函数名 也会被列在这个文件里面 在该文件中可以看到LKM到底可以调用那些函数 当试图卸载某个模块时 内核需要知道此模块是否已经没有被使用 同时它需要有种方法来通知此将卸载模块 模块必须能够在从内核种删除之前释放其分配的所有系统资源 如内核内存或中断 当模块被卸载时 内核将从内核符号表中删除所有与之对应的符号 但是 内核模块的引入也带来了如下问题 但是 内核模块的引入也带来了如下问题 1 有可能同时带来与内核模块相关的性能与内存损失 可加载模块的代码一般较长 且额外的数据结构可能会占据一些内存 对内核资源的间接使用也可能带来效率方面的问题 对系统性能和内存利用有负面影响 但是 内核模块的引入也带来了如下问题 1 有可能同时带来与内核模块相关的性能与内存损失 可加载模块的代码一般较长 且额外的数据结构可能会占据一些内存 对内核资源的间接使用也可能带来效率方面的问题 对系统性能和内存利用有负面影响 2 一旦Linux模块被加载 则和普通内核代码一样成为内核的一部分 具有与其他内核代码相同的权限与职责 因此 Linux内核模块也可以象所有内核代码和设备驱动一样使内核崩溃 但是 内核模块的引入也带来了如下问题 1 有可能同时带来与内核模块相关的性能与内存损失 可加载模块的代码一般较长 且额外的数据结构可能会占据一些内存 对内核资源的间接使用也可能带来效率方面的问题 对系统性能和内存利用有负面影响 2 一旦Linux模块被加载 则和普通内核代码一样成为内核的一部分 具有与其他内核代码相同的权限与职责 因此 Linux内核模块也可以象所有内核代码和设备驱动一样使内核崩溃 3 为了内核模块访问所有内核资源 内核必须维护符号表 并在装入和卸载模块时修改这些符号表 但是 内核模块的引入也带来了如下问题 1 有可能同时带来与内核模块相关的性能与内存损失 可加载模块的代码一般较长 且额外的数据结构可能会占据一些内存 对内核资源的间接使用也可能带来效率方面的问题 对系统性能和内存利用有负面影响 2 一旦Linux模块被加载 则和普通内核代码一样成为内核的一部分 具有与其他内核代码相同的权限与职责 因此 Linux内核模块也可以象所有内核代码和设备驱动一样使内核崩溃 3 为了内核模块访问所有内核资源 内核必须维护符号表 并在装入和卸载模块时修改这些符号表 4 有些模块要求利用其他模块的功能 因此 内核要维护模块之间的依赖性 5 内核必须能够在卸载模块时通知模块 并且要释放分配给模块的内存和中断等资源 6 内核版本和模块版本的不兼容 也可能导致系统崩溃 因此 严格的版本检查是必需的 9 1 1模块的加载 9 1 1模块的加载 有两种方法可用来加载模块 1 利用insmod命令手工将模块插入内核 9 1 1模块的加载 有两种方法可用来加载模块 1 利用insmod命令手工将模块插入内核 2 由内核在必要时加载模块 称为 需求加载 当内核发现有必要加载某个模块时 如用户安装了内核中不存在的文件系统时 内核将请求内核后台进程 kerneld 准备加载适当的模块 这个内核后台进程仅仅是一个带有超级用户权限的普通用户进程 当系统启动时它也被启动并为内核打开了一个进程间通讯 IPC 通道 内核可以利用该通道向Kerneld进程发送任务的执行请求 Kerneld进程的主要功能是加载和卸载模块 另外 该进程也负责其他一些任务 例如打开和关闭PPP链接等 kerneld自身并不执行这些任务 它通过某些程序如insmod来做此工作 因此 该进程实际是代表内核进行调度的代理 执行insmod命令时 必须指定要加载模块的位置 对需求加载的内核模块 通常保存在 lib modules kernel version 和系统的其他程序一样 内核模块实际是经连接的目标文件 但模块是可重定位的 也就是说 为了让装入的模块和已有的内核组件之间可以互相访问 模块不能连接为从特定地址执行的映像文件 模块可以是a out或elf格式的目标文件 insmod利用一个特权系统调用 可找到内核的导出符号表 符号成对出现 一个是符号名称 另外一个是符号的值 例如符号的地址 内核维护一个由module list指针指向的module链表 其中第一个module数据结构保存有内核的导出符号表 见图9 1 并不是所有的内核符号均在符号表中导出 而只有一些特殊的符号才被添加到符号表中 例如 request irq 是一个导出符号 它是一个内核例程 可由驱动程序申请控制某个特定的系统中断 利用ksyms命令或查看 proc ksyms文件内容 可非常方便地看到所有的内核导出符号及其符号值 利用ksyms命令 不仅可以看到内核的所有符号 也可以看到只由以加载模块导出的符号 insmod命令将模块读到它本身的虚拟内存中 然后利用内核导出的符号表 修正尚未解析的对内核例程的引用 这种修正实际是对模块在内存中的映像进行修正 insmod将符号的地址写入模块中适当的位置而实现修正 图9 1装入VFAT和FAT之后的内核模块表 insmod命令修正模块对内核符号的引用之后 再次利用特权系统调用请求内核分配足够的物理内存空间保存新的模块 内核将分配新的module数据结构以及足够的内核内存 并将新模块添加在内核模块表的末尾 新的内核模块标记为Uninitialized 未初始化 图9 1是装入VFAT和FAT模块之后的内核模块表 图中并没有表示出第一个模块 它实际是一个伪模块 仅仅用来保存内核的导出符号表 利用lsmod命令可列出所有已加载的内核模块以及它们的内在依赖性 内核为新模块分配的内核内存映射到insmod进程的地址空间中 这样 insmod就可以将模块复制到新分配的内存中 insmod还对模块进行重新定位 经重定位之后 新的模块就可以从新分配的内核地址开始运行了 显然 模块不能期望自己能够在不同的Linux系统 或前后两次装入时被加载到相同地址 重定位操作可通过对模块映像中适当的地址进行修正而解决这一问题 新的模块也要向内核导出符号 由insmod建立相应的符号表 每个内核模块必须包含模块的初始化和清除例程 这些例程作为每个模块均具备的例程而不被导出 但insmod必须知道它们的地址 并将地址传递给内核 insmod同样利用特权系统调用将模块的初始化和清除例程地址传递给内核 新的模块添加到内核之后 它必须更新内核符号集并修改使用新模块的模块 由其他模块依赖的模块必须在自身符号表的末尾维护一个引用表 并指向其他模块的module结构 例如 图9 1表明VFAT文件系统模块依赖于FAT文件系统模块 因此 FAT模块包含一个对VFAT模块的引用 该引用在装入VFAT模块时添加 内核成功调用模块的初始化例程之后继续模块的安装 最后 模块状态被设置为Running 运行 模块的清除例程保存在module数据结构中 在卸载模块时由内核调用 9 1 2模块的卸载 和模块的加载类似 可利用rmmod命令手工卸载模块 当对需求加载的模块则由kerneld在不再需要时自动卸载 每次kerneld的空闲定时器到期时 它会利用系统调用将当前不再使用的需求加载模块从内核中移走 启动kerneld时指定该定时器的时间 通常的时间为180秒 如果内核的其他部分依赖于装入的模块时 该模块不能卸载 例如 如果挂装了FAT文件系统 则不能卸载已装入的FAT文件系统模块 lsmod命令的输出会显示已安装模块的使用计数 例如 Module pages Usedby msdos51vfat41 autoclean fat62 autoclean 使用计数就是依赖于该模块的内核实体个数 模块的使用计数保存在模块映像的第一个长整型中 但是 这一长整型中还包含有AUTOCLEAN和VISITED标志 这两个标志均由需求加载的模块使用 具有AUTOCLEAN标志的模块是系统认为可以自动卸载的模块 具有VISITED标志的模块表明正由其他内核组件使用 当任何其他内核组件使用该模块是设置该标志 当kerneld请求系统移走不使用的需求加载模块时 系统首先寻找可以移走的模块 但系统只查看标记为AUTOCLEAN 并且状态处于RUNNING的模块 如果上述模块的VISITED标志被清除 则系统将卸载该模块 否则系统会清除VISITED标志并查看下一个模块 假定某个模块是可卸载的 则系统调用其清除例程释放分配该模块的内核资源 相应的module数据结构被标志为DELETED并从内核模块链表中断开 所有由该模块依赖的模块 系统会修改它们的引用表以便取消依赖性 最后 系统释放模块的内核内存 9 1 3内核模块的管理 9 1 3内核模块的管理 在Linux里 除了直接修改系统核心的源代码 把设备驱动程序加进核心里以外 还可以把设备驱动程序作为可加载的模块 由系统管理员动态地加载它 使之成为核心的一部分 也可以由系统管理员把已加载地模块动态地卸载下来 Linux的模块可以用C语言编写 用gcc编译成目标文件 不进行链接 作为 o文件存在 为此需要在gcc命令行里加上 c的参数 在编译时 还应该在gcc的命令行里加上这样的参数 D KERNEL DMODULE 由于在不链接时 gcc只允许一个输入文件 因此一个模块的所有部分都必须在一个文件里实现 编译好的模块 o放 lib modules xxxx misc下 xxxx表示核心版本 如在核心版本为2 0 30时应该为 lib modules 2 0 30 misc 然后用depmod a使此模块成为可加载模块 模块用insmod命令加载 用rmmod命令来卸载 并可以用lsmod命令来查看所有已加载的模块的状态 利用insmod命令可手工装入内核模块 利用lsmod可查看当前装入的内核模块以及需求加载模块的使用计数及标志信息 利用rmmod则可以卸载指定的模块 编写模块程序的时候 必须提供两个函数 一个是intinit module void 供insmod在加载此模块的时候自动调用 负责进行设备驱动程序的初始化工作 init module返回0以表示初始化成功 返回负数表示失败 另一个函数是voidcleanup module void 在模块被卸载时调用 负责进行设备驱动程序的清除工作 在成功的向系统注册了设备驱动程序后 调用register chrdev成功后 就可以用mknod命令来把设备映射为一个特别文件 其它程序使用这个设备的时候 只要对此特别文件进行操作就行了 9 2Linux内核配置系统 随着Linux操作系统的广泛应用 特别是Linux在嵌入式领域的发展 越来越多的人开始投身到Linux内核级的开发中 面对日益庞大的Linux内核源代码 开发者在完成自己的内核代码后 都将面临着同样的问题 即如何将源代码融入到Linux内核中 增加相应的Linux配置选项 并最终被编译进Linux内核 这就需要了解Linux的内核配置系统 Linux内核是由分布在全球的Linux爱好者共同开发的 Linux内核每天都面临着许多新的变化 但是 Linux内核的组织并没有出现混乱的现象 反而显得非常的简洁 而且具有很好的扩展性 开发人员可以很方便的向Linux内核中增加新的内容 原因之一就是Linux采用了模块化的内核配置系统 从而保证了内核的扩展性 9 2 1配置系统的基本结构 9 2 1配置系统的基本结构 Linux内核的配置系统由三个部分组成 1 Makefile 分布在Linux内核源代码中的Makefile定义Linux内核的编译规则 2 配置文件 config in 给用户提供配置选择的功能 3 配置工具 包括配置命令解释器 对配置脚本中使用的配置命令进行解释 和配置用户界面 提供基于字符界面 基于Ncurses图形界面以及基于Xwindows图形界面的用户配置界面 各自对应于Makeconfig Makemenuconfig和Makexconfig 这些配置工具都是使用脚本语言 如Tcl TK Perl编写的 也包含一些用C编写的代码 除非是配置系统的维护者 一般的内核开发者无须了解配置系统的原理 只需要知道如何使用配置系统 如何编写Makefile和配置文件就可以 所以 本节只对Makefile和配置文件进行讨论 凡是涉及到与具体CPU体系结构相关的内容 都以ARM为例 这样不仅可以将讨论的问题明确化 而且对内容本身不产生影响 9 2 2Makefile Makefile的作用是根据配置的情况 构造出需要编译的源文件列表 然后分别编译 并把目标代码链接到一起 最终形成Linux内核二进制文件 由于Linux内核源代码是按照树形结构组织的 所以Makefile也被分布在目录树中 Linux内核中的Makefile以及与Makefile直接相关的文件有 Makefile 顶层Makefile 是整个内核配置 编译的总体控制文件 config 内核配置文件 包含由用户选择的配置选项 用来存放内核配置后的结果 如makeconfig arch Makefile 位于各种CPU体系目录下的Makefile 如arch arm Makefile 是针对特定平台的Makefile 各个子目录下的Makefile 比如drivers Makefile 负责所在子目录下源代码的管理 Rules make 规则文件 被所有的Makefile使用 用户通过makeconfig配置后 产生了 config 顶层Makefile读入 config中的配置选择 顶层Makefile有两个主要的任务 产生vmlinux文件和内核模块 module 为了达到此目的 顶层Makefile递归的进入到内核的各个子目录中 分别调用位于这些子目录中的Makefile 至于到底进入哪些子目录 取决于内核的配置 在顶层Makefile中 有一句 includearch ARCH Makefile 包含了特定CPU体系结构下的Makefile 这个Makefile中包含了平台相关的信息 位于各个子目录下的Makefile同样也根据 config给出的配置信息 构造出当前配置下需要的源文件列表 并在文件的最后有include TOPDIR Rules make Rules make文件起着非常重要的作用 它定义了所有Makefile共用的编译规则 比如 如果需要将本目录下所有的c程序编译成汇编代码 需要在Makefile中有以下的编译规则 s c CC CFLAGS S o 有很多子目录下都有同样的要求 就需要在各自的Makefile中包含此编译规则 这会比较麻烦 而Linux内核中则把此类的编译规则统一放置到Rules make中 并在各自的Makefile中包含进了Rules make includeRules make 这样就避免了在多个Makefile中重复同样的规则 对于上面的例子 在Rules make中对应的规则为 s c CC CFLAGS EXTRA CFLAGS CFLAGS F CFLAGS S o Makefile中的变量顶层Makefile定义并向环境中输出了许多变量 为各个子目录下的Makefile传递一些信息 有些变量 比如SUBDIRS 不仅在顶层Makefile中定义并且赋初值 而且在arch Makefile还作了扩充 常用的变量有以下几类 1 版本信息版本信息有 VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION和KERNELRELEASE 版本信息定义了当前内核的版本 例如VERSION 2 PATCHLEVEL 4 SUBLEVEL 18 EXATAVERSION rmk7 它们共同构成内核的发行版本KERNELRELEASE 2 4 18 rmk7 2 CPU体系结构 ARCH在顶层Makefile的开头 用ARCH定义目标CPU的体系结构 比如ARCH arm等 许多子目录的Makefile中 要根据ARCH的定义选择编译源文件的列表 3 路径信息 TOPDIR和SUBDIRSTOPDIR定义了Linux内核源代码所在的根目录 例如 各个子目录下的Makefile通过 TOPDIR Rules make就可以找到Rules make的位置 SUBDIRS定义了一个目录列表 在编译内核或模块时 顶层Makefile就是根据SUBDIRS来决定进入哪些子目录 SUBDIRS的值取决于内核的配置 在顶层Makefile中SUBDIRS赋值为kerneldriversmmfsnetipclib 根据内核的配置情况 在arch Makefile中扩充了SUBDIRS的值 4 内核组成信息 HEAD CORE FILES NETWORKS DRIVERS LIBSLinux内核文件vmlinux是由以下规则产生的 vmlinux CONFIGURATION init main oinit version olinuxsubdirs LD LINKFLAGS HEAD init main oinit version o start group CORE FILES DRIVERS NETWORKS LIBS end group ovmlinux可以看出 vmlinux是由HEAD main o version o CORE FILES DRIVERS NETWORKS和LIBS组成的 这些变量 如HEAD 都是用来定义连接生成vmlinux的目标文件和库文件列表 其中 HEAD在arch Makefile中定义 用来确定被最先链接进vmlinux的文件列表 例如 对于ARM系列的CPU HEAD定义为 HEAD arch arm kernel head PROCESSOR o arch arm kernel init task o表明head PROCESSOR o和init task o需要最先被链接到vmlinux中 PROCESSOR为armv或armo 取决于目标CPU CORE FILES NETWORK DRIVERS和LIBS在顶层Makefile中定义 并且由arch Makefile根据需要进行扩充 CORE FILES对应着内核的核心文件 有kernel kernel o mm mm o fs fs o ipc ipc o 可以看出 这些是组成内核最为重要的文件 同时 arch arm Makefile对CORE FILES进行了扩充 arch arm Makefile Ifwehaveamachine specificdirectory thenincludeitinthebuild MACHDIR arch arm mach MACHINE ifeq MACHDIR wildcard MACHDIR SUBDIRS MACHDIR CORE FILES MACHDIR MACHINE o CORE FILES endifHEAD arch arm kernel head PROCESSOR o arch arm kernel init task oSUBDIRS arch arm kernelarch arm mmarch arm libarch arm nwfpeCORE FILES arch arm kernel kernel oarch arm mm mm o CORE FILES LIBS arch arm lib lib a LIBS 5 编译信息 CPP CC AS LD AR CFLAGS LINKFLAGS在Rules make中定义的是编译的通用规则 具体到特定的场合 需要明确给出编译环境 编译环境就是在以上的变量中定义的 针对交叉编译的要求 定义了CROSS COMPILE 如 CROSS COMPILE arm linux CC CROSS COMPILE gccLD CROSS COMPILE ld CROSS COMPILE定义了交叉编译器前缀arm linux 表明所有的交叉编译工具都是以arm linux 开头的 所以在各个交叉编译器工具之前 都加入了 CROSS COMPILE 以组成一个完整的交叉编译工具文件名 比如arm linux gcc CFLAGS定义了传递给C编译器的参数 LINKFLAGS是链接生成vmlinux时 由链接器使用的参数 LINKFLAGS在arm Makefile中定义 如 arch arm MakefileLINKFLAGS p X Tarch arm vmlinux lds 6 配置变量CONFIG config文件中有许多的配置变量等式 用来说明用户配置的结果 例如CONFIG MODULES y表明用户选择了Linux内核的模块功能 config被顶层Makefile包含后 就形成许多的配置变量 每个配置变量具有确定的值 y表示本编译选项对应的内核代码被静态编译进Linux内核 m表示本编译选项对应的内核代码被编译成模块 n表示不选择此编译选项 如果根本就没有选择 那么配置变量的值为空 2 Rules make变量Rules make是编译规则文件 所有的Makefile中都会包括Rules make Rules make文件定义了许多变量 最为重要是那些编译 链接列表变量 O OBJS L OBJS OX OBJS LX OBJS 本目录下需要编译进Linux内核vmlinux的目标文件列表 其中OX OBJS和LX OBJS中的 X 表明目标文件使用了EXPORT SYMBOL输出符号 M OBJS MX OBJS 本目录下需要被编译成可装载模块的目标文件列表 同样 MX OBJS中的 X 表明目标文件使用了EXPORT SYMBOL输出符号 O TARGET L TARGET 每个子目录下都有一个O TARGET或L TARGET Rules make首先从源代码编译生成O OBJS和OX OBJS中所有的目标文件 然后使用 LD r把它们链接成一个O TARGET或L TARGET O TARGET以 o结尾 而L TARGET以 a结尾 3 Makefile子目录 3 Makefile子目录 子目录Makefile用来控制本级目录以下源代码的编译规则 下面通过一个例子来讲解子目录Makefile的组成 Makefileforthelinuxkernel Allofthe potential objectsthatexportsymbols Thislistcomesfrom grep lEXPORT SYMBOL hc export objs tc o Objectfilelists obj y obj m obj n obj obj CONFIG TC tc oobj CONFIG ZS zs oobj CONFIG VT lk201 olk201 map olk201 remap o Filesthatarebothresidentandmodular removefrommodular obj m filter out obj y obj m TranslatetoRules makelists L TARGET tc aL OBJS sort filter out export objs obj y LX OBJS sort filter export objs obj y M OBJS sort filter out export objs obj m MX OBJS sort filter export objs obj m include TOPDIR Rules make 1 注释对Makefile的说明和解释 由 开始 2 编译目标定义类似于obj CONFIG TC tc o的语句是用来定义编译的目标 是子目录Makefile中最重要的部分 编译目标定义那些在本子目录下 需要编译到Linux内核中的目标文件列表 为了只在用户选择了此功能后才编译 所有的目标定义都融合了对配置变量的判断 前面说过 每个配置变量取值范围是 y n m和空 obj CONFIG TC 分别对应着obj y obj n obj m obj 如果CONFIG TC配置为y 那么tc o就进入了obj y列表 obj y为包含到Linux内核vmlinux中的目标文件列表 obj m为编译成模块的目标文件列表 obj n和obj 中的文件列表被忽略 配置系统就根据这些列表的属性进行编译和链接 export objs中的目标文件都使用了EXPORT SYMBOL 定义了公共的符号 以便可装载模块使用 在tc c文件的最后部分 有 EXPORT SYMBOL search tc card 表明tc o有符号输出 这里需要指出的是 对于编译目标的定义 存在着两种格式 分别是老式定义和新式定义 老式定义就是前面Rules make使用的那些变量 新式定义就是obj y obj m obj n和obj Linux内核推荐使用新式定义 不过由于Rules make不理解新式定义 需要在Makefile中的适配段将其转换成老式定义 3 适配段适配段的作用是将新式定义转换成老式定义 在上面的例子中 适配段就是将obj y和obj m转换成Rules make能够理解的L TARGET L OBJS LX OBJS M OBJS MX OBJS L OBJS sort filter out export objs obj y 定义了L OBJS的生成方式 在obj y的列表中过滤掉export objs tc o 然后排序并去除重复的文件名 这里使用到了GNUMake的一些特殊功能 具体的含义可参考Make的文档 infomake 4 include TOPDIR Rules make 9 2 3配置文件 9 2 3配置文件 除了Makefile的编写 另外一个重要的工作就是把新功能加入到Linux的配置选项中 提供此项功能的说明 让用户有机会选择此项功能 所有的这些都需要在config in文件中用配置语言来编写配置脚本 在Linux内核中 配置命令有多种方式 以字符界面配置 makeconfig 为例 顶层Makefile调用scripts Configure 按照arch arm config in来进行配置 命令执行完后产生文件 config 其中保存着配置信息 下一次再做makeconfig将产生新的 config文件 原 config被改名为 config old 1 配置语言 1 顶层菜单mainmenu name prompt prompt 是用 或 包围的字符串 与 的区别是 中可使用 引用变量的值 mainmenu name设置最高层菜单的名字 它只在makexconfig时才会显示 2 询问语句bool prompt symbol hex prompt symbol word int prompt symbol word string prompt symbol word tristate prompt symbol 询问语句首先显示一串提示符 prompt 等待用户输入 并把输入的结果赋给 symbol 所代表的配置变量 不同的询问语句的区别在于它们接受的输入数据类型不同 比如bool接受布尔类型 y或n hex接受16进制数据 有些询问语句还有第三个参数 word 用来给出默认值 3 定义语句define bool symbol word define hex symbol word define int symbol word define string symbol word define tristate symbol word 不同于询问语句等待用户输入 定义语句显式的给配置变量 symbol 赋值 word 3 定义语句define bool symbol word define hex symbol word define int symbol word define string symbol word define tristate symbol word 不同于询问语句等待用户输入 定义语句显式的给配置变量 symbol 赋值 word 4 依赖语句dep bool prompt symbol dep dep mbool prompt symbol dep dep hex prompt symbol word dep dep int prompt symbol word dep dep string prompt symbol word dep dep tristate prompt symbol dep 与询问语句类似 依赖语句也是定义新的配置变量 不同的是 配置变量 symbol 的取值范围将依赖于配置变量列表 dep 这就意味着 被定义的配置变量所对应功能的取舍取决于依赖列表所对应功能的选择 以dep bool为例 如果 dep 列表的所有配置变量都取值y 则显示 prompt 用户可输入任意的值给配置变量 symbol 但是只要有一个配置变量的取值为n 则 symbol 被强制成n 不同依赖语句的区别在于它们由依赖条件所产生的取值范围不同 5 选择语句choice prompt word word choice语句首先给出一串选择列表 供用户选择其中一种 比如LinuxforARM支持多种基于ARMcore的CPU Linux使用choice语句提供一个CPU列表 供用户选择 choice ARMsystemtype AnakinCONFIG ARCH ANAKIN Archimedes A5000CONFIG ARCH ARCA5K Cirrus CL PS7500FECONFIG ARCH CLPS7500 SA1100 basedCONFIG ARCH SA1100 SharkCONFIG ARCH SHARK RiscPCChoice首先显示 prompt 然后将 word 分解成前后两个部分 前部分为对应选择的提示符 后部分是对应选择的配置变量 用户选择的配置变量为y 其余的都为n 6 if语句if expr then statement fiif expr then statement else statement fiif语句对配置变量 或配置变量的组合 进行判断 并作出不同的处理 判断条件 expr 可以是单个配置变量或字符串 也可以是带操作符的表达式 操作符有 o a等 7 菜单块 menublock 语句mainmenu optionnext commentcomment endmenu引入新的菜单 在向内核增加新的功能后 需要相应的增加新的菜单 并在新菜单下给出此项功能的配置选项 Comment后带的注释就是新菜单的名称 所有归属于此菜单的配置选项语句都写在comment和endmenu之间 8 Source语句source word word 是文件名 source的作用是调入新的文件 2 默认配置Linux内核支持非常多的硬件平台 对于具体的硬件平台来说 有些配置是必需的 有些配置却不是必需的 此外 新增加功能的正常运行往往也需要一定的先决条件 因此 特定硬件平台能够正常运行对应着一个最小的基本配置 这就是默认配置 Linux内核中针对每个ARCH都会有一个默认配置 在向内核代码增加了新的功能后 如果新功能对于这个ARCH是必需的 就要修改此ARCH的默认配置 修改方法如下 在Linux内核根目录下 备份 config文件cparch arm deconfig config修改 configcp configarch arm deconfig恢复 config如果新增的功能适用于许多的ARCH 只要针对具体的ARCH 重复上面的步骤就可以了 3 帮助信息在配置Linux内核时 遇到不懂含义的配置选项 可以查看它的帮助 从中可得到选择的建议 下面介绍如何给一个配置选项增加帮助信息 所有配置选项的帮助信息都在Documentation Configure help中 它的格式为 给出本配置选项的名称 对应配置变量 对应配置帮助信息 在帮助信息中 首先简单描述此功能 其次说明选择了此功能后会有什么效果 不选择又有什么效果 最后 不要忘了写上 如果不清楚 选择N 或者 Y 给不知所措的用户以提示 9 2 4配置实例 9 2 4配置实例 对于一个开发者来说 将自己开发的内核代码加入到Linux内核中 需要有三个步骤 首先确定把自己开发代码放入到内核的位置 其次 把自己开发的功能增加到Linux内核的配置选项中 使用户能够选择此功能 最后 构建子目录Makefile 根据用户的选择 将相应的代码编译到最终生成的Linux内核中去 下面通过一个简单的例子 testdriver 说明如何向Linux内核中增加新的功能 1 目录结构testdriver放置在drivers test 目录下 cddrivers test tree Config in Makefile cpu Makefile cpu c test c test client c test ioctl c test proc c test queue c test Makefile test c 2 配置文件 1 drivers test Config in TESTdriverconfiguration mainmenu optionnext commentcomment TESTDriver bool TESTsupport CONFIG TESTif CONFIG TEST y thentristate TESTuser spaceinterface CONFIG TEST USERbool TESTCPU CONFIG TEST CPUfiEndmenu由于testdriver对于内核来说是新的功能 所以首先创建一个菜单TESTDriver 然后 显示 TESTsupport 等待用户选择 接下来判断用户是否选择了TESTDriver 如果是 CONFIG TEST y 则进一步显示子功能 用户接口与CPU功能支持 由于用户接口功能可以被编译成内核模块 所以这里的询问语句使用了tristate 因为tristate的取值范围包括y n和m m就是对应着模块 2 配置文件 2 arch arm config in在文件的最后加入 sourcedrivers test Config in 将TESTDriver子功能的配置纳入到Linux内核的配置中 3 Makefile 1 drivers test Makefile drivers test Makefile MakefilefortheTEST SUB DIRS MOD SUB DIRS SUB DIRS ALL SUB DIRS SUB DIRS cpuL TARGET test aexport objs test otest client oobj CONFIG TEST test otest queue otest client oobj CONFIG TEST USER test ioctl oobj CONFIG PROC FS test proc osubdir CONFIG TEST CPU cpuinclude TOPDIR Rules makeclean fordirin ALL SUB DIRS domake C dirclean donerm f oa flags d

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论