VxWorks自定义动态系统调用的应用

合集下载

VxWorks开发教程(2024)

VxWorks开发教程(2024)

03
无线通信应用案例分 析
通过分析一个具体的无线通信应用案 例,展示如何在VxWorks系统中实现 无线通信功能,并提供一些优化和改 进的建议。
2024/1/28
35
08
图形界面开发与多媒体应用支 持
Chapter
2024/1/28
36
图形界面开发框架介绍
WindML
2024/1/28
29
设备驱动开发流程
01
需求分析
明确设备的功能需求、性能需求 和接口需求,为后续的设备驱动
开发提供基础。
03
编码实现
依据设计文档,使用C语言等编程 语言实现设备驱动的代码编写。
2024/1/28
02
设计阶段
根据需求分析结果,设计设备驱 动的整体架构、数据结构和函数
接口等。
04
测试与验证
2024/1/28
10
建立工程及源代码管理
创建新工程
在Workbench中,选择“File”->“New”>“VxWorks Project”,然后按照向导创建一个 新的VxWorks工程。
配置工程属性
在工程属性中,你可以设置编译选项、包含路径 、链接库等。确保这些配置与你的目标机和源代 码相匹配。
配的内存。
使用memPartAlloc和memPartFree函数:VxWorks提供了内存分区管理功能,可以 使用memPartAlloc函数从指定的内存分区中分配内存,使用memPartFree函数释放
内存到相应的分区。
2024/1/28
使用taskAlloc和taskFree函数:针对任务相关的内存分配,可以使用taskAlloc和 taskFree函数。这些函数会从任务的控制块中分配和释放内存。

风河Workbench3.0_VxWorks6.6应用程序开发使用说明V1.0

风河Workbench3.0_VxWorks6.6应用程序开发使用说明V1.0

说明:由于开发经验和英语水平有限,在本文档中肯定存在偏差和谬误。

在有疑问的地方,请以风河的官方文档为准。

欢迎联系,指正错误。

QQ:1039309823。

风河Woorkbench3.0/VxWorks6.6使用说明第一章工程视图(Projects Overview)Workbench利用工程( Projects)就像逻辑容器和积木块——它们能够连接在一起创建一个软件系统。

工程( Projects)窗口可以直观地组织工程结构反映在内部的依赖关系上,以及编译和链接的次序。

前期配置的各种不同的工程允许在后面建立或添加工程时使用与之前的工程相同的配置和建立方式,因而只需要极小的输入。

一、Workspace/Project 的设置Wind River Workbench并不知道使用者的源文件在哪一个地方,在开始的使用的时候Wind River Workbench在安装目录下有一个默认的工作空间(workspace )的目录。

但是这不是必需的或者说并不一定是合理的,当使用者的工作空间因为产品升级或者更改安装目录已经完全存储在当前的安装目录树之外的时候!通常,使用者需要把workspace目录设置在当前的源文件树的根目录下并且在此创建Workbench工程。

对于各种不同的源文件树,可以使用不同的工作空间(workspaces)。

当决定在什么地方建立工程(projects)要做以下考虑:1.在workspace建立工程如果使用者想要新建一个工程在workspace下,通常的情况有A.所建的工程还没有建立源文件。

B.所建的工程已经存在源文件,但需要添加进工程。

C.所建的工程不允许设置在源文件目录处。

2.在workspace外部建立工程在创建工程时,点击“Browse”,将要建立的工程放置在在与workspace不同的目录。

通常的情形有:A.所建的工程建立在已有的原文件之上,改变工程目录之后需要对源文件进行添加和链接。

VxWorks操作系统基础(适合初学者阅读)2024新版

