VxWorks kernal programmers guide

更新时间:2023-11-30 02:08:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

VxWorks Kernal Programmer’s Guide

第一部分:核心技术

1 概述

2 VxWorks配置

2.1 介绍

VxWorks是一个高可扩展性的操作系统,可以针对不同目的是要独立组件工具包轻松配置。VxWorks的定制版本也可以被创建,用于配置的备选项。本章讨论了基本的VxWorks配置,和小型化VxWorks配置,电源管理设施,和可以产生的VxWorks系统镜像类型。

2.2 关于VxWorks配置

VxWorks是一个灵活的可扩展的带多个设备的操作系统,这些设备可以包含,删除,不同配置,使用定制技术扩展,根据应用和系统需要,和开发周期不同阶段。默认的Vxworks镜像提供最初开发使用。

配置VxWorks的主要方式是VIPs和VSBs。风河Workbench开发套装和vxprj命令行配置工具可以用于和这些工程类型工作。关于风河Workbench和vxprj更多信息,参考Wind River Workbench by Example guide和VxWorks Command-Line Tools User’s Guide。

2.2.1 默认配置和镜像

VxWorks发布包括针对每个支持的BSP的默认系统镜像。每个系统镜像时一个可以引导好运行在目标系统上的二进制模块。一个系统镜像包括一组链接到一块的一组组件形成一个单一的不可移动的带已解决外部引用的对象模块。

默认的系统镜像设计用于开发环境。它们包含使用主机开发工具用于和系统交互的一组组件组成。大多数情况下,会为最初的系统开发提供足够的系统镜像(提供默认的驱动)。使用一个默认Vxworks镜像,你可以交互下载,且运行内核应用。

关于设置开发环境相关信息,参考Wind River Workbench by Example guide。关于VxWorks镜像类型信息,参考2.7 VxWorks Image Types。

2.2.2 VIP配置

VxWorks镜像工程用于配置不同组件组成的系统。VxWorks组件提供基于预编译库(归档文件)的操作系统工具单元,预编译库是通过特征引用的方式连接到系统中。关于VIPs更多信息,参考2.3 VxWorks Image Projects: VIPs。

2.2.3 VSB配置

对于有严格性能要求或资源限制的系统,VSB工程可以用于创建专门(频率较低的)的VxWorks库版本,和用于多样化优化。VSB选项和关联的条件化代码提供配置源代码基本的方法。一旦VxWorks库源码重新编译,一个VIP工程可以用于配置系统本身。关于VSB更多信息,参考2.4 VxWorks Source Build Projects: VSBs。

2.2.4 配置和定制

若由风河提供的VxWorks组件不提供你的系统要求的功能,你可以创建定制设备,如新的文件系统和网络协议,和组件包(参考20. Custom Components and CDFs),基于进程应用增加系统调用(参考21. Custom System Calls),创建你自己的调度(参考22. Custom Scheduler)。

2.2.5 配置工具:Workbench和vxprj

针对VIP和VSB提供的开发工具有风河Workbench开发套装和vxprj命令行配置工具。Workbench和vxprj可以用于配置和编译VxWorks系统,和其它管理VIP,VSB和其它类型的工程。

关于如何使用Workbench和vxprj,参考Wind River Workbench by Example和VxWorks Command-Line Tools User’s Guide。

2.3 VIPs

VxWorks镜像工程用于使用不同组件配置VxWorks系统。VxWorks组件提供基于预编译库的操作系统单元,预编译库通过特征引用的方法链接到一个系统中。VIP可能基于一个默认VxWorks配置或配置原型。配置原型提供设计用于具体目的的一组组件组成,如开发环境,DO-178B验证等。另外组件包用于使用一组组件配置系统,如那些提供POSIX支持的组件。

在开发周期过程中你可能想重新配置和重新编译VxWorks和专门选择用于支持应用开发需求的组件。如,你可能想保护内核shell和错误检测和报告工具,和删除包含在默认系统镜像中的其他组件。

对于生产系统,你将想重新配置VxWorks,仅需要操作过程中使用的组件,编译为合适的系统镜像类型(参考2.7 VxWorks Image Types)。你可能想删除针对主机开发需要的组件,如WDB

target agent和debugging components (INCLUDE_WDB and INCLUDE_DEBUG),和删除 支持其他操作系统的组件,应用不需要的组件,加速启动时间,和安全问题。

风河Workbench和vxprj命令行工具可以用于配置VxWorks,基于组件选择和删除。Workbench 配置工具展示了包含组件的图形化信息,和其他系统相关的信息。Vxprj工具也可以用于列出各种类型的组件信息。另外,VxWorks Component Reference提供所有组件和它们的参数,包,原型等的详细信息。(更多信息,参考2.3.1 VxWorks Components,2.3.3 Component Bundles and Configuration Profiles,和2.3.4 VxWorks Component Reference。)

2.3.1 VxWorks组件

一个VxWorks组件是VxWorks可以配置的基本功能单元。设计用于实时系统的组件,强调确定性和性能。每个组件提供一个或多个预编译静态库(归档文件),通常有一个或多个配置参数。组件通过特征引用的方法链接到系统中。

而一些组件是独立的,其它组件是有依赖性的,依赖的组件在运行时也必须包含在操作系统中。内核shell是一个依赖多个组件的组件。特征表是一个组件依赖其它组件的例子(内核shell和模块loader;更多信息,参考16. Kernel Shell and Loader)。组件依赖由VxWorks内核配置工具自动确定(风河Workbench和vxprj命令行工具)。

组件名

VxWorks组件使用CDFs文件packaged,用以INCLUDE_开始的宏名识别组件,和用户友好的描述。(关于配置文件的信息,参考20Custom Components and CDFs)

名,描述,配置VxWorks组件功能可以在Workbench中用GUI配置工具显示。Workbench为配置VxWorks选择组件提供了工具,设置组件参数,和配置和编译过程中组件间依赖关

系的自动确认机制。

命令行操作系统配置工具——vxprj——使用源于配置宏的命名传统来识别独立的操作系统组件。规范标识组件名称以INCLUDE开始。如,INCLUDE_MSG_Q是消息队列组件。除了配置工具vxprj工具提供了列举包含在工程中组件信息功能,配置参数等。

注:本书中,组件通过宏名识别。GUI配置工具提供了查找组件的功能。 基本的VxWorks组件

Table 2-1描述了VxWorks通用组件。名称以XXX结尾的表数组件家族,XXX由独立组件名的一个前缀代替。如INCLUDE_CPLUS_XXX,指包含INCLUDE_CPLUS_MIN和其它的组件家族。

Table 2-1注明的不包含VxWorks默认配置的所有组件。所有组件和参数的详细信息,参考VxWorks Component Reference。

2.3.2 设备驱动选择

设备驱动可以用Workbench和vxprj为系统增加或删除组件。一些驱动是VxBus兼容的,其它(传统驱动)不是。

注明仅VxBus兼容驱动可以用于SMP配置。关于VxWorks SMP和移植相关信息,参考24. VxWorks SMP和24.17 Migrating Code to VxWorks SMP。

注明VxBus驱动组件名不需要INCLUDE_元素(如DRV_SIO_NS16550),而非VxBus驱动使用INCLUDE_元素(如INCLUDE_ELT_3C509_END)。

关于VxBus设备驱动基础设施相关信息,参考VxWorks Device Driver Developer’s Guide。

2.3.3 组件包和组件原型

除了基本的VxWorks组件,组件包和用于配置VxWorks的配置原型。

