嵌入式操作系统实验报告.docx

上传人:小飞机 文档编号:3102900 上传时间:2023-03-10 格式:DOCX 页数:29 大小:49.15KB
返回 下载 相关 举报
嵌入式操作系统实验报告.docx_第1页
第1页 / 共29页
嵌入式操作系统实验报告.docx_第2页
第2页 / 共29页
嵌入式操作系统实验报告.docx_第3页
第3页 / 共29页
嵌入式操作系统实验报告.docx_第4页
第4页 / 共29页
嵌入式操作系统实验报告.docx_第5页
第5页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《嵌入式操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《嵌入式操作系统实验报告.docx(29页珍藏版)》请在三一办公上搜索。

1、嵌入式操作系统实验报告中南大学信息科学与工程学院 实验报告 姓名:安磊 班级: 计科0901 学号: 0909090310 1 指导老师:宋虹 2 目录 课程设计内容 - 3 uC/OS操作系统简介 - 3 uC/OS操作系统的组成 - 3 uC/OS操作系统功能作用 - 4 uC/OS文件系统的建立 - 6 文件系统设计的原则 -6 文件系统的层次结构和功能模块 -6 文件系统的详细设计 - 8 文件系统核心代码 - 9 课程设计感想 - 11 附录 - 3 12 课程设计内容 在uC/OS操作系统中增加一个简单的文件系统。 要求如下: (1) 熟悉并分析uc/os操作系统 (2) 设计并实

2、现一个简单的文件系统 (3) 可以是存放在内存的虚拟文件系统,也可以是存放在磁盘的实际文件系统 (4) 编写测试代码,测试对文件的相关操作:建立,读写等 课程设计目的 操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。 本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握操作系统开发的基本技能。 IuC/OS操作系统简介 C/OS-II是一种可移植的,可植入ROM的,可裁剪的,抢占式的,实时多任务操作系统内核。它被广泛应用于微处理器、微控制器和数字

3、信号处理器。 C/OS 和C/OS-II 是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将C/OS-II嵌入到开发的产品中。C/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至 2KB 。C/OS-II 已经移植到了几乎所有知名的CPU 上。 严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内

4、存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。 uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。 uC/OS操作系统的组成 C/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。如下图: 4 uc/os核心任务处理时间管理任务通信和同步cpu的移植每个部分具体作用 1) 核心部分(OSCore.c) 是操作系统的处理

5、核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。 2) 任务处理部分(OSTask.c) 任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为C/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。 3) 时钟部分(OSTime.c) C/OS-II中的最小时钟单位是timetick。任务延时等操作是在这里完成的。 4) 任务同步和通信部分 为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。 5) 与CPU的接口

6、部分 是指C/OS-II针对所使用的CPU的移植部分。由于C/OS-II是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。 uC/OS操作系统功能作用 任务管理 5 uC/OS-II 中最多可以支持64 个任务,分别对应优先级063,其中0 为最高优先级。63为最低级,系统保留了4个最高优先级的任务和4个最低优先级的任务,所有用户可以使用的任务数有56个。 uC/OS-II提供

7、了任务管理的各种函数调用,包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。 系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,该任务仅给一个整形变量做累加运算;另一个是系统任务,它的优先级为次低,该任务负责统计当前cpu的利用率。 时间管理 uC/OS-II的时间管理是通过定时中断来实现的,该定时中断一般为10毫秒或100毫秒发生一次,时间频率取决于用户对硬件系统的定时器编程来实现。中断发生的时间间隔是固定不变的,该中断也成为一个时钟节拍。 uC/OS-II要求用户在定时中断的服务程序中,调用系统提供的与时钟节拍相关的系统函数,例如中断级的任务切换函数,系统时间函数。

8、 内存管理 在ANSI C中是使用malloc和free两个函数来动态分配和释放内存。但在嵌入式实时系统中,多次这样的操作会导致内存碎片,且由于内存管理算法的原因,malloc和free的执行时间也是不确定。 uC/OS-II中把连续的大块内存按分区管理。每个分区中包含整数个大小相同的内存块,但不同分区之间的内存块大小可以不同。用户需要动态分配内存时,系统选择一个适当的分区,按块来分配内存。释放内存时将该块放回它以前所属的分区,这样能有效解决碎片问题,同时执行时间也是固定的。 任务间通信与同步 对一个多任务的操作系统来说,任务间的通信和同步是必不可少的。uC/OS-II中提供了4种同步对象,分