VxWorks操作系统基础(适合初学者阅读)2024新版
提供最基本的系统服务,如任务调度、内存管理、中断处理等。
系统库(System Library)
提供一系列操作系统服务,如文件操作、网络协议栈等。
驱动程序(Device Drivers)
与硬件设备交互,实现对硬件设备的控制和管理。
内核组成及作用
内核组成及作用
01
内核的主要作用包括
02 管理系统资源,如CPU、内存、I/O设备等 。
06
VxWorks文件系统操作指南
文件系统类型及特点介绍
RAM-based File System
基于RAM的文件系统,读写速度快,但数据在 关机后丢失。
TrueFFS
Wind River特有的闪存文件系统,提供磨损均 衡和掉电保护功能。
ABCD
DOS File System (dosFs)
兼容MS-DOS的文件系统,支持FAT12、FAT16 和FAT32格式。
01
VxWorks操作系统概述
VxWorks操作系统定义
VxWorks是一款由美国风河公司( Wind River)开发的嵌入式实时操 作系统(RTOS),专为需要实时响 应和高可靠性的应用而设计。
VxWorks提供了丰富的中间件和开发 工具,支持多种处理器架构和硬件平 台,广泛应用于航空、航天、通信、 医疗、工业自动化等领域。
在ISR中处理完中断事件后, 需要及时清除中断标志,避 免重复处理。
中断优先级设置和嵌套处理
01
VxWorks支持多级中断优先级,高优先级的中断可以打断低优先 级的中断处理。
02
中断优先级可以通过配置文件或动态调整进行设置,以满 足不同应用场景的需求。
03
在处理中断时,如果发生更高优先级的中断请求, VxWorks会自动保存当前中断的上下文信息,并跳转到更 高优先级的中断处理程序中。处理完成后,再恢复之前中 断的上下文信息并继续执行。这种机制称为中断嵌套处理 。

vxworks 使用案例

vxworks 使用案例

vxworks 使用案例VxWorks是一款实时操作系统(RTOS),广泛应用于嵌入式系统、工业控制、航空航天、军事等领域。

以下是一些VxWorks的典型使用案例:1. 嵌入式设备:VxWorks可用于各种嵌入式设备,如智能家居、无人驾驶汽车、工业机器人等。

在这些设备中,VxWorks可以提供实时性能、低功耗和紧凑的系统资源占用。

2. 航空航天:VxWorks在航空航天领域有着广泛应用,如飞行控制系统、卫星通信系统、航空电子设备等。

在这些系统中,VxWorks需要具备高可靠性、实时性和强大的内存管理能力。

3. 军事系统:VxWorks在军事领域也有广泛应用,如导弹控制系统、雷达系统、指挥控制系统等。

在这些系统中,VxWorks需要满足严格的性能、安全性和可靠性要求。

4. 工业控制:VxWorks可用于各种工业控制系统,如生产线自动化、智能仪表、传感器等。

在这些系统中,VxWorks可以提供实时性能、稳定性和易于扩展的特性。

5. 医疗设备:VxWorks在医疗设备中有广泛应用,如超声波设备、心电监测设备、手术机器人等。

在这些设备中,VxWorks需要具备高可靠性、实时性和良好的兼容性。

6. 通信设备:VxWorks可用于通信设备,如交换机、路由器、基站的控制系统等。

在这些设备中,VxWorks需要提供高性能、低功耗和稳定的系统运行。

7. 汽车电子:VxWorks在汽车电子领域也有广泛应用,如发动机控制系统、刹车控制系统、车载信息娱乐系统等。

在这些系统中,VxWorks 需要满足功能安全、实时性和低功耗的要求。

总之,VxWorks作为一款实时操作系统,在众多领域发挥着重要作用。

其高性能、实时性、可靠性和易用性使得它成为许多嵌入式系统和实时控制应用的首选操作系统。

VxWorks操作系统简介

VxWorks操作系统简介

VxWorks操作系统简介VxWorks操作系统简介VxWorks操作系统是一种广泛应用于嵌入式系统开发的实时操作系统。

本文将详细介绍VxWorks操作系统的架构、特性、应用领域以及相关的法律名词注释。

一、VxWorks操作系统架构VxWorks操作系统采用分层架构,包括内核层、中间层以及外围应用层。

具体架构如下:⒈内核层:提供底层的操作系统服务,包括任务管理、内存管理、中断处理、设备驱动等。

内核层使用高度模块化的设计,可以根据需求选择性地加载不同的内核服务。

⒉中间层:提供更高层次的功能,如文件系统、网络协议栈、图形用户界面等。

中间层通过对内核接口的封装,提供更便捷的应用开发接口。