组件包是管理组件组,可以做为一个单元增加到系统(如,BUNDLE_POSIX提供内核POSIX支持需要的所有组件)。

原型提供了一个操作系统功能基线,提供一个方便的方法,和VxWork生产安装默认配置不一样。原型如下:

PROFILE_SMALL_FOOTPRINT——VxWorks Small Footprint Profile,为必须的最小内核公共提供基本配置,和一个要求的小型化内存。

PROFILE_COMPATIBLE——VxWorks 5.5 Compatible Profile,提供兼容VxWorks 5.5 最小配置。

PROFILE_DEVELOPMENT——VxWorks内核开发原型,提供一个VxWorks内核,包含开发和调试组件,包含实时进程的支持。

PROFILE_ENHANCED_NET——VxWorks增强网络原型。为经典管理网络客户端工具设备增加合适组件到默认原型。增加的主要组件是CHCP客户端和DNS服务器,telnet服务器(不包含shell),和几个命令行式样配置工具。

PROFILE_CERT——VxWorks DO-178认证原型。提供VxWorks操作系统的一个DO-178验证API组。

PROFILE_BOOTAPP——VxWorks boot loader原型,为一个Vxworks boot loader提供工具。

更多信息,参考3.7 Configuring and Building Boot Loaders。

关于所有组件包和原型信息,参考VxWorks Component Reference。

2.3.4 VxWorks组件引用

关于所有VxWorks组件和太慢的参数,组件包,原型更详细的引用信息,参考VxWorks Component Reference。

2.4 VSBs

标准VxWorks组件设计用于实时系统,强调确定性和性能。它们提供了预编译库,通过特征引用的方法链接到系统中。这是对于提供快速构建比较方便,意味着可以构建更大,更具通用目的的库,不需要为了适应一个系统的需求针对大小和性格有非常严格的要求。

对于有严格性能需求和资源限制的系统,VSB工程可以用于创建专门的VxWorks库版本,并可以使用不同的优化。库基于用户不同的选择有条件的编译。一些情况下,一个VSB工程产生的库提供一个APIs子组,由标准的VxWorks组件提供,或其他有一些不同的行为。它们会提高性能,因为他们仅执行定义的一组代码。

为了在Vxworks系统中使用库版本和优化,一个VIP工程随后被创建,关联一个VSB工程。VIP工程之后用于配置VxWorks本身。

VSB选项和关联的条件代码针对源代码基本的配置提供方法。VSB工程工具提供的主要选项种类包括如下:

? 组件基本的非离散可配置功能选项(包括跨库和组件的功能)。如,系统可视化工具。

? 编译优化选项。如,浮点数支持。

? 多处理器系统相关选项。如为SMP VxWorks配置指定库。

? 用于构建功能库选项,通过源码传递(如不同的网络和中间件工具)。 VSB选择控制基于库代码条件编译的VxWorks功能增加和删除。基于VSB工程的系统可以像小型化系统一样提高系统性能,因为它们会删除系统不需要的代码,只留下执行的嗲吗。另外它们还充分使用专门优化。(如,cache模式)

Figure 2-1展示了VSB工程如何用于删除系统不需要的代码的抽象视图。这种情况下,一个VSB选项可以用于删除支持来自整个系统的XYZ功能。

一些情况下,具体APIs组或整个库可以用VSB选项删除。如,若创建一个无须支持RTPsd的VSB工程,则rtpLib不需要包含在系统中。

更具体一点,默认包含在几个VxWorks库(如semBLib)中的任务系统可视化工具,由不同的组件提供(如INCLUDE_SEM_BINARY)。 提供这个功能的代码因此有效的跨越几个库和组件。若系统视图没有打算使用(如大多数部署系统),一个VSB工程可以用于从系统中所有VxWorks中删除系统可视化工具。这提高了体积和性能。

2.4.1 基本的操作系统VSB选项

VSB工程设施(Workbench或vxprj)提供一组扩展选项用于选择配置一个VSB工程。这些包括具体功能选项,和设计用于性能和体积优化的选项。 针对基本的VxWorks操作系统功能VSB工程可选选项如下: ? 具体BSP优化(如浮点数支持) ? 不一致的缓存模式(PowerPC) ? System Viewer Instrumentation

? 实时进程 ? 对象管理

? 共享内存对象(VxMP) ? 任务钩子函数 ? CPU电源管理 ? 高级选项

? VxWorks BSP验证测试套装 ? SMP

? SMP确定性或性能 ? AMP

这些选项在如下详细描述。注明其它技术(如网络)提供更多的附加选项,在相关的编程指导和平台用户指南中描述。

针对一系列选项和描述,参考风河Wrokbench VSB功能和vxprj工具。

2.4.2 VSB原型

VSB原型提供提供了一个方便的定义一组VSB选项的方法用于创建设计用于具体目的的操作系统设备。一个VSB原型做如下事情:

? 展示一组供用户改变的VSB选项。

? 隐藏和原型目的无关的其它选项或用户不能改变的选项。 ? 为原型目的设置所有默认选项。

如,参考2.5.2 Configuring Small Footprint VxWorks。

2.4.3 使用VSB工程创建VxWorks系统基本步骤

使用VSB工程来配置和构建VxWorks,涉及如下基本步骤(使用Workbench或vxprj命令行工具):

1. 创建一个VSB工程,选择期望的VSB选项,之后编译工程创建具体VxWorks库版本和使用其它优化;

2. 基于VSB工程创建有一个VIP。

3. 使用VIP,用期望的组件配置VxWorks,之后基于专门的库版本编译工程,创建系统镜像。

注:工具配置防止增加用VSB工程创建的定制库不支持的组件。

2.4.4 针对VSB系统开发内核应用

因为用VSB工程创建的系统包含标准VxWorks库版本,趋向于运行在那些系统上的内核应用必须带编译时连接到版本库。相关信息,参考Wind River Workbench by Example guide和

VxWorks

Command-Line Tools User’s Guide。

2.5 小型化Vxworks配置

VxWorks可以使用一个小型化原型配置产生一个携带小型化内存的最小内核。

注:所有体系结构不支持VxWorks的小型化配置。关于支持的信息,参考VxWorks

Architecture

Supplement和VxWorks BSP Reference。

2.5.1

2.5.2

2.5.3

2.5.4

2.5.5

2.5.6

关于小型化VxWorks 配置小型化VxWorks

针对小型化VxWorks的配置和编译步骤 针对小型化VxWorks开发应用 应用例子

调试小型化VxWorks

2.6 电源管理

开始于VxWorks 6.2版本,增强电源管理设备由因特体系结构(IA)提供。早期版本针对其它体系结构提供的设备保持不变。针对其它体系结构提高的新设备在以后发布。参考2.6.1 Power Management for IA Architecture和2.6.2 Power Management for Other Architectures。

2.6.1 针对IA体系结构的电源管理

2.6.2 针对其他体系结构的电源管理

2.7 VxWorks镜像类型

不同的VxWorks镜像类型可以用于不同的引导方法,存储,加载和执行场景。如下镜像的默认版本在VxWorks安装中被提供。可以创建由不同组件组成的定制版本。

仅vxWorks镜像类型——有时值一个可下载镜像——需要一个boot loader。这种方法在开发环境下最通用(最实际),因为不需要每次修改的时候重新烧录到flash或拷贝到目标存储媒介。镜像通常存储在主机系统中。

其它镜像类型——有时指独立镜像——不需要一个独立的boot loader。通常用于生产系统,存在在flash中。独立镜像需要配置非默认启动参数(参考2.7.3 Boot Parameter Configuration for Standalone VxWorks Images)。