9、别是信号量,邮箱,消息队列和事件。所有这些同步对象都有创建,等待,发送,查询的接口用于实现进程间的通信和同步。 任务调度 uC/OS-II 采用的是可剥夺型实时多任务内核。可剥夺型的实时内核在任何时候都运行就绪了的最高优先级的任务。 uC/os-II的任务调度是完全基于任务优先级的抢占式调度,也就是最高优先级的任务,一旦处于就绪状态,则立即抢占正在运行的低优先级任务的处理器资源。为了简化系统设计,uC/OS-II规定所有任务的优先级不同,因为任务的优先级也同时唯一标志了该任务本身 6 IIuC/OS文件系统的建立 uC/OS操作系统本身是没有自带文件系统的。但可由用户自行设计。 文件系统设计的

10、原则: 1.简洁性 现有的比较完善的文件系统功能齐全、对系统资源要求较高,而我们所需要的这个嵌入式文件系统是嵌入式平台的一个中间件,要求简洁高效可靠。为此我们在设计过程中借鉴了MS-DOS的FAT16文件系统格式的目录形式进行文件管理,打开文件数据结构则采用了类似于UNIX系统文件表的方式,为每一个打开文件设置了一个数据结构指针FS_FILE,使得用户接口简洁明了。 2.多设备驱动支持 考虑到应用的广泛性和存储介质的多样性,要求我们在进行设计文件系统时必须考虑对多种存储介质的兼容性。整个系统采用模块化分层设计的原则和面向对象的实现方法,使得用户可以通过统一的顶层应用程序接口方便地对各种存储介质

11、进行文件操作。利用本文件系统可以管理不同的存储介质,可以同时访问不同的硬件。 3.多操作系统支持 文件系统的开发是基于ucos ii,在设计开发过程中,考虑到以后对多操作系统的支持,OS接口模块设计为动态可变,当文件系统应用于其它操作系统时,只需将OS接口模块中的操作系统信息变为新的操作系统即可。 4.可靠性 由于嵌入式系统的数据资源的重要性,要求存储数据的物理介质必须具有很高的稳定性,可是我们知道一些人为或外在的因素可能会导致介质的损坏,从而造成数据的缺失,所以我们要尽可能提高文件系统可靠性。 文件系统的层次结构和功能模块 API层中间转换层介质驱动层7 嵌入式文件系统由于功能和作用与普通桌

12、面操作系统的文件系统不同,导致了二者在体系结构上具有很大的差异性。在普通桌面操作系统中,文件系统不仅要管理文件,提供文件系统调用API,还要管理各种设备,支持对设备和文件操作的一致性。在嵌入式文件系统中,这种规则发生了很大的变化。在某些情况下,嵌入式系统可以针对特殊的目的来进行定制,对嵌入式操作系统的系统功能规整性、可伸缩性及其灵活性提出了更高的要求。 基于以上的考虑,我们采用了如上图所示的嵌入式文件系统体系结构,该结构定义的文件系统从上到下有三个层次:第一层为API层、第二层为中间转换层、下层为介质驱动层。 API层 API层是文件系统和用户应用程序之间的接口,它有一个标准C函数库,其中包含

13、有诸如打开文件、写文件等函数。本层的功能是将用户调用传送给中间转换层。这是整个系统设计的核心,也是嵌入式文件系统中用户唯一可见的部分 POSIX中文件系统的标准系统调用全部在该部分中得以实现。 中间转换层 中间转换层要为文件系统的实现提供与硬件无关的统一接口,是文件系统结构规整性的基础。中间转换层包含有文件系统子层及逻辑块子层,其中文件系统子层将文件操作解释到逻辑块子层,然后文件系统调用逻辑块子层并根据不同的设备定义出相应的设备驱动程序;逻辑块子层主要是同步对设备驱动程序的访问,向上提供友好界面。 介质驱动层 介质驱动层是访问硬件的最低端的程序,该程序的结构要能够便于实现对硬件的访问。本层的功

14、能主要是完成对介质的访问。本层的重要任务就是提供统一的设备驱动程序接口。 API接口模块磁盘分区模块API接口模块 中间转换模块设备驱动模块根据文件系统的层次结构,可以将该文件系统分成四大功能块:API接口模块、中间转换模块、磁盘分区模块、设备驱动模块。如上图: 主要完成文件的基本操作,包含有文件的生成、删除、打开、关闭、文件读、文件写等。 中间转换模块 主要完成对存取权限的检查、介质的选择、逻辑到物理的转换。 磁盘分区模块 主要完成对几个主要数据结构的初始化,设置文件系统的总体分区信息以及每个分区的几部分:空闲块管理、引导区、FAT区、文件存储区等。 设备驱动模块 8 完成存储介质的驱动程序

