开发工具介绍课件.ppt

上传人:牧羊曲112 文档编号:1330515 上传时间:2022-11-10 格式:PPT 页数:80 大小:1.13MB
返回 下载 相关 举报
开发工具介绍课件.ppt_第1页
第1页 / 共80页
开发工具介绍课件.ppt_第2页
第2页 / 共80页
开发工具介绍课件.ppt_第3页
第3页 / 共80页
开发工具介绍课件.ppt_第4页
第4页 / 共80页
开发工具介绍课件.ppt_第5页
第5页 / 共80页
点击查看更多>>
资源描述

《开发工具介绍课件.ppt》由会员分享,可在线阅读,更多相关《开发工具介绍课件.ppt(80页珍藏版)》请在三一办公上搜索。

1、开发工具介绍ppt课件,开发工具介绍ppt课件,“工欲善其事, 必先利其器”-论语,xlanchen2006.5.18,2,Embedded Operating Systems,xlanchen2006.5.182Embedded,开发工具介绍课件,开发工具介绍课件,交叉开发平台,主机:开发软件的平台,称为主机,往往是通用电脑;目标机:运行软件的平台,称为目标机,在这里是嵌入式系统。,xlanchen2006.5.18,5,Embedded Operating Systems,交叉开发平台主机:开发软件的平台,称为主机,往往是通用电脑,嵌入式交叉开发工具,掌握嵌入式开发工具的使用是进行嵌入式开

2、发的前提条件之一与主流软件开发工具类似,嵌入式交叉开发工具也包括编译器,即能够把一个源程序编译生成一个可执行程序的软件调试工具,即能够对执行程序进行源码或汇编级调试的软件软件工程工具,用于协助多人开发或大型软件项目的管理的软件,xlanchen2006.5.18,6,Embedded Operating Systems,嵌入式交叉开发工具掌握嵌入式开发工具的使用是进行嵌入式开发的,GNU tools,GNU tools和其他一些优秀的开源软件可以完全覆盖上述类型的软件开发工具。为了更好的开发嵌入式系统,需要了解如下一些软件GCCBinutils辅助GCC的主要软件Gdbmakecvs,xlan

3、chen2006.5.18,7,Embedded Operating Systems,GNU toolsGNU tools和其他一些优秀的开源软件,GCC,很多人认为GCC只是一个C编译器,其实GCC = GNU Compiler Collection目前,GCC可以支持多种高级语言,如C、C+ADAObject CJAVAFortranPASCAL,xlanchen2006.5.18,8,Embedded Operating Systems,GCC很多人认为GCC只是一个C编译器,其实GCC = G,GCC下的工具,cpp 预处理器GNU C编译器在编译前自动使用cpp对用户程序进行预处理g

4、cc 符合ISO等标准的C编译器g+ 基本符合ISO标准的C+编译器gcj GCC的java前端gnat GCC的GNU ADA 95前端,xlanchen2006.5.18,9,Embedded Operating Systems,GCC下的工具cpp 预处理器GNU C编译器在编译前,GNU Toolsgcc,gcc是一个强大的工具集合,它包含了预处理器,编译器,汇编器,链接器等组件。它会在需要的时候调用其他组件。输入文件的类型和传递给gcc的参数决定了gcc调用具体的哪些组件。对于开发者,它提供的足够多的参数,可以让开发者全面控制代码的生成,这对嵌入式系统级的软件开发非常重要,xlanc

5、hen2006.5.18,10,Embedded Operating Systems,GNU Toolsgccgcc是一个强大的工具集合,它包含,gcc使用举例(1)源程序,xlanchen2006.5.18,11,Embedded Operating Systems,gcc使用举例(1)源程序xlanchen2006.5.,gcc使用举例(2)编译和运行,编译,运行,xlanchen2006.5.18,12,Embedded Operating Systems,gcc使用举例(2)编译和运行编译运行xlanchen2,gcc的工作工程(1),如果使用-v选项,则可以看到许多被隐藏的信息,xl