不同的VxWorks镜像类型,用法,行为描述如下: vxWorks

VxWorks镜像类型目的是开发过程中使用,通常指downloadable。在生产系统下也非常用于,boot loader 和系统镜像被存储在磁盘上。在开发环境中,镜像通常存储在主机系统(或网络服务器上),通过boot loader下载到目标系统,并加载到RAM。特征表在主机上维持(vxWorks.sym文件),用于主机开发工具。保存特征表在主机上减少了要加载到目标机上的镜像大小,减少了启动时间。

若VxWorks配置了INCLUDE_STANDALONE_SYM_TBL组件,特征表包含在VxWorks镜像中。

vxWorks_rom

一个存储在目标机上非易失性设备上的VxWorks镜像。它拷贝本身到RAM,之后切换处理器到RAM执行。因为镜像没有压缩,所有比基于ROM镜像大,因此有一个比较慢的启动时间;但是比vxWorks_romResident镜像执行时间快。关于启动参数配置信息,参考2.7.3 Boot Parameter Configuration for Standalone VxWorks Images。

vxWorks_romCompress

一个存储在目标机上非易失性设备上的VxWorks镜像。几乎整个压缩,有很小未压缩部分在设备上电或复位时处理器立即执行。这一部分代码负责解压缩ROM镜像中压缩部分到RAM,切换处理器到RAM执行。因为是压缩镜像和其它镜像比需要更小的存储空间,但是解压缩延长启动时间。和vxWorks_rom比启动时间更长,使用的ROM空间少。和vxWorks_rom有同样的运行速度。关于启动参数的配置,参考2.7.3 Boot Parameter Configuration for Standalone VxWorks Images。

vxWorks_romResident

一个存储在目标机上ROM中的VxWorks镜像。启动时仅拷贝dss段到RAM;text段

仍保持在ROM中。因此描述为ROM-resident。启动比较快,使用RAM很小,但是运行比较慢,因为ROM访问提取指令比RAM提取指令慢。对于有内存限制的系统比较有用。启动参数配置信息,参考2.7.3 Boot Parameter Configuration for Standalone VxWorks Images。

2.7.1 默认VxWorks镜像

默认VxWorks镜像文件在installDir/vxworks-6.x/target/proj/projName下。如: /home/moi/myInstallDir/vxworks-6.x/target/proj/wrSbc8260_diab/default_rom/vxWorks_rom

2.7.2 针对开发和生产系统的VxWorks镜像

对于很多生产系统通常必须在ROM中存储一个和VxWorks链接的内核应用模块。VxWorks要配置在启动时自动执行应用。系统镜像可以见到存储应用模块允许被其它函数调用,或被终端用户交互使用(如,诊断程序)。

为了生产一个基于ROM的系统,你必须链接模块到v xWorks,并编译为适合ROM的系统镜像类型。相关信息,参考4.12 Configuring VxWorks to Run Applications Automatically。若你想在启动时自动启动应用,你必须配置VxWorks如下(4.12 Configuring VxWorks to Run Applications Automatically)。或参考4.13 Image Size Considerations。

注明,开发过程中,VxWorks必须配置WDB目标代理通讯接口,用于连接主机和目标机系统(网络,串口等)。默认,配置为一个增强网络驱动(END)连接。更多信息,参考D. WDB Target Agent。注明在使用主机开发工具之前,如shell和debugger,必须启动一个目标服务器,配置为通讯的相同模式。

关于配置带不同操作系统工具的VxWorks的信息,参考2.3.2 Device Driver Selection。 若你想在flash在存储镜像,想使用用户TrueFFS,参考13.3.6 Reserving a Region in Flash for a Boot Image。

2.7.3 单独VxWorks镜像启动参数配置

依赖系统需求,你可能需要为一个独立的镜像静态的重新配置启动参数——也就是说,不需要一个boot loader——指所有的系统镜像,除了downloadable vxWorks镜像。如一个网络目标机大多数需要设置本身的IP地址为一些默认的信息。

使用INCLUDE_BSP_MACROS组件的DEFAULT_BOOT_LINE配置参数设置启动参数。针对vxWorks的配置过程和boot loader的配置过程一样。关于boot loader的信息,参考3.5.2 Description of Boot Parameters。关于静态配置的信息,参考3.7.3 Configuring Boot Parameters Statically。

3 Boot Loader

3.1 介绍

一个VxWorks boot loader是一个应用,目的是加载一个VxWorks image到目标机。有时

VxWorks

Bootrom,但是这个词不推荐使用(合并应用和媒介)。如VxWorks,boot loader可以用

不同的工具配置,如命令行工具动态设置启动参数,一个网络loader,和一个文件系统loader。 相同的boot loader VxWorks 配置用于单处理器(UP),对称多处理器(SMP),和非对称多处理器(AMP)。

在一个开发环境中,boot loader对于从一个主机系统加载一个VxWorks镜像时非常有用的,在主机系统上,VxWorks可以快速修改和编译。当boot loader和操作系统都存储在磁盘

上或其它媒介上时,也可以用于生产系统。

Self-booting (standalone) VxWorks images不要求一个boot loader。这些镜像通常用于生产系统(存储在non-volatile设备上)。更多信息,参考2.7 VxWorks Image Types。

常常,boot loader被烧录到一个non-volatile设备(flash内存或EEPROM)上具体地址处,这个地址是目标机上电或重新启动后,处理器执行的第一条代码处。获取烧录在non-volatile设备上的boot loader,或写入到一个磁盘的方法取决于目标机,在BSP参考文档中描述。

VxWorks产品安装包括针对每一个安装BSP的默认boot loader。若它们不满足要求,你可以创建定制boot loaders。如,你可能需要使用一个不同的网卡驱动通过网络来加载Vxworks镜像,或你为了部署系统删除boot loader shell。

本章涉及的信息,特别是关于安装一个cross-development环境的信息,参考Wind River Workbench by Example。

3.2 使用默认boot loader

默认boot loader设计用于一个网络目标,必须配置相关参数,如主机和目标网络地址,加载文件全目录和文件名,用户名等。为了使用默认boot loader,你必须使用boot loader shell交互式的改变默认参数,以至于loader可以找到主机上的VxWorks镜像,并加载到目标机。

进入引导参数后,目标机启动VxWorks镜像。大多数目标机,新的设置会保存(在non-volatile设备或磁盘上),所有你可以直接启动目标机,不需要重新设置默认参数。

在一个终端控制台上,可以和boot loader shell交互,这个终端控制台,通过串口连接主机和目标机,在主机上启动一个终端应用程序。建立通讯的具体信息,参考相关文档。

默认boot loade镜像位于installDir/vxworks-6.x/target/config/bspName。Boot loader命令和参数在3.4.1 Boot Loader Shell Commands描述和3.5 Boot Parameters。提供不同的Boot loader镜像类型,如3.3 Boot Loader Image Types描述。

3.3 Boot Loader Image类型

Boot loader镜像可以存储在ROM,flash,磁盘,或存储在网络上。Boot loader镜像是ELF个数。二进制版本(.bin)用于磁盘,16进制文件版本(.hex)用于烧录non-volatile设备。什么样的目标机选择什么样的boot loader,参考BSP相关文档。

下面描述了boot loader的不同版本。下面列出的每一组镜像的第一个镜像是通过PROFILE_BOOTAPP配置原型产生的,第二个通过传统的bspDir/config.h方法。关于编译方法的更多信息,参考3.7 Configuring and Building Boot Loaders。