⒊外围应用层:包括用户应用程序和系统管理工具。

用户应用程序可以基于VxWorks操作系统的开发环境进行开发,并且通过内核和中间层提供的接口与系统进行交互。

二、VxWorks操作系统特性VxWorks操作系统有以下特点:⒈实时性:VxWorks操作系统被广泛应用于实时系统开发,具有快速响应、低延迟和可预测性等特性。

它使用了优化的调度算法和中断处理机制,确保系统对实时任务的及时响应。

⒉可靠性:VxWorks操作系统采用了可靠性设计和故障恢复机制,例如内存保护、任务隔离和异常处理等。

这些机制可最大限度地减少系统崩溃和错误的影响。

⒊可扩展性:VxWorks操作系统具有高度可扩展性,可以根据应用的需要进行灵活配置。

开发人员可以根据系统需求选择性地加载所需的内核服务和中间层模块,以达到最佳性能和资源利用。

⒋安全性:VxWorks操作系统提供了多层次的安全机制,包括权限控制、数据加密和访问控制等。

这些机制可以在网络和物理环境中保护系统不受未经授权的访问和攻击。

三、VxWorks操作系统的应用领域VxWorks操作系统在各行各业都有广泛的应用,特别适用于对实时性和可靠性要求较高的领域。

以下是一些典型的应用领域:⒈工业自动化:VxWorks操作系统被广泛用于控制系统和工业领域,如汽车制造、航空航天和机械制造等。

vxworks系统及函数详解

vxworks系统及函数详解

VxWork介绍及编程VxWork介绍及编程一.嵌入式操作系统VxWorks简介VxWorks操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。

良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地。

它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、军事演习、弹道制导、飞机导航等。

在美国的F-16、FA-18 战斗机、B-2 隐形轰炸机和爱国者导弹上,甚至连1997年4月在火星表面登陆的火星探测器上也使用到了VxWorks。

实时操作系统和分时操作系统的区别从操作系统能否满足实时性要求来区分,可把操作系统分成分时操作系统和实时操作系统。

分时操作系统按照相等的时间片调度进程轮流运行,分时操作系统由调度程序自动计算进程的优先级,而不是由用户控制进程的优先级。

这样的系统无法实时响应外部异步事件。

实时操作系统能够在限定的时间内执行完所规定的功能,并能在限定的时间内对外部的异步事件作出响应。

分时系统主要应用于科学计算和一般实时性要求不高的场合。

实时性系统主要应用于过程控制、数据采集、通信、多媒体信息处理等对时间敏感的场合。

VxWorks的特点•可靠性操作系统的用户希望在一个工作稳定,可以信赖的环境中工作,所以操作系统的可靠性是用户首先要考虑的问题。

而稳定、可靠一直是VxWorks的一个突出优点。

自从对中国的销售解禁以来,VxWorks以其良好的可靠性在中国赢得了越来越多的用户。

•实时性实时性是指能够在限定时间内执行完规定的功能并对外部的异步事件作出响应的能力。

实时性的强弱是以完成规定功能和作出响应时间的长短来衡量的。

VxWorks 的实时性做得非常好,其系统本身的开销很小,进程调度、进程间通信、中断处理等系统公用程序精练而有效,它们造成的延迟很短。

系统调用原理

系统调用原理

系统调用原理(最新版)目录1.系统调用的概念与作用2.系统调用的分类3.系统调用的实现原理4.系统调用的应用实例5.系统调用与用户程序的关系正文一、系统调用的概念与作用系统调用(System Call)是操作系统向用户程序提供的一种申请操作系统服务的接口。

用户程序通过系统调用请求操作系统的帮助,完成文件操作、进程管理、内存管理等任务。

系统调用是操作系统与用户程序之间的桥梁,使得用户程序可以更加高效地使用操作系统的功能。

二、系统调用的分类根据系统调用的功能,可以将其分为以下几类:1.文件操作:包括创建文件、打开文件、读取文件、写入文件、关闭文件等。

2.进程管理:包括创建进程、终止进程、切换进程、获取进程信息等。

3.内存管理:包括分配内存、释放内存、复制内存等。

4.设备管理:包括设备分配、设备回收、设备操作等。