6、anchen2006.5.18,13,Embedded Operating Systems,gcc的工作工程(1)如果使用-v选项,则可以看到许多被隐藏,xlanchen2006.5.18,14,Embedded Operating Systems,xlanchen2006.5.1814Embedded O,gcc的编译过程,一般情况下,c程序的编译过程为预处理编译成汇编代码汇编成目标代码链接,xlanchen2006.5.18,15,Embedded Operating Systems,gcc的编译过程一般情况下,c程序的编译过程为xlanche,gcc的工作过程(2),预处理使用-E参数输

7、出文件的后缀为“.cpp”gcc E o gcctest.cpp gcctest.c使用wc命令比较预处理后的文件与源文件,可以看到两个文件的差异,xlanchen2006.5.18,16,Embedded Operating Systems,gcc的工作过程(2)预处理使用-E参数输出文件的后缀为,行数 单词数 字节数,预编译,xlanchen2006.5.18,17,Embedded Operating Systems,行数 单词数 字节数预编译xlanchen2006.5.1,预处理文件汇编代码1)使用-x参数说明根据指定的步骤进行工作,cpp-output指明从预处理得到的文件开始编译

8、2)使用-S说明生成汇编代码后停止工作gcc x cpp-output S o gcctest.s gcctest.cpp也可以直接编译到汇编代码gcc S gcctest.c,gcc的工作过程(3),xlanchen2006.5.18,18,Embedded Operating Systems,预处理文件汇编代码1)使用-x参数说明根据指定的步骤进行,预处理文件汇编代码,直接编译到汇编代码,xlanchen2006.5.18,19,Embedded Operating Systems,预处理文件汇编代码直接编译到汇编代码xlanchen20,gcc的工作过程(4),汇编代码目标代码gcc x

9、 assembler c gcctest.s直接编译成目标代码gcc c gcctest.c使用汇编器生成目标代码as o gcctest.o gcctest.s,xlanchen2006.5.18,20,Embedded Operating Systems,gcc的工作过程(4)汇编代码目标代码xlanchen2,汇编代码目标代码,直接编译成目标代码,使用汇编器,xlanchen2006.5.18,21,Embedded Operating Systems,汇编代码目标代码直接编译成目标代码使用汇编器xlanche,gcc的工作过程(5),目标代码执行代码gcc o gcctest gcct

10、est.o直接生成执行代码gcc o gcctest gcctest.c,xlanchen2006.5.18,22,Embedded Operating Systems,gcc的工作过程(5)目标代码执行代码xlanchen2,目标代码执行代码,直接生成执行代码,xlanchen2006.5.18,23,Embedded Operating Systems,目标代码执行代码直接生成执行代码xlanchen2006,gcc的高级选项,-Wall:打开所有的警告信息,xlanchen2006.5.18,24,Embedded Operating Systems,gcc的高级选项-Wall:打开所有

11、的警告信息xlanche,根据警告信息检查源程序,Main函数的返回值为int,在函数的末尾应当返回一个值,xlanchen2006.5.18,25,Embedded Operating Systems,根据警告信息检查源程序Main函数的返回值为int在函数的末,修改源程序,xlanchen2006.5.18,26,Embedded Operating Systems,修改源程序xlanchen2006.5.1826Embed,优化编译,优化编译选项有:-O0缺省情况,不优化-O1-O2-O3等等,不同程度的优化,xlanchen2006.5.18,27,Embedded Operating

12、 Systems,优化编译优化编译选项有:不同程度的优化xlanchen20,gcc的优化编译举例(1)考虑如下的源代码,不同的优化编译选项,xlanchen2006.5.18,28,Embedded Operating Systems,gcc的优化编译举例(1)考虑如下的源代码不同的优化xla,gcc的优化编译举例(2)使用time命令统计程序的运行,xlanchen2006.5.18,29,Embedded Operating Systems,gcc的优化编译举例(2)使用time命令统计程序的运行x,GNU binutils,binutils是一组二进制工具程序集,是辅助GCC的主要软件