Compressed Image

vxWorks_romCompress 和 bootrom 文件 这个镜像几乎是整个压缩的。有一小部分未压缩部分,在设备上电或复位之后处理器立即运行。这部分初始化内存和解压缩压缩部分(存储在非易失性设备上)到RAM,导致处理器切换到RAM执行。压缩镜像比其他boot loader镜像小,因此使用比较小的非易失性存储空间。然而,解压缩增加了启动时间。

Uncompressed Image

vxWorks_rom 和 bootrom_uncmp 文件 这个镜像没有压缩。拷贝本身到RAM,处理器切换到RAM执行。因为镜像没有压缩,所以比压缩镜像大。然而,启动时间比较快,因为不需要要求的解压缩操作。

Resident in Non-Volatile Storage

vxWorks_romResident 和 bootrom_res 文件

这个镜像在启动时仅拷贝数据段到RAM,文本段保留在非易失存储上。这意味着处理器总是在非易失性存储外执行指令。因此有时描述为ROM-驻留型。这种类型的boot loader要求足够大的RAM来加载VxWorks内核。因此对于带有较小的RAM板卡,RAM是为应用保存数据的情况是很有用的。

Boot loader镜像位于installDir/vxworks-6.x/target/config/bspName。注明大多数默认BSP的默认镜像都需要配置网络开发环境。关于创建一个定制boot loader的信息,参考3.7 Configuring and Building Boot Loaders。

3.4 Boot Loader Shell

Boot loader shell提供了如何命令:

? 改变启动参数(如主机和目标IP地址) ? 重新启动目标系统 ? 管理启动过程

配置INCLUDE_BOOT_SHELL组件到boot loader,来包含boot loader shell。

提醒:不要增加INCLUDE_WDB_BANNER,INCLUDE_SIMPLE_BANNER,INCLUDE_SHELL或组件到boot loader。这些组件和boot loader shell冲突。若你包含了这些组件中的的其中一个,你会遇到错误。

3.5 Boot Parameters

启动参数包括需要定位和加载一个VxWorks内核的所有信息,还有其它用于管理启动过程的信息。根据具体启动配置要求,可以包含主机和目标机IP地址和全路径和要引导的VxWorks镜像名,用户名等。启动参数可以在运行时交互改变,也可以在创建boot loader时静态配置。交互改变启动参数要通过重启生效(在一个非易失性设备或磁盘上)。启动参数用于独立VxWorks镜像——不需要一个boot loader——boot loader自身用(更多信息,参考2.7 VxWorks Image Types)。 3.5.1 显示目前的启动参数

3.5.2 启动参数描述

3.5.3 交互式改变启动参数

3.6 Rebooting VxWorks

3.7 配置和编译Boot Loaders

3.8 安装boot Loaders

3.9 从一个网卡启动

3.10

从一个目标文件系统启动 从使用TSFS的主机文件系统启动

3.11

4 内核应用程序

4.1 介绍

VxWorks内核应用执行在和内核本身一样的模式和内存空间。这方面和用于其它操作系统的应用不一样,如UNIX和Linux;也和VxWorks实时进程RTP应用不一样。

内核应用可以交换下载和运行在一个VxWorks目标机上,或链接到操作系统镜像中,(可选)在启动时自动执行。

这一章提供了关于编写内核应用代码,创建为用户使用的静态库,内核对象静态实例化,执行应用等相关的信息。关于多任务,I/O,文件系统,其它内核中有的vxWorks工具相关的信息,参考相关章节。

关于Workbench和命令行编译环境相关信息,参考Wind River Workbench by Example和VxWorks Command-Line Tools User’s Guide。

关于开发用户模式RTP应用相关信息(作为用户模式的实时进程一样执行),参考VxWorks Application Programmer’s Guide。

4.2 关于内核应用

执行在内核中的VxWorks应用创建为一个浮动对象模块。它们可以被称为最特别的kernel-based application modules,但是通常为了方便称它们为kernel application modules或kernel applications。不要和执行在用户模式(实时进程RTPs)的应用混淆。

当一个基于内核应用模块编译后,用户代码被链接到请求的VxWorks库,产生一个ELF二进制文件。内核应用包含定义操作系统接口和数据结构的头文件后使用VxWorks工具。

内核应用模块可能是:

通过对象模块loader加载或动态链接到操作系统中。 静态链接到操作系统,作为系统镜像的一部分。 下载内核模块对应快速开发和调试非常有用,因为操作系统不需要为应用的每个迭代重新编译。这个方法也可能用于生产系统的诊断工具。不同的开发工具,包括调试器和shell(主机或内核),可以用于下载和管理模块。模块可以从任何主机支持的文件系统中(NFS,ftp等)下载到目标机。

内核应用模块也可以存储在目标机flash或ROM中,在ROMFS文件系统中,或磁盘上。一旦它们已经加载到目标机,内核应用模块可以在shell或Wrokbench上立即启动这些应用。

静态链接到操作系统的应用模块可以在shell或Workbench中交互运行。VxWorks也可以配置它们为启动时自动启动。静态链接和自动启动在生产系统中比较稳定。

一个运行在内核空间中的应用不会像一个进程一样执行;简化为另外一组执行在内核空间的其它一组任务。内核不保护任何一个参与的内核应用导致的任何不良行为——内核应用和内核以管理员模式运行在同样的地址空间。

警告:若你想移植一个内核应用到用户模式应用,执行为一个RTP,你必须确保代码满足一个RTP应用的要求和编译为一个RTP。你必须确保VxWorks配置支持RTPs。更多信息,参考VxWorks Application Programmer's Guide。

4.3 C和C++库

风河固有C库和Dinkum C和C++库都为VxWorks应用开发提供了。如Table 4-1展示,VxWorks固有库用于C内核应用开发,和库用于所有案例。

VxWorks固有C库提供ANSI规格外函数。注明不对多字节字符提供支持。

关于这些库的更多信息,参考VxWorks and Dinkum API references。关于C++工具更多信息,参考5. C++ Development。

4.4 内核应用结构

内核应用代码和通常C或C++应用相似,不一样的地方是,内核应用不需要传统的main()函数(不像一个基于进程的VxWorks应用)。仅需要一个入口点函数,启动应用运行需要的所有任务。

注明:若你的内核应用包括一个main()函数,也不会自动启动。下载或存储在系统镜像中的内核应用模块必须被交互启动(或被另外一个已经运行的应用启动)。操作系统也可以配置为自动启动(参考a4.12 Configuring VxWorks to Run Applications Automatically)。 入口点函数执行所有需要的数据初始化,启动所有运行应用使用的任务。如一个内核应用可能有一个函数命名为myAppStartUp( ):

void myAppStartUp (void) {

runFoo();

tidThis = taskSpawn(\(FUNCPTR) thisRoutine,0,0,0,0,0,0,0,0,0,0); tidThat = taskSpawn(\(FUNCPTR) thatRoutine,0,0,0,0,0,0,0,0,0,0);

tidAnother = taskSpawn(\(FUNCPTR) anotherRoutine,0,0,0,0,0,0,0,0,0,0); return (OK); }

关于VxWorks任务和多任务信息,参考6. Tasks and Multitasking。关于和C++一同工作的信息,参考5. C++ Development。

4.5 VxWorks头文件

很多内核应用大量使用VxWorks操作系统工具或工具库。这个通常需要源模块引用Vxworks头文件。如下部分讨论了VxWorks头文件的使用方法。

VxWorks头文件支持针对所有全局VxWorks函数的ANSI C函数原型声明。VxWorks通过