5.其他系统服务:包括获取系统时间、随机数生成等。

三、系统调用的实现原理系统调用的实现原理可以分为以下几个步骤:1.用户程序调用库函数:用户程序调用库函数,如 C 语言的标准库函数,来实现文件操作、进程管理等功能。

2.库函数调用系统调用:库函数通过调用系统调用来请求操作系统提供相应的服务。

3.操作系统处理:操作系统根据系统调用的类型,执行相应的操作,如文件操作、进程管理等。

4.返回结果:操作系统将处理结果返回给库函数。

5.库函数返回结果给用户程序:库函数将操作系统返回的结果返回给用户程序。

四、系统调用的应用实例以下是一个简单的系统调用应用实例,使用 C 语言编写,通过系统调用实现文件的创建和写入功能:```c#include <stdio.h>#include <unistd.h>int main() {int fd = open("example.txt", O_CREAT | O_TRUNC | O_WRONLY, 0644);if (fd < 0) {perror("open");return -1;}write(fd, "Hello, system call!", 25);close(fd);return 0;}```五、系统调用与用户程序的关系系统调用是操作系统为用户程序提供的一种服务接口,用户程序通过系统调用来请求操作系统的帮助,实现文件操作、进程管理等功能。

VxWorks动态加载

VxWorks动态加载

VxWorks动态加载注:最近在做热补丁的功能,看到一篇gateway写的文章,觉得很通俗易懂的,就将搜集到的资料又整理了一下,供大家参考。

使用动态加载目标模块的方式有很多好处,比如可以在不破坏原来的环境下增加调试定位功能,相当于给系统打“补丁”,不需要编译原来的代码(甚至可以不用原来的代码)而只需要关注正在调试的代码,这样能减少编译时间和减少映像的加载量。

实现目标模块的动态加载有很多种方法,如在主机环境的界面上通过在目标模块上单击鼠标右键,选择“Download 文件名”;也可以通过wShell和GDB 命令行窗口实现。

本文通过tshell下使用ld()、loadModule()、loadModuleAt()中一个函数来实现,当然在代码中也可以自如地调用它们。

ld命令是由用户接口子程序库usrLib提供的一个加载命令。

使用ld的前提是在config.h中定义INCLUDE_LOADER。

这样,在usrRoot()函数中就会自动调用加载模块初始化函数moduleLibInit();同时,根据CPU类型,自动决定目标模块的格式。

如果CPU是MIPS、PPC、ARM、I80X86、COLDFIRE、SIMSPARCSOLARIS、SH等,加载的目标模块格式是elf类型,就会调用loadElfInit();如果CPU是I960、AM29XXX等,加载的目标模块的格式则是coff 类型,就会调用loadCoffInit()函数。

在ARM和PPC下,Tornado编译器生成的.o或.out都是elf类型,打开目标文件都会看到文件头有ELF(45,4C,46)标记。

这时可以通过ftp工具把它加载到文件系统(如使用copy命令加载到RAM盘)中,再调用ld()或loadModule()函数加载到内存中运行。

ld的函数原型是:MODULE_ID ld( int syms, BOOL noAbort, char *name )。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

VxWorks自定义动态系统调用的应用解建伟;赖前程;曹成军;张兴旺【摘要】The user mode application through system calls interface can access the kernel services and hardware resources.Custom system calls in VxWorks has a very important role in applicationdevelopment.Applications of user mode are able to access more kernel functions or other hardware resources through custom systemcalls,extending the scope of application.Thus,the concept of custom system calls in VxWorks and the system calls process are described,then the implementation process of the dynamical custom system calls is introduced step by step.Finally,the method of using dynamical custom system calls in application program is introduced.%系统调用是用户模式程序访问内核服务、硬件资源的接口.自定义的系统调用在VxWorks程序开发中有着非常重要的作用.通过自定义系统调用可以让用户模式的程序访问更多的内核函数、硬件资源,可以扩展程序的应用范围.简单论述VxWorks中自定义系统调用的概念,描述系统调用的过程,分步介绍自定义动态系统调用的实现过程.最后介绍应用程序中动态系统调用的使用方法.【期刊名称】《计算机应用与软件》【年(卷),期】2017(034)002【总页数】5页(P242-245,266)【关键词】VxWorks;自定义;系统调用【作者】解建伟;赖前程;曹成军;张兴旺【作者单位】中国电器科学研究院有限公司广东广州510300;中国电器科学研究院有限公司广东广州510300;中国电器科学研究院有限公司广东广州510300;中国电器科学研究院有限公司广东广州510300【正文语种】中文【中图分类】TP316.2VxWorks是美国风河公司设计开发的嵌入式实时操作系统,它支持多种处理器平台,具有较高的可扩展性与安全性。