13、,它主要包括addr2line 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。ar 建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。,xlanchen2006.5.18,30,Embedded Operating Systems,GNU binutilsbinutils是一组二进制工具程序,as 是GNU汇编器,主要用来编译GNU C编译器gcc输出的汇编文件,他将汇编代码转换成二进制代码,并存放到一个object文件中,该目标文件将由连接器ld

14、连接C+filt解码C+符号名,连接器使用它来过滤 C+ 和 Java 符号,防止重载函数冲突。 gprof 显示程序调用段的各种数据。ld 是连接器,它把一些目标和归档文件结合在一起,重定位数据,并链接符号引用,最终形成一个可执行文件。通常,建立一个新编译程序的最后一步就是调用ld。,xlanchen2006.5.18,31,Embedded Operating Systems,as 是GNU汇编器,主要用来编译GNU C编译器gcc输出,nm 列出目标文件中的符号。objcopy把一种目标文件中的内容复制到另一种类型的目标文件中.objdump 显示一个或者更多目标文件的信息。使用选项来控

15、制其显示的信息。它所显示的信息通常只有编写编译工具的人才感兴趣。ranlib 产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。readelf 显示ebf格式可执行文件的信息。,xlanchen2006.5.18,32,Embedded Operating Systems,nm 列出目标文件中的符号。xlanchen2006.5.,size 列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个归档文件中的每个模块只产生一行输出。strings 打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字

16、符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其它类型的文件它打印整个文件的可打印字符,这个程序对于了解非文本文件的内容很有帮助。strip 丢弃目标文件中的全部或者特定符号。,xlanchen2006.5.18,33,Embedded Operating Systems,size 列出目标文件每一段的大小以及总体的大小。默认情况下,libiberty 包含许多GNU程序都会用到的函数,这些程序有: getopt, obstack, strerror, strtol 和 strtoul.libbfd 二进制文件描述库.libopcodes 用来处理opcode

17、s的库, 在生成一些应用程序的时候也会用到它, 比如objdump.Opcodes是文本格式可读的处理器操作指令.,xlanchen2006.5.18,34,Embedded Operating Systems,libiberty 包含许多GNU程序都会用到的函数,这些,binutils开发工具使用举例,arnmObjcopyObjdumpreadelf,xlanchen2006.5.18,35,Embedded Operating Systems,binutils开发工具使用举例arxlanchen200,ar,ar用于建立、修改、提取归档文件(archive),一个归档文件,是包含多个被包

18、含文件的单个文件(也可以认为归档文件是一个库文件)。被包含的原始文件的内容、权限、时间戳、所有者等属性都保存在归档文件中,并且在提取之后可以还原,xlanchen2006.5.18,36,Embedded Operating Systems,arar用于建立、修改、提取归档文件(archive),一个,使用ar建立库文件(1),源程序add.c和minus.c,xlanchen2006.5.18,37,Embedded Operating Systems,使用ar建立库文件(1)源程序add.c和minus.cxl,使用ar建立库文件(2),编译成目标文件,建立库文件,将库文件拷贝到/usr/

19、lib目录下,Ar的rv参数的说明:r:将多个文件组成一个文件v:输出信息,xlanchen2006.5.18,38,Embedded Operating Systems,使用ar建立库文件(2)编译成目标文件建立库文件将库文件拷贝,库文件使用举例在代码中使用Add和Minus函数,xlanchen2006.5.18,39,Embedded Operating Systems,库文件使用举例在代码中使用Add和Minus函数xlanc,在编译时指定库文件,指明将libtest.a链接进来,运行结果,xlanchen2006.5.18,40,Embedded Operating Systems,