15、,包含有一个驱动程序函数表和介质读、介质写、检查状态、执行特定命令等驱动程序。 文件系统的详细设计 文件系统组织方式 文件系统逻辑组织为流式文件,物理组织为连续文件。用户对于流式文件的访问是以字节为单位的。每个文件的内部有一个读写指针,通过系统调用可以将该指针固定到文件的某一个位置处,以后的读写系统调用将从该指针所确定的位置处开始。而用于保存文件的物理设备是划分为块页的,文件的物理结构就是要确定如何将字节保存在存储介质中。所以说文件的物理组织形式对于文件系统的性能有着较为直接的影响,所以我们在进行文件的物理组织选择时比较慎重。结合我们系统的实际应用情况,我们决定文件的物理组织方式采用顺序结构,

16、这是因为我们的嵌入式应用环境要求实时性高,采集到的数据一旦以文件的方式存储在介质上很少进行改动,也即文件的长度变化不大,所以我们将逻辑文件的信息存放在外存的连续编号的物理块中。 文件和文件控制块FCB 为了实现对于文件的管理,系统需要掌握一组有关文件的描述信息,例如文件的名称、文件的地址、文件的建立曰期等等,这些信息组合在一起构成一个数据结构,在这里我们称之为文件控制块FCB。FCB是文件存在的标志,其中记录着系统对于文件进行管理所需要的全部信息,FCB所包含内容如图2所示。每一个文件都有一个文件控制块,它们被保存于外存空间,当系统欲访问一个文件时,应当能够根据文件名字找到它所对应的文件控制块

17、,然后根据文件控制块中的文件位置信息找到该文件具体所存放的区域。 文件描述符 文件描述符由基本文件名和扩展文件名两部分构成,二者以圆点分开。文件名由1-8个字符构成,扩展名由1-3个字符构成。分别占据FCB中的00H- 07H和08H-0AH两部分。在FCB中,文件名和扩展名是左对齐放置的,剩余部分填入空格码。当进行文件删除时,在文件目录记录项的第一字节中放入 E5H,表示该记录项是空项。从公平没有使用过的记录项的第一字节中写入的是00H,刚刚格式化的根文件目录或刚刚生成的子文件目录的未使用文件目录记录项的开头写入的均是00H。这个00H在文件进行检索时特别有用,主要是用来确定搜索到文件目录的

18、什么区域就可以不用再继续搜索了。例如,当文件检索中没有00H时,必须对全文件目录区进行检索,而一旦遇到有00H的场合,检索便宣告结束,这样可以大大缩短检索文件的时间,提高了文件检索的效率。 对文件的主要操作 文件系统的功能是通过一系列对文件的操作实现的。为此,系统提供给用户一整套系统调用,用以完成创建、打开、读、写、关闭、删除文件等项工作。对应的函数分别为:FS_FOPEN、FS_REMOVE、FS_FCLOSE、FS_FREAD和FS_FWRITE,各函数均通过驱动模块来实现,具体的代码此处不在罗列。 文件的保护机制 由于文件系统保存着用户非常重要的信息,因而如何保护信息、防止未授权使用就是

19、所有文件系统必须要解决的重要问题之一。但系统中的全部信息又不能完全成为私有,还必须进行文件共享,以提高资源的利用率和方便用户使用。 文件共享和保密是一个问题的两个方面。对文件的保护保密是由对文件的共享要求起的。在非共享环境中,不需要再做什么保护,实际上它已经是极端的完全保护情况;相反,另一种极端情况则是完成共享,而不做任何保护。这两种情况都缺乏实用意义,一般用法是有控制9 的进行文件共享。保护机制通过限制文件的存取类型来实现受控制共享。允许或禁止对文件的存取受多种因素的限制,如用户的身份、文件本身的性质、对文件所要进行的存取类型等。常用的保护机制有命名、口令、存取控制、密码等,对文件的保护必须

20、要根据实际需要和实现的可能性来选择合适的方法。由于本文件系统主要是以FAT文件系统为基础来进行设计的,所以在对文件进行保护和共享方面同样也有FAT文件系统所具有的不足,没有一套完整的文件保护机制来完成对文件的保护,安全特性只能通过共享权限来加以实现。 文件系统核心代码截图 各部分代码文件功能解释 api_dir.c Purpose: 对 文件系统的目录 的各种操作,包括显示目录建立,删除等操作的函数 api_in.c Purpose: FS_FRead函数,从文件中读取数据 api_misc.c Purpose: 对 文件 的各种的操作函数,打开文件,关闭文件,删除文件,文件系统初始化 api