VxWorks在6.0版本之前的系统只提供一个内存地址空间,用户程序和操作系统程序没有做隔离,所有的任务都运行在特权模式。

尽管这种形式为程序开发提供了比较好的性能和灵活性,但也使内核与应用程序在内存空间存在相互干扰的可能。

在6.0版本以后,操作系统开始支持实时进程RTP(real-time processes),它支持应用程序在用户模式运行,并且是与操作系统内核完全隔离的运行模型。

这种模型是专门为满足硬实时操作系统对确定性和速度的要求而设计[1]。

VxWorks中的RTP在很多方面都与Unix和Linux的用户态的进程类似,每个进程都有自己的地址空间,包括可执行代码、数据堆栈以及自身相关的管理资源[2]。

这使得系统的安全性得到极大提高,同时系统调用接口为用户态的应用程序提供了访问内核的接口[3]。

系统调用常用于RTP程序访问内核服务,CPU外设或其他硬件资源。

需要说明的是应用编程接口(API)与系统调用是不同的,前者是一个函数定义,说明如何获得一个给定的服务,而后者是通过软中断向内核发出一个明确的模式切换请求[4]。

由于特权模式的内核程序和用户模式程序有不同的指令集和内存管理单元MMU(memory management unit)设置,应用程序运行在用户模式时不能直接访问内核函数和数据结构。

用户模式程序执行系统调用函数时系统从用户模式切换到CPU特权级别的内核模式,当执行完函数后再恢复到用户模式[5]。

VxWorks中系统调用的模式切换过程对使用者来说是透明的[1]。

在RTP程序中使用实时系统原有的系统调用与内核交互时,时常会出现不满足设计需求或性能指标的情况[6]。

通过增加自定义系统调用,我们可以根据自己的需求,来给内核增加特定的功能,满足性能指标和设计需求[7]。

在VxWorks中的系统调用一般可分为两大类,一类是操作系统定义的系统调用,像exit、create、open、semGive等都是系统调用;另外一类是用户自定义的系统调用。

VxWorks中的自定义系统调用又分为静态自定义系统调用和动态自定义系统调用两种。

这两种系统调用的实现方式不同,性能都基本一致,但是它们各有优缺点。

自定义的静态系统调用的优势在于它是与操作系统源码一起编译,可根据需要修改系统原有的系统调用函数;在使用时与普通的函数调用方式一致。

不足之处是修改定义系统调用要对系统核心文件作修改,编译调试,这会带来比较大的工作量,一个小小的失误往往会使系统不稳定甚至崩溃,系统可靠性和稳定性不容易保证;同时增加、修改系统调用都比较麻烦,使得系统可维护性与可移植性将会降低[8]。

动态的系统调用只需要在运行时向系统注册自定义系统调用,不需要像自定义静态系统调用那样修改VxWorks源代码文件,不需要与操作系统一起重新编译生成[2]。

其优势是不需要对系统核心代码做更改,减少了对内核稳定性的影响;同时对新增系统调用的修改、更新、删除都比较方便。

不足之处在于一般不能通过名字直接访问动态系统调用函数,在应用的时候需要知道自定义动态系统调用的组编号和索引位置,然后统一由syscall函数调用。

2.1 分析与设计在VxWorks6.9实时操作系统中用户自定义的系统调用主要有3个元素:(1) 系统调用。

执行系统调用的是使用汇编语言编写的一个函数,它通过C语言调用。

区别不同系统调用的方式是在调用时使用系统调用函数名字和系统调用编号,这是系统开发人员定义的。

(2) 捕获处理。