20、在编译时指定库文件指明将libtest.a链接进来运行结果x,nm,nm的主要功能是列出目标文件中的符号,这样程序员就可以定位和分析执行程序和目标文件中的符号信息和它的属性,xlanchen2006.5.18,41,Embedded Operating Systems,nmnm的主要功能是列出目标文件中的符号,这样程序员就可以定,nm显示的符号类型,A:符号的值是绝对值,并且不会被将来的链接所改变B:符号位于未初始化数据部分(BSS段)C:符号是公共的。公共符号是未初始化的数据。在链接时,多个公共符号可能以相同的名字出现。如果符号在其他地方被定义,则该文件中的这个符号会被当作引用来处理D:符号

21、位于已初始化的数据部分T:符号位于代码部分U:符号未被定义?:符号类型未知,或者目标文件格式特殊,xlanchen2006.5.18,42,Embedded Operating Systems,nm显示的符号类型A:符号的值是绝对值,并且不会被将来的链接,nm使用举例,如果对test可执行文件使用nm,会有什么结果呢?,xlanchen2006.5.18,43,Embedded Operating Systems,nm使用举例如果对test可执行文件使用nm,xlanche,objcopy,可以将一种格式的目标文件内容进行转换,并输出为另一种格式的目标文件。它使用GNU BFD(binary

22、format description)库读/写目标文件,通过这个BFD库,objcopy能以一种不同于源目标文件的格式生成新的目标文件$objcopy -h在makefile里面用-O binary 选项来生成原始的二进制文件,即通常说的image文件,xlanchen2006.5.18,44,Embedded Operating Systems,objcopy可以将一种格式的目标文件内容进行转换,并输出为,Objcopy使用举例,使用file命令查看文件类型,生成srec格式的目标文件,使用file命令查看新文件的类型,xlanchen2006.5.18,45,Embedded Operat

23、ing Systems,Objcopy使用举例使用file命令查看文件类型生成sre,文件格式,a.outassembler and link editor output 汇编器和链接编辑器的输出 coffcommon object file format一种通用的对象文件格式 ELFexcutive linked fileLinux系统所采用的一种通用文件格式,支持动态连接。ELF格式可以比COFF格式包含更多的调试信息,xlanchen2006.5.18,46,Embedded Operating Systems,文件格式a.outassembler and link e,文件格式,Fla

24、telf格式有很大的文件头,flat文件对文件头和一些段信息做了简化uClinux系统使用flat可执行文件格式SRECMOTOROLA S-Recoder格式(S记录格式文件) 等等,xlanchen2006.5.18,47,Embedded Operating Systems,文件格式Flatelf格式有很大的文件头,flat文件对文,objdump,显示一个或多个目标文件的信息,由其选项来控制显示哪些信息。一般来说,objdump只对那些要编写编译工具的程序员有帮助,但是我们通过这个工具可以方便的查看执行文件或者库文件的信息,xlanchen2006.5.18,48,Embedded O

25、perating Systems,objdump显示一个或多个目标文件的信息,由其选项来控制显,Objdump使用举例(1),-f选项:显示文件头中的内容,xlanchen2006.5.18,49,Embedded Operating Systems,Objdump使用举例(1)-f选项:显示文件头中的内容xl,Objdump使用举例(2),-d选项进行反汇编,xlanchen2006.5.18,50,Embedded Operating Systems,Objdump使用举例(2)-d选项进行反汇编xlanche,readelf,readelf软件显示一个或多个ELF格式的目标文件信息。,x

26、lanchen2006.5.18,51,Embedded Operating Systems,readelfreadelf软件显示一个或多个ELF格式的目,Readelf使用举例,xlanchen2006.5.18,52,Embedded Operating Systems,Readelf使用举例xlanchen2006.5.185,其他GNU工具,Gdb调试器GNU make软件工程工具diff,patch补丁工具CVS版本控制系统,xlanchen2006.5.18,53,Embedded Operating Systems,其他GNU工具Gdb调试器xlanchen2006.5.,GNU

27、 Toolchaingdb,Gdb = GNU debugerGNU tools中的调试器,功能强大设置断点监视、修改变量单步执行显示/修改寄存器的值堆栈查看远程调试,xlanchen2006.5.18,54,Embedded Operating Systems,GNU Toolchaingdb Gdb = GNU de,gdb使用举例(1),源代码如下,编译:gcc o bug bug.c,xlanchen2006.5.18,55,Embedded Operating Systems,gdb使用举例(1)源代码如下编译:xlanchen200,gdb使用举例(2)编译并运行,?,编译,xla