21、.out_.c Purpose: 向一个文件写入数据,FS_FWrite函数 10 app.c: Purpose:.主函数.1.向系统申请一段内存空间2.fs.c app_cfg.c Porpose:定义申请空间的程序的优先级 定义程序开始时的栈的大小 clibmisc.c Purpose:由于该文件系统所用的c库文件并非c的运行库函数,而是自己的库函数 包括字符串的复制,比较,测量长度,二进制与字符串的相互转化, 由src所指内存区域复制count个字节到dest所指内存区域.大小写转换函数等 fs.c Purpose:.文件操作测试函数. 包括函数:向某个文件写(write_file)数据

22、(*txt) _dump_file(const char *name)利用文件系统读取一个文件 fs_api.h Purpose:声明file_system的全局函数,定义各种宏 fs_cong.h Propose:此文件包含该文件系统的所有设置 fs_dev.h Purpose: 定义驱动器驱动的结构FS_device_type, 写入参数,设备控制函数) fs_fsl.h Purpose:定义文件系统层的结构FS_fsl_type fs_info.c Purpose:定义文件系统层功能表,设备驱动程序函数表,逻辑块层缓存,其中的 _Fs_devinfo结构可以简述该文件系统是建立在何种设备

23、之上的 fs_int.h Purpose:定义内部参数,这些参数是在整个文件系统层的不同层均有使用 fs_os.h Purpose:定义文件系统的系统层的函数声明 fs_port.h Purpose:体系结构定义了文件系统的依赖 这个头文件定义了几乎所有的基本的数据类型和宏 ,该参数可以根据你的编译器 和cpu的种类而改变 fs_x_ucos_ii.c Purpose:对文件句柄的上锁和解锁操作,对文件option的上锁和解锁操作 对目录的句柄的上锁和解锁操作 /*filehandle是一个数字,在文件打开的时候由操作系统分配给一个文件。当访问文件的时候 操作系统使用内部的文件句柄,。一块特殊

24、的区域的内存被预留给文件句柄,这个区域的大小决定了有多少 文件可以同时打开。在DOS和Windows,你可以设置最大数量的打开的文件*/ 11 ide_x_hw.h Purpose:Segger SED137XE 板的硬件层 是一个CF卡,在IDE模式P8.P9.P10.P7 os_cfg.h Purpose:对系统的宏定义 *name:指向文件名的指针 myfile:文件的物理地址.myfile=FS_FOpen(name,r); int x:对应地址的字符 x = FS_FRead(mybuffer,1,sizeof(mybuffer)-1,myfile) FS_FClose(myfile

25、);关闭文件 UCOS-II :ucos的源代码 UCOS-II-PORT:移植系统时需要修改的部分 III.课程设计感想 通过本次课程设计,使我对uC/OS操作系统有了更深入的理解。操作系统是一门实践性较强的课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。一个人的力量是有限的,要想把课程设计做的更好,就要学会参考一定的资料,吸取别人的经验,让自己和别人的思想有机的结合起来,得出属于你自己的灵感。 程序的编写需要有耐心,有些事情看起来很复杂,但问题需要一点一点去解决,分析问题,把问题一个一个划分,划分成小块以后就逐个去解决。再总体解决大的问题。这样做起来不仅有条理也使问题得到了

26、轻松的解决。 在这个过程中,我也曾经因为实践经验的缺乏失落过,也曾经仿真成功而热情高涨。生活就是这样,汗水预示着结果也见证着收获。劳动是人类生存生活永恒不变的话题。虽然这只是一次的极简单的课程制作,可是平心而论,也耗费了我不少的心血,这就让我不得不佩服开发技术的前辈,才意识到老一辈对我们社会的付出,为了人们的生活更美好,他们为我们社会所付出多少心血啊! 对我而言,知识上的收获重要,精神上的丰收更加可喜。让我知道了学无止境的道理。我们每一个人永远不能满足于现有的成就,人生就像在爬山,一座山峰的后面还有更高的山峰在等着你。挫折是一份财富,经历是一份拥有。这次课程设计必将成为我人生旅途上一个非常美好

27、的回忆! 通过这次的课程设计我对于专业课的学习有了更加深刻的认识,以为现在学的知识用不上就加以怠慢,等到想用的时候却发现自己的学习原来是那么的不扎实。以后努力学好每门12 专业课,让自己拥有更多的知识,才能解决更多的问题! IV.附录 因为本次课程设计为小组合作完成。我只负责系统到硬件的代码编写。现附上代码如下: fs_dev.h /* * * Micrium, Inc. * 949 Crestview Circle * Weston, FL 33327-1848 * * uC/FS * * (c) Copyright 2002, Micrium, Inc. * All rights rese

28、rved. * * - File : fs_dev.h Purpose : Define structures for Device Drivers - Known problems or limitations with current version - None. -END-OF-HEADER- */ #ifndef _FS_DEV_H_ #define _FS_DEV_H_ 13 /* * * Global data types * * */ typedefstruct FS_FARCHARPTR name; int (*dev_status)(FS_u32 id); int (*de