当用户RTP程序访问系统调用时会执行捕获指令处理,它将调用的程序从用户模式切换到特权(内核)模式执行。

系统调用编号传递给内核去识别关联的函数。

在内核中,捕获处理从用户堆栈或寄存器空间拷贝系统调用参数到内核堆栈空间,然后调用系统调用关联匹配的处理函数。

(3) 处理函数。

系统调用的处理函数是系统开发者编写的程序,它只有一个结构体变量参数,结构体成员就是系统调用的参数[3]。

当系统从处理函数返回,调用任务将从特权(内核)模式切换到用户模式。

用户自定义动态系统调用程序的实现一般可以分为以下3个步骤:(1) 设计参数结构,编写处理函数;(2) 添加系统调用处理表结构信息;(3) 注册系统调用函数及相关设置。

VxWorks文档建议,对于添加动态系统调用的方法最好使用统一的命名约定,使得系统调用的逻辑一致性和代码的清晰度最好。

命名约定如表1所示。

设计的实时控制系统中需要实现RTP应用程序读写FPGA中的数据动态系统调用,其中FPGA是挂载在处理器的IFC(Integrated Flash Controller)接口上通过绝对地址访问。

根据命名约束,在内核任务程序中需要实现两个自定义动态系统调用get_fpga_registerSc和set_fpga_registerSc函数,并为它们注册合适的系统调用编号,检查系统调用的注册信息。

最后在RTP程序中通过使用此动态统调用访问FPGA的寄存器内容,检查执行正确性。

2.2 实现过程第一步是设计、编写动态系统调用函数,及其参数结构。

自定义读写函数的系统调用其声明如下:int set_fpga_registerSc(SysCallSetRegScArgs *pArgs);int get_fpga_registerSc(SysCallGetRegScArgs *pArgs);其中动态系统调用定义必须要有整型的返回值,参数是通过指向参数结构体的指针来进行传递。

自定义动态系统调用函数最多可以有8个参数,即最多可以只有8个结构体成员。

每个参数长度都是本机字大小(32位处理器参数长度就是32位,64位处理器参数长度就是64位),如果在32位系统上要传递64位参数需要特别处理。

get_fpga_registerSc系统调用有2个参数,其传递的参数结构体如下:typedef struct{unsigned int index;unsigned short* pV;} SysCallGetRegScArgs;函数get_fpga_registerSc的执行是在内核中完成,执行时所有参数在使用前必须做边界值检查,验证使用的内存地址,以及检查数据结构的有效性。

对内存地址的验证是实际大小的缓冲大小,而不是最大缓冲大小。

也就是说RTP程序分配了一个20个字节的缓冲区,那么系统调用函数应该验证这20个字节的内存,如果系统调用函数验证这个缓冲的最大长度(比如64个字节)可能会因为只有20个字节被分配而出错。

解决这个问题的最好方法是通过参数告诉系统调用函数使用的缓冲空间的大小信息。

对动态系统调用函数get_fpga_registerSc的实现如下:int get_fpga_registerSc(SysCallGetRegScArgs *pArgs){if(pArgs->index > FPGA_AGREED_MAX_SIZE){errno = EMSGSIZE;return ERROR;}if (scMemValidate (pArgs->pV, sizeof(unsigned short), SC_PROT_WRITE) == ERROR){errno = EINVAL;return ERROR;}if(FPGA_GetValue(pArgs->index,pArgs->pV)==ERROR){errno = EINVAL;return ERROR;}return OK;}在执行时首先验证读取的FPGA地址是否已经超出了可访问范围,然后使用scMemValidate函数来验证第二个参数地址写入的有效性,最后读取FPGA指定地址的数据并返回。

系统调用内存验证函数scMemValidate的第一个参数是验证的起始地址,第二个是验证地址的数据或结构的长度,第三个参数是地址空间访问模式,它分为读、写、以及线程安全的读写3种模式。

这3种模式中的读、写可以组合使用,而线程安全的读写不可以组合使用。

在参数检查、内存验证、以及执行过程中如果出现了错误,需要根据具体情况对errno设置一个合适的异常值,然后返回错误-1(ERROR),如果正常则返回0(OK)。

相关文档
最新文档