28、nchen2006.5.18,56,Embedded Operating Systems,gdb使用举例(2)编译并运行?编译xlanchen,gdb使用举例(3)使用gdb调试bug,运行bug,输入字符串,出错位置,能不能看到源代码呢?,xlanchen2006.5.18,57,Embedded Operating Systems,gdb使用举例(3)使用gdb调试bug运行bug输入字符,使用gcc的-g参数,gcc g o bug bug.c重新调试,源代码,xlanchen2006.5.18,58,Embedded Operating Systems,使用gcc的-g参数gcc g

29、o bug bug.c源,xlanchen2006.5.18,59,Embedded Operating Systems,xlanchen2006.5.1859Embedded O,使用GNU make管理项目,GNU make是一种代码维护工具,在使用GNU编译器开发大型应用时,往往要使用make管理项目。如果不使用make管理项目,就必须重复使用多个复杂的命令行维护项目和生成目标代码。Make通过将命令行保存到makefile中简化了编译工作。Make的主要任务是根据makefile中定义的规则和步骤,根据各个模块的更新情况,自动完成整个软件项目的维护和代码生成工作。,xlanchen20

30、06.5.18,60,Embedded Operating Systems,使用GNU make管理项目GNU make是一种代码维护工,Make可以识别出makefile中哪些文件已经被修改,并且在再次编译的时候只编译这些文件,从而提高编译的效率Make会检查文件的修改和生成时间戳,如果目标文件的修改或者生成时间戳比它的任意一个依赖文件旧,则make就执行makefile文件中描述的相应命令,以便更新目的文件只更新那些需要更新的文件,而不重新处理那些并不过时的文件,xlanchen2006.5.18,61,Embedded Operating Systems,Make可以识别出makefil

31、e中哪些文件已经被修改,并且,特点:适合于支持多文件构成的大中型软件项目的编译,链接,清除中间文件等管理工作提供和识别多种默认规则,方便对大型软件项目的管理支持对多目录的软件项目进行递归管理对软件项目具有很好的可维护性和扩展性,xlanchen2006.5.18,62,Embedded Operating Systems,特点:xlanchen2006.5.1862Embedde,makefile,Makefile告诉make该做什么、怎么做makefile主要定义了1)依赖关系即有关哪些文件的最新版本是依赖于哪些别的文件产生或者组成的2)需要用什么命令来产生目标文件的最新版本3)以及一些其他

32、的功能,xlanchen2006.5.18,63,Embedded Operating Systems,makefileMakefile告诉make该做什么、怎么做,Makefile的规则,规则一条规则包含3个方面的内容,1)要创建的目标(文件),2)创建目标(文件)所依赖的文件列表;3)通过依赖文件创建目标文件的命令组,xlanchen2006.5.18,64,Embedded Operating Systems,Makefile的规则规则一条规则包含3个方面的内容,xl,规则一般形式target . : prerequisites . command . . 例如test:test.c;g

33、cc O o test test.c,xlanchen2006.5.18,65,Embedded Operating Systems,规则一般形式xlanchen2006.5.1865Embe,一个简单的makefile,edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.omain.o : main.c defs.hcc -c main.ckbd.o

34、 : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils

35、.o : utils.c defs.hcc -c utils.cclean : rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o,xlanchen2006.5.18,66,Embedded Operating Systems,一个简单的makefileedit : main.o kbd,Make的工作过程,default goal在缺省的情况下,make从makefile中的第一个目标开始执行Make的工作过程类似一次深度优先遍历过程,xlanchen2006.5.18,67,Embedded

36、Operating Systems,Make的工作过程default goal在缺省的情况下,,Makefile 中的变量,使用变量可以降低错误风险简化makefileobjects变量($(objects))objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects),xlanchen2006.5.18,68,Embedded Operating Systems,Makefile 中的变量使用变量可以xlanchen20,有点