ANSI

X3.159-1989标准规范所有的头文件。

VxWorks系统头文件在installDir/vxworks-6.x/target/h目录下和子目录下。 4.5.1 VxWorks头文件:vxWorks.h

头文件vxWorks.h必须在每个使用VxWorks工具的内核应用模块中首先包含。它包含用于其它

VxWorks模块扩展的基本定义和类型。很多其他VxWorks头文件要求这些定义。

#include

4.5.2 其它VxWorks头文件

内核应用可以包含其它VxWorks头文件,若需要访问VxWorks工具。如一个使用VxWorks链接表库的模块必须包含lstLib.h头文件:

#include

针对每个库的API引用入口列出了用于库的所有必须的头文件。

4.5.3 ANSI 头文件

所有的ANSI规范的头文件都包含在VxWorks中。那些编译器独立的或具体VxWorks的头文件在installDir/vxworks-6.x/target/h,而一个编译器独立的(如stddef.h和stdarg.h)在编译器安装时被提供。每个工具链知道如何查找自身的内部头文件;不需要特殊的编译标志。

4.5.4 ANSI C++头文件

每个编译器有自身的C++库和C++头文件(如iostream和new)。C++头文件位于编译器安装目录,不是installDir/vxworks-6.x/target/h。不需要特殊标志来使能编译器查找这些头文件。关于C++开发更多信息,参考5. C++ Development。

注:VxWorks 5.5先前版本,风河推荐使用-nostdinc标志。目前版本不要使用,会防止编译器查找头文件,如stddef.h。

4.5.5 –I编译器标志

默认,编译器首先在源模块中查找头文件,之后在源模块中子目录中查找。通常编译器总是在查找源模块其它子目录之前查找目录installDir/vxworks-6.x/target/h;为了确保这个顺序,总是在VxWorks下增加如下标志:

-I %WIND_BASE%/target/h %WIND_BASE%/target/h/wrn/coreip 一些头文件位于子目录中 。为了在这些目录下引用头文件,确保include对应子目录名,所有使用单元-I标识符指明,文件会被找到。如:

#include #include

4.5.6

VxWorks嵌套头文件

一些VxWorks工具利用其它低水平的VxWorks工具。如,tty管理工具使用环形缓存子程序库。Tty头文件tyLib.h使用环形缓存头文件rngLib.h.提供的定义。

将会不方便的是需要你意识到包含头文件的内部依赖和排序。取而代之的是,所有的VxWorks头文件显式包含了所有先决条件的头文件。因此,tyLib.h本身包含了头文件rngLib.h。(一个例外是基本VxWorks头文件vxWorks,所有其他的头文件已经包含)

通常,先决头文件的显式包含可以抛出一个问题:一个头文件只能包含一次,否则会产生重要错误(因为C预处理器认为重复定义会造成潜在的代码冲突问题)。然而,所有的头文件包含条件编译语句和保证只编译一次的定义,和你include多长没关系。因此,一个内核应用模块仅需要包含直接的头文件,无需关心头文件中的内部依赖和顺序,不会产生冲突。

4.5.7 VxWorks私有头文件

一些VxWorks元素是内部可能变化的细节,所有不能再内核中引用。仅支持一个模块的工具用法通过在头文件中公共定义,和通过模块的子函数接口。你的坚持确保了你的应用代码不会VxWorks模块实现中内部变化的影响。

一些使用HIDDEN组件标志的内部细节:

/* HIDDEN */ ...

/* END HIDDEN */

内部细节也可以用private头文件隐藏:存储在installDir/vxworks-6.x/target/h/private目录中的文件。这些文件的命名规范使用后缀P.h在installDir/vxworks-6.x/target/h目录中。如semLib的私有头文件是installDir/vxworks-6.x/target/h/private/semLibP.h。

4.6 静态内核对象实例化

VxWorks内核对象——如任务和信号量——可以动态或静态实例化。静态实例化提供性能和确定性优势。专有VxWorks C 宏提供静态实例化。

4.6.1 关于内核对象的静态实例化

一个内核对象的静态实例化意味着对象被声明为一个编译时变量(使用一个专有Vxworks宏),通常用于全局范围。因此编译器为应用对象分配空间,不需要在运行时分配。因此,对象在启动时可以立即初始化。

与静态实例化对比,内核对象的动态实例化涉及运行时系统内存分配,之后在使用之前初始化。同样,对象删除涉及对象的验证,之后返回内存给系统。对象创建和删除同样依赖动态内存分配,通常使用malloc( )和free( )函数。

应用使用动态实例化必须考虑运行时内存不足,对象不能成功创建的情况(采取一些合适的错误恢复过程或退出)。另外,动态分配是一个相对比较慢的操作,会阻塞一个单一函数的调用(如,taskSpawn( ),semXCreate( ),等)。

如下实例说明了动态和静态代码实例化的区别(但是不要使用任何VxWorks对象实例化宏)。

动态实例化

struct my_object * pMyObj; ...

pMyObj = (struct my_object *) malloc (sizeof (struct my_object)); if (pMyObj != NULL) {

objectInit (pMyOjb); return (OK); } else {

/* failure path */ return (ERROR); }

静态实例化

struct my_object myObj; ...

objectInit (&myOjb);

/* myObj now ready for use */

可以静态实例化的内核对象 如下内核对象可以静态实例化: ? 任务 ? 信号量 ? 消息队列 ? 看门狗定时器

更详细的信息,参考4.6.4 Static Instantiation of Tasks,4.6.5 Static Instantiation Of Semaphores,4.6.6 Static Instantiation of Message Queues,和4.6.7 Static Instantiation of Watchdog Timers。

静态实例化和代码大小

对象的编译时声明不在可执行文件中,一个VxWorks镜像中或存储介质中(如 flash内存)占据任何空间。若一个对象在编译时声明,但是没有初始化,编译器设置它为未初始化数据段(bss)。未初始化数据要求被ANSI C标准设置为0。

当未初始化数据会导致运行时内存占用,所有需要动态分配。另外情况,内存占用一样。 静态初始化优势

内核对象的静态初始化提供了几个优势,和动态初始化比较: ? 对象的静态初始化是一个快速,比较确定性操作。

? 应用逻辑简单因为不用考虑动态初始化内存分配失败的问题。 ? 静态对象命名不会失败,除非程序本身太大,系统内存不能容纳。

? 小型化VxWorks配置可以用针对动态内存分配的删除工具创建(如,参考2.5 Small-Footprint VxWorks Configuration)。

应用和静态初始化

内核对象的静态初始化为实时应用提供了显著优势,大多数应用应该大量考虑静态初始化。大多数应用要求一些对象在整个应用运行生命周期内存在,不要求删除。因此这些对象可以静态初始化。使用静态初始化,使得软件更具备鲁棒性,确定性和更快速。

另外,小系统在设计时不要使用动态内存分配工具,一个VxWorks配置是专门用于这样的设计(更多信息,参考2.5 Small-Footprint VxWorks Configuration)。

注:静态初始化应该在内核应用中使用。不设计用于RTP应用(用户模式)。

4.6.2 static声明范围

内核对象通常声明为全局变量,因为对象IDs通常用于任务间通讯和同步。然而,也不需要是全局的。在函数范围内提供一个对象声明,生命周期仅在函数运行范围内有效。

4.6.3 关于宏使用的警告

为了保证合适的宏表达式,任务初始化宏必须使用一个反斜杠字符,若声明或调用换行时。如,如下确保了使用VX_TASK_INSTANTIATE宏进行一个任务的静态初始化会被编译器合适处理:

myTaskId = VX_TASK_INSTANTIATE(myTask, 100, 0, 4096, pEntry, \\ 0,1,2,3,4,5,6,7,8,9);

宏使用详细描述在4.6.4 Static Instantiation of Tasks,4.6.5 Static Instantiation Of Semaphores,4.6.6 Static Instantiation of Message Queues,和4.6.7 Static Instantiation of Watchdog Timers。

4.6.4 任务的静态实例化

VX_TASK宏在编译时声明了一个任务对象。宏使用两个参数:任务名和栈大小。和使用taskSpawn( )不一样,名称可能为NULL指针,名称强制带有VX_TASK宏。栈大小必须为一个非零整数值,必须为一个编译时常量。

VX_TASK_INSTANTIATE宏可以用于VX_TASK来静态初始化和调度一个任务取代动态初始化taskSpawn( )。同样,VX_TASK_INITIALIZE宏可以用于VX_TASK来初始化一个任务,但是任务一直处于挂起状态,指定使用taskActivate( )函数激活。

VX_TASK_INSTANTIATE返回发起的任务ID,或任务发起异常,返回ERROR。相同的任务名必须用于VX_TASK_INSTANTIATE和VX_TASK宏。如:

#include #include VX_TASK(myTask,4096); int myTaskId;

STATUS initializeFunction (void) {

myTaskId = VX_TASK_INSTANTIATE(myTask, 100, 0, 4096, pEntry, \\ 0,1,2,3,4,5,6,7,8,9); if (myTaskId != ERROR)

return (OK); /* instantiation succeeded */ else

return (ERROR); }

为了初始化一个任务,但是一直保持挂起状态,直到调用VX_TASK_INITIALIZE宏之后。taskActivate( )函数用于之后运行任务。相同的参数必须用于VX_TASK_INSTANTIATE和taskActivate( ).。如:

#include #include VX_TASK(myTask,4096); int myTaskId;

STATUS initializeFunction (void) {

myTaskId = VX_TASK_INITIALIZE(myTask, 100, 0, 4096, pEntry, \\

0,1,2,3,4,5,6,7,8,9); if (myTaskId != NULL) {

taskActivate (myTaskId); return (OK); } else

return (ERROR); }

更多信息,参考the taskLib API reference entry。

关于任务和任务管理函数相关通用信息,参考6.2 About Tasks and Multitasking,6.4 Task Scheduling,和6.5 Task Creation and Management。

4.6.5 信号量的静态实例化

VX_BINARY_SEMAPHORE, VX_COUNTING_SEMAPHORE,VX_MUTEX_SEMAPHORE, 和 VX_READ_WRITE_SEMAPHORE宏分别用于在编译时声明一个二进制类型信号量,counting,

互斥。

通过这些宏声明的信号量通过分别调用semBInitialize( ), semCInitialize( ) semMInitialize( ), 和 semRWInitialize( )函数初始化。三个semXInitialize( )函数和他们相关的semXCreate( )函数功能一样。

相同的信号量命名必须成对使用VX_XXX_SEMAPHORE宏和semXInitialize( )函数。函数的返回值是一个信号量ID,之后用于执行信号量操作。如:

#include #include

VX_BINARY_SEMAPHORE(mySemB); /* declare the semaphore */ SEM_ID mySemBId; /* semaphore ID for further operations */ STATUS initializeFunction (void) {

if ((mySemBId = semBInitialize (mysemB, options, 0)) == NULL) return (ERROR); /* initialization failed */ else

return (OK); }

更多信息,参考API references for semBLib, semCLib, and semMLib。关于信号量的通用信息,参考7.4 Interrupt Locks。

4.6.6 消息队列的静态实例化

VX_MSG_Q宏在编译时声明一个消息队列。使用三个参数:名称,消息队列中最多消息数,每个消息的最大字节数。msgQInitialize( )函数用于初始化消息队列,使得为使用准备好。相同的消息队列名——还有针对消息队列大小和最大消息数的相同值——必须使用宏和函数。如:

#include #include

VX_MSG_Q(myMsgQ,100,16); /* declare the msgQ */

MSG_Q_ID myMsgQId; /* MsgQ ID to send/receive messages */ STATUS initializeFunction (void) {

if ((myMsgQId = msgQInitialize (myMsgQ, 100, 16, options)) == NULL) return (ERROR); /* initialization failed */ else

return (OK); }

更多信息,参考API reference for msgQLib。关于消息队列通用信息,参考7.7 Message Queues。

4.6.7 看门狗定时器的静态实例化

VX_WDOG宏在编译时声明一个看门狗定时器。使用一个参数,看门狗定时器的名字。wdInitialize( )函数用于初始化看门狗定时器和使能使用。相同的看门狗名必须用于宏和函数。如:

#include #include

VX_WDOG(myWdog); /* declare the watchdog */

WDOG_ID myWdogId; /* watchdog ID for further operations */ STATUS initializeFunction (void) {

if ((myWdogId = wdInitialize (myWdog)) == NULL) return (ERROR); /* initialization failed */ else

return (OK); }

更多信息,参考API reference for wdLib。关于消息队列的通用信息,参考8.4 Watchdog Timers。

4.7 内核应用和内核组件需求

VxWorks是一个高配置操作系统。当内核应用模块独立于操作系统编译(参考4.9 Building Kernel Application Modules),编译过程不能确定是否应用上的VxWorks实例最终运行,因为,要保证VxWorks内核包含应用所需的所有组件(如网卡和文件系统等)。因此,应用代码检查内核设备不存在的错误提醒(也就是说,检查API调用的返回值)和正确的回复比较有用。

当内核应用模块链接到操作系统时,编译系统产生和丢失组件相关的错误。Workbench和vxprj命令行工具也可以提供为重新配置VxWorks进行依赖检查的机制。

4.8 内核应用和内核组件需求

4.9 编译内核应用模块

VxWorks内核应用可以用Workbench或用命令行编译(命令行环境包括一组有用的默认makefile规则)。关于Workbench和命令行编译环境的用法,参考Wind River Workbench by Example guide和VxWorks Command-Line Tools User’s Guide。

提醒:VxWorks内核应用必须针对运行的系统类型编译。针对UP VxWorks系统编译,

针对SMP VxWorks编译,针对基于版本库创建的VxWorks系统,版本库基于VSB工程(UP或SMP),二进制不兼容。注明loader拒绝一个内核模块若和加载的系统不兼容,控制台会输出一个错误信息,并设置errno为S_loadLib_INCOMPATIBLE_MODULE。

4.10 下载内核应用对象模块到目标机

内核应用对象模块可以从Workbench或内核shell中下载。一旦一个模块加载到目标内存,模块中的任何子函数会被触发,任务发起,模块使用的调试工具等。通常使用启动函数来运行应用比较有用。(参考4.4 Kernel Application Structure)。

关于使用内核shell和内核loader信息,参考16.2 Kernel Shell和16.3 Kernel Object-Module Loader。关于使用Workbench更多信息,参考Wind River Workbench by Example guide。

4.11 链接内核应用对象模块到VxWorks

VxWorks内核应用可以使用Workbench或命令行开发工具链接到VxWorks。关于使用Workbench和命令行编译环境信息,参考Wind River Workbench by Example guide和VxWorks Command-Line Tools User’s Guide。

4.12 配置VxWorks自动运行应用程序

VxWorks可以配置为在启动时自动启动内核应用。这样做,执行如下步骤: 1.配置INCLUDE_USER_APPL组件到VxWorks中;