29、v_read)(FS_u32 id, FS_u32 block, void *buffer); int (*dev_write)(FS_u32 id, FS_u32 block, void *buffer); int (*dev_ioctl)(FS_u32 id, FS_i32 cmd, FS_i32 aux, void *buffer); FS_device_type; #endif - fs_info.h /* * * Micrium, Inc. * 949 Crestview Circle * Weston, FL 33327-1848 * * uC/FS * * (c) Copyrig

30、ht 2001 - 2003, Micrium, Inc. 14 * All rights reserved. * * - File : fs_conf.c Purpose : File system configurable global data Unless you are going to add own device drivers, or you would like to modify e.g. order in the device table, you do not have to modify this file. Usually all configuration can

31、 be made in fs_conf.h. - Known problems or limitations with current version - None. -END-OF-HEADER- */ /* * * #include Section * * */ #include fs_port.h #include fs_dev.h #include fs_api.h #include fs_fsl.h #include fs_int.h 15 #include fs_conf.h /* * * Externals * * */ /* * * File System Layer Func

32、tion Tables */ /* FAT function table */ #ifdef FS_USE_FAT_FSL externconst FS_fsl_type FS_fat_functable; #endif /* FS_USE_FAT_FSL */ /* * * Device Driver Function Tables * If you add an own device driver, you will have to add an external for its function table here. */ /* RAMDISK_DRIVER function tabl

33、e */ 16 #if FS_USE_RAMDISK_DRIVER externconst FS_device_type FS_ramdevice_driver; #endif /* FS_USE_RAMDISK_DRIVER */ /* WINDRIVE_DRIVER function table */ #if FS_USE_WINDRIVE_DRIVER externconst FS_device_type FS_windrive_driver; #endif /* FS_USE_WINDRIVE_DRIVER */ /* SMC_DRIVER function table */ #if

34、FS_USE_SMC_DRIVER externconst FS_device_type FS_smcdevice_driver; #endif /* FS_USE_SMC_DRIVER */ /* MMC_DRIVER function table */ #if FS_USE_MMC_DRIVER externconst FS_device_type FS_mmcdevice_driver; #endif /* FS_USE_SMC_DRIVER */ /#if FS_USE_IDE_DRIVER /extern const FS_device_type FS_idedevice_drive

35、r; /#endif /* FS_USE_IDE_DRIVER */ #if FS_USE_FLASH_DRIVER externconst FS_device_type FS_flashdevice_driver; #endif /* FS_USE_FLASH_DRIVER */ /* * 17 * Local variables * * */ /* * * Logical Block Layer Cache * If FS_USE_LB_READCACHE is enabled, then the buffer definition for each media is done here

36、according to the settings in fs_conf.h. */ #if FS_USE_LB_READCACHE /* RAMDISK cache settings. There is no cache required for RAM. */ #define FS_CACHEINFO_RAMDISK_DRIVER 0, /* Windrive cache settings. The driver does have its own cache. Therefore we never use LB read cache for it. */ #define FS_CACHE

37、INFO_WINDRIVE_DRIVER 0, /* FLASH cache settings. 18 There is no read cache required for flash. */ #define FS_CACHEINFO_FLASH_DRIVER 0, /* SmartMedia cache settings */ #ifndef FS_SMC_CACHENUM #define FS_SMC_CACHENUM 0 #endif #if (FS_SMC_CACHENUM) & (FS_USE_SMC_DRIVER) static _FS_SMC_BuffersFS_SMC_MAX

38、UNITFS_SMC_CACHENUM; static FS_LB_CACHE _FS_SMC_CacheFS_SMC_MAXUNIT = #if (FS_SMC_MAXUNIT=1) FS_SMC_CACHENUM, 0, &_FS_SMC_Buffers00 ; #elif (FS_SMC_MAXUNIT=2) FS_SMC_CACHENUM, 0, &_FS_SMC_Buffers00, FS_SMC_CACHENUM, 0, &_FS_SMC_Buffers10 ; #else #error Please define _FS_SMC_Cache for desired number of units #endif #define FS_CACHEINFO_SMC_DRIVER &_FS_SMC_Cache0, #else #define FS_CACHEINFO_SMC_DRIVER 0, #endif /* MMC/SD cache settings */ #ifndef FS_MMC_CACHENUM #define FS_MMC_CAC

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号