37、像环境变量环境变量在make 过程中被解释成make的变量可以被用来贮存一个文件名列表。贮存可执行文件名。如用变量代替编译器名。贮存编译器FLAG,xlanchen2006.5.18,69,Embedded Operating Systems,有点像环境变量xlanchen2006.5.1869Emb,预定义变量,Make使用了许多预定义的变量,如ARASCCCXXCFLAGSCPPFLAGS等等,xlanchen2006.5.18,70,Embedded Operating Systems,预定义变量Make使用了许多预定义的变量,如xlanchen,简化后的makefile文件,objec

38、ts = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects) cc -o edit $(objects)main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h ut

39、ils.o : defs.h .PHONY : clean clean : rm edit $(objects),xlanchen2006.5.18,71,Embedded Operating Systems,简化后的makefile文件objects = main.o,内部变量,$扩展成当前规则的目的文件名$扩展成依靠列表中的第一个依靠文件$扩展成整个依靠的列表(除掉了里面所有重复的文件名) 等等不需要括号括住例如:CC = gccCFLAGS = -Wall -O -g foo.o : foo.c foo.h bar.h$(CC) $(CFLAGS) -c $ -o $,xlanchen2

40、006.5.18,72,Embedded Operating Systems,内部变量$扩展成当前规则的目的文件名xlanchen20,隐含规则 (Implicit Rules),内置的规则告诉make当没有给出某些命令的时候,应该怎么办。用户可以使用预定义的变量改变隐含规则的工作方式,如一个编译的具体命令将会是:$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $ -o $,xlanchen2006.5.18,73,Embedded Operating Systems,隐含规则 (Implicit Rules)内置的规则xlan,设定目标(Phony

41、 Targets),设定目标目标不是一个文件其目的是为了让一些命令得以执行使用PHONY显式声明设定目标.PHONY: clean使用设定目标实现多个目的all: prog1 prog2,xlanchen2006.5.18,74,Embedded Operating Systems,设定目标(Phony Targets)设定目标xlanche,典型的设定目标,设定目的也可以用来描述一些其他的动作。例如,想把中间文件和可执行文件删除,可以在 makefile 里设立这样一个规则:clean:$rm *.o exec_file前提是没有其它的规则依靠这个 clean 目的,它将永远 不会被执行。但

42、是,如果你明确的使用命令 make clean , make 会把这个目的做为它的主要目标,执行那些 rm 命令,xlanchen2006.5.18,75,Embedded Operating Systems,典型的设定目标设定目的也可以用来描述一些其他的动作。例如,想,Makefile中的函数 (Functions),用来计算出要操作的文件、目标或者要执行的命令使用方法:$(function arguments)典型的函数$(subst from,to,text) $(subst ee,EE,feet on the street) 相当于fEEt on the strEEt,xlanchen

43、2006.5.18,76,Embedded Operating Systems,Makefile中的函数 (Functions)用来计算出要,$(patsubst pattern,replacement,text)$(patsubst %.c,%.o,x.c.c bar.c) 相当于x.c.o bar.o$(wildcard pattern) $(wildcard *.c)objects := $(wildcard *.o),xlanchen2006.5.18,77,Embedded Operating Systems,$(patsubst pattern,replacement,makefi

44、le中的条件语句,conditional-directivetext-if-trueendiforconditional-directivetext-if-trueelsetext-if-trueendif,xlanchen2006.5.18,78,Embedded Operating Systems,makefile中的条件语句conditional-dire,四种条件语句,ifeq.else.endififneqelseendififndefelseendif ifndef.elseendif,xlanchen2006.5.18,79,Embedded Operating Systems,四种条件语句ifeq.else.endifxlanc,实际项目中的makefile,xlanchen2006.5.18,80,Embedded Operating Systems,实际项目中的makefilexlanchen2006.5.,

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

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


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号