2.在应用的入口点usrAppInit( )函数中增加调用,在installDir/vxworks-6.x/target/proj/projDir/usrAppInit.c文件中。

假如,应用入口点函数myAppStartUp( )启动所有应用需要的任务,你需要在usrAppInit( )函数中增加调用如下:

void usrAppInit (void) {

#ifdef USER_APPL_INIT

USER_APPL_INIT; /* for backwards compatibility */ #endif

myAppStartUp(); }

3.链接基于内核应用对象模块到内核镜像(参考4.11 Linking Kernel Application Object Modules with VxWorks)。

4.13 镜像大小考虑

系统镜像大小通常要重点考虑,尤其是当内核应用模块链接到操作系统后。这是真实的是否镜像被一个boot loader加载或自启动(参考2.7 VxWorks Image Types)。

提醒:对于基于ROM镜像,确保ROM_SIZE配置参数影响ROMs使用的容量。

4.13.1 boot loader和可下载镜像

通常,VxWorks boot loader代码被拷贝到RAM的一个起始地址上面的常量地址RAM_HIGH_ADRS,boot loader轮流拷贝可下载系统镜像到RAM_LOW_ADRS位置。这些常量的值是体系结构独立的,但是在任何情况下系统镜像不能超过两个常量间的空间。否则系统会覆盖boot loader代码,当下载时,潜在杀死启动进程。

为了帮助避免这个除夕,上一个命令执行当编译一个新的Vxworks镜像为vxsize,表示

新可执行镜像大小和ROM中预留了多少空间:

vxsize 386 -v 00100000 00020000 vxWorks

vxWorks: 612328(t) + 69456(d) + 34736(b) = 716520 (235720 bytes left)

(In this output, t stands for text segment, d for data segment, and b for bss.)

确信RAM_HIGH_ADRS小于LOCAL_MEM_SIZE。若新镜像太大,vxsize产生一个警告。这种情况下,你应该重新配置boot loader来拷贝启动ROM代码到足够的内存地址位置,通过增加config.h文件中RAM_HIGH_ADRS值,和BSP的makefile(两个值也一致)。之后重新编译boot loader。更多信息,参考Reconfiguring Memory Layout for a Persistent Memory Region。

4.13.2 自启动镜像

对于自启动镜像,驻留ROM VxWorks 系统的数据段加载到RAM_LOW_ADRS(在makefile中定义)以最小化内存碎片。

对于有限内存的CPU板(小于1M RAM),确信RAM_HIGH_ADRS小于LOCAL_MEM_SIZE,有足够的空间来容纳数据段。注明RAM_HIGH_ADRS定义在BSP makefile和中(要一致)。

5 C++开发

5.1 介绍

这一章提供了VxWorks系统下使用风河和GNU工具链进行C++开发相关信息。 警告:风河编译器C++和GNU C++库文件不兼容。

注明:本章提供了VxWorks内核有的相关设施信息。关于实时进程相关信息,参考VxWorks Application Programmer’s Guide相关章节。

5.2 配置C++到VxWorks

默认,VxWorks仅包括mini C++支持。你可以通过增加如下组件支持C++功能: INCLUDE_CTORS_DTORS

默认包含在内核中,确保编译器产生的初始化函数,包括C++静态对象的初始化,在内核启动时调用。

INCLUDE_CPLUS

包括基本的C++应用支持。通常和INCLUDE_CPLUS_LANG混合使用。 INCLUDE_CPLUS_LANG

包含C++语言功能支持,如new, delete和异常处理。 INCLUDE_CPLUS_IOSTREAMS 包括所有的库功能。

INCLUDE_CPLUS_DEMANGLER

包括C++命令,在使用内核shell loader时非常用于,因为它提供用于内核shell特征表查询返回命令特征名。若同时包含INCLUDE_CPLUS和INCLUDE_SYM_TBL组件,这个组件被默认增加。

5.3 C++代码需求

任何使用C++的VxWorks任务必须用VX_FP_TASK选项发起。默认,从主机工具发起任务(风河shell)默认使能VX_FP_TASK。

警告:当使用VX_FP_TASK选项发起使用C++的任务失败时,可能很难调试,在运行时产生不可预见的浮点数寄存器破坏。

若你从你的C代码中引用一个(非重载,全局)C++特征,你必须使用extern \通过原型C链接:

#ifdef __cplusplus

extern \#else

void myEntryPoint (); #endif

你也可以使用这个语法来在C++代码中访问C特征。VxWorksC特征自动存在在C++代码中,因为VxWorks头文件使用这种声明机制。

每个编译器有自身的C++库和C++头(如iostream和new)。C++头位于编译器安装目录,不是installDir/vxworks-6.x/target/h中。不需要做什么就可以使能编译器找到这些头。

注: VxWorks 5.5之前发布版本,风河推荐使用-nostdinc标志。目前的发布版本不需要使用这个标志,防止编译器找不到头文件,如stddef.h。

5.4 在信号处理和ISRs中使用C++

小心在信号处理和ISRs中使用C++代码。相关信息,参考8.2.5 Signal Handlers和8.3.3 Caveats With Regard to Writing ISRs。

5.5 在DKM工程中使用C++

下载到VxWorks内核中的C++代码应该链接到一个单一下载对象模块中。也必须被一直使用,任何COMDAT或已经连接的部分会销毁。VxWorks为在可下载模块中调用静态构造和析构函数提供了几种措施。

警告:风河编译器C++和GNU C++库文件是不兼容的。用C++写的DKM必须用VxWorks使用的编译来编译。 5.5.1 使用一个单一C++模块

VxWorks loader 仅支持self-contained的C++模块。一个自包含的C++模块是一个不能使用来之其它C++模块的类,它的类也不能被其它C++模块使用。尤其,一个模块必须包含自身标准库拷贝,或不使用C++标准库。

为了生产自包含模块,所有下载的C++对象文件应于被链接到一个单一可下载对象模块。

卸载一个不是自包含的C++模块可能会导致来之其他模块创建对象的空引用到卸载模块中的数据结构。尤其,若标准库流部分来之后面卸载的一个模块的初始化是会出现的。这种情况下,任何更进一步的iostreams的使用会伴随一个内核异常失败(访问无效的地址)。

警告:C++对象文件必须链接到一个DKM模块。

关于内核loader的信息,参考16.3 Kernel Object-Module Loader。

5.5.2 Munching 一个C++应用模块

在一个C++模块加载到VxWorks内核前,必须经历一个附件主机处理步骤,由于历史原因,称为munching。Munching执行如下任务: 初始化静态对象支持

确保为所有的静态对象在C++运行时以正确的顺序调用构造和析构函数。

对于风河编译器,自动销毁COMDAT部分;对于GUN编译器,自动销毁linkonce。

Munching 必须在编译之后,下载之前执行。 Munching例子

对于每个工具链,如下例子编译一个C++应用源文件,hello.cpp,依赖.o文件运行munch,编译产生ctdt.c文件,用ctdt.o文件链接应用产生一个可下载模块,hello.out。 使用风河工具链 1 编译源文件:

$ dcc -tPPC604FH:vxworks61 -Xlocal-data-area-static-only -XO \\

-IinstallDir/vxworks-6.x/target/h -DCPU=PPC32 -DTOOL_FAMILY=diab -DTOOL=diab \\ -D_WRS_KERNEL -c hello.cpp

2.munch对象文件:

$ ddump -Ng hello.o | tclsh \\

installDir/vxworks-6.x/host/resource/hutils/tcl/munch.tcl -c ppc > ctdt.c

3.编译munch输出:

$ dcc -tPPC604FH:vxworks61 -Xlocal-data-area-static-only -XO \\

-IinstallDir/vxworks-6.x/target/h -DCPU=PPC32 -DTOOL_FAMILY=diab -DTOOL=diab \\ -D_WRS_KERNEL -c ctdt.c

4.用munched对象文件链接最初对象文件创建一个可下载模块: $ dld -tPPC604FH:vxworks61 -X -r4 -o hello.out hello.o ctdt.o 注明:-r4选项销毁任何保护在输入文件中的COMDAT部分。 使用GUN工具链 1. 编译源代码:

ccppc -mcpu=604 -mstrict-align -O2 -fno-builtin \\ -IinstallDir/vxworks-6.x/target/h \\

-DCPU=PPC604 -DTOOL_FAMILY=gnu -DTOOL=gnu -c hello.cpp

2.munch一个对象文件:

nmppc hello.o | wtxtcl installDir/vxworks-6.x/host/src/hutils/munch.tcl \\ -c ppc > ctdt.c

3.编译munch输出:

ccppc -mcpu=604 -mstrict-align -fdollars-in-identifiers -O2 \\ -fno-builtin -IinstallDir/vxworks-6.x/target/h \\ -DCPU=PPC604 -DTOOL_FAMILY=gnu -DTOOL=gnu -c ctdt.c

4使用munched对象文件链接最初的对象文件创建一个可下载模块:

ccppc -r -nostdlib -Wl,-X \\

-T installDir/vxworks-6.x/target/h/tool/gnu/ldscripts/link.OUT \\ -o hello.out hello.o ctdt.o

注明:VxWorks内核对象模块loader不直接支持linkonce部分。取代的是,在加载之前linkonce部分必须被混合或销毁到标准的text和data部分。GNU -T选项销毁任何包含在输入文件中的linkonce部分。

使用一个通用Makefile规则

若你使用VxWorks makefiel定义,你可以写一个兼容GUN和风河编译器工具链的makefile

CPU = PPC604 TOOL = gnu

TGT_DIR = $(WIND_BASE)/target include $(TGT_DIR)/h/make/defs.bsp

default : hello.out %.o : %.cpp

$(CXX) $(C++FLAGS) -c $< %.out : %.o

$(NM) $*.o | $(MUNCH) > ctdt.c

$(CC) $(CFLAGS) $(OPTION_DOLLAR_SYMBOLS) -c ctdt.c $(LD_PARTIAL) $(LD_PARTIAL_LAST_FLAGS) -o $@ $*.o ctdt.o

Munching,下载,链接之后,静态构造和析构被调用。这个步骤描述如下。

5.5.3 交互调用构造和析构函数

5.6 C++编译器区别

5.6.1

5.6.2

模板实例化 运行时类型信息

5.7 名称空间 5.8 C++ Demo例子

6 任务和多任务

6.1 介绍

现代实时系统基于多任务和任务间通讯的补充概念。一个多任务环境允许一个实时应用用一组独立的任务构建,每个任务由自己的执行线程和系统资源组。任务是VxWorks中调度的基本单元。内核或进程中所有的任务都隶属于同一个调度(不能调度VxWorks进程)。

关于VxWorks对POSIX线程支持的更多信息,参考9. POSIX Facilities。

注明:本章提供了VxWorks内核中存在的设备信息。关于实时进程相关的设备信息,参考VxWorks Application Programmer’s Guide相关章节。

6.2 关于任务和多任务

VxWorks任务是操作系统自身代码执行的基本单元,和作为一个进程执行的应用程序中一样。在其它操心系统下,通常使用线程。(更多信息,参考VxWorks支持的POSIX线程,参考9.10 POSIX Threads)

多任务是为应用控制和操作多个,分散的实时事件而提供的基本机制。VxWorks实时内核提供基本的多任务环节。对于一个单处理器系统,表象是多个任务在并发执行,其实内

核是基于调度策略来执行的。

每个任务由自身的上下文,指内核用于每次任务查看的调度运行需要的CPU环境和系统资源。对于一个上下文切换,一个任务的上下文保存在任务控制块中(TCB)。

一个任务的上下文包括:

? 一个执行的线程;也就是说任务的程序计数器 ? 一个任务的虚拟内存上下文(若支持进程) ? CPU寄存器和协处理器寄存器(可选) ? 动态变量和函数调用栈

? 标准输入、标准输出,标准错误的I/O指派 ? 一个延迟定时器 ? 一个时间片定时器 ? 内核控制结构 ? 信号处理

? 任务私有环境(环境变量)错误状态(errno) ? 调试和性能监控值

若VxWorks没有配置支持进程(INCLUDE_RTP),一个任务的上下文不包括虚拟内存上下文。所有的任务只能在一个但一个通用地址空间运行(内核)。

然而,若VxWorks配置了进程支持——不管进程是否激活——一个内核任务的上下文必须包含自身的虚拟内存上下文,因为系统有潜在操作除内核之外其它虚拟内存上下文的可能性。也就是说,系统中的任务可能运行在不同的虚拟内存上下文中(内核和一个或多个进程)。

关于虚拟内存上下文更多信息,参考15. Memory Management。

注:POSIX标准包括一个线程的概念,和任务相似,但是有其它功能,详细,参考9.10 POSIX Threads。

6.2.1 任务状态和转换

内核为系统中的每一个任务维持目前的状态。一个任务从一个状态改变为另外一个状态做为应用特定函数调用的行为结果(如,尝试使用目前不存在的信号量)和使用开发工具如调试器。

最高优先级的任务是目前执行的处于ready状态的任务。当用创建任务,立即进入ready状态。关于ready状态更多信息,参考Scheduling and the Ready Queue。

当使用VX_TASK_NOACTIVATE选项参数,用taskCreate( )创建任务,或taskOpen( ),实例化后的任务处于suspended状态。要通过taskActivate( )激活,导致任务进入ready状态。激活阶段是非常快的,及时使能应用创建并激活任务。

Tasks States and State Symbols 描述了任务状态和你使用开发工具看到的state symbols。 注明任务状态是附加的;一个任务可能在一个时刻处于多个状态。转换可能会发生在其中一个状态。如一个任务从挂起态到挂起和停止态转换。且之后改变为非挂起态,之后变化为停止态。

STOP状态用于调试工具,程序运行到一个断点位置时。也用于错误检测和报告工具()。展

示了shell 命令i(),任务状态信息。

基本任务状态转换说明

Figure 6-1提供了一个任务状态转换的简要说明。对于澄清目的,不显示附加的在Tasks States and State Symbols,讨论的信息,不显示用于调试工具显示的STOP状态。

列表中列出的函数是导致相关转换的例子。如,一个任务调用taskDelay( )从ready状态转换到delayed状态。

注明taskSpawn( )导致创建任务后,任务进入ready状态,而taskCreate( )函数创建任务后,任务进入suspend状态(使用VX_TASK_NOACTIVATE参数,调用taskOpen( )函数完成后续的目的)。

6.3 VxWorks系统任务

依据自身配置,VxWorks在启动时启动各种不同的任务,有的任务一直运行。一个基本的VxWorks配置关联的任务组,通常使用的可选组件关联一些任务,描述如下:

提醒:不要suspend,delete,change这些任务中的任何一个。这样做会导致不可预知的系统行为。

Basic VxWorks Tasks

本文来源:https://www.bwwdw.com/article/t7it.html

Top