《linux内核》PPT课件.ppt

上传人:赵** 文档编号:68492119 上传时间:2022-12-28 格式:PPT 页数:28 大小:338.50KB
返回 下载 相关 举报
《linux内核》PPT课件.ppt_第1页
第1页 / 共28页
《linux内核》PPT课件.ppt_第2页
第2页 / 共28页
点击查看更多>>
资源描述

《《linux内核》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《linux内核》PPT课件.ppt(28页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第第1515章章 解析解析LinuxLinux内核内核内核是操作系统的核心,通常说的内核是操作系统的核心,通常说的Linux是指是指Linux操操作系统的内核,是一组系统管理软件的集合。作系统的内核,是一组系统管理软件的集合。Linux内核是内核是目前最流行的开源操作系统之一,由于其代码的高度开放性,目前最流行的开源操作系统之一,由于其代码的高度开放性,越来越多的人参与到越来越多的人参与到Linux内核的研究和开发中。内核的研究和开发中。Linux内内核的功能也在不断提高,性能在不断改进。操作系统内核是核的功能也在不断提高,性能在不断改进。操作系统内核是软件开发领域比较深的技术点,需要结合软硬

2、件知识才能深软件开发领域比较深的技术点,需要结合软硬件知识才能深入理解。本章由浅入深讲解入理解。本章由浅入深讲解Linux内核,带领读者进入嵌入内核,带领读者进入嵌入式开发比较深入的领域,主要内容如下:式开发比较深入的领域,主要内容如下:如何获取如何获取Linux内核代码内核代码Linux内核功能解析内核功能解析Linux内核代码布局内核代码布局Linux内核镜像结构内核镜像结构15.1 15.1 基本知识基本知识Linux内核是内核是Linux操作系统不可缺少的组成部分,但操作系统不可缺少的组成部分,但是内核本身不是操作系统。许多是内核本身不是操作系统。许多Linux操作系统发行商如操作系统

3、发行商如RedHat、Debian等都采用等都采用Linux内核,然后加入用户需要内核,然后加入用户需要的工具软件和程序库,最终构成一个完整的操作系统。嵌入的工具软件和程序库,最终构成一个完整的操作系统。嵌入式式Linux系统是运行在嵌入式硬件系统上的系统是运行在嵌入式硬件系统上的Linux操作系统,操作系统,每个嵌入式每个嵌入式Linux系统都包括了必要的工具软件和程序库。系统都包括了必要的工具软件和程序库。15.1.1 15.1.1 什么是什么是LinuxLinux内核内核内核是操作系统的核心部分,为应用程序提供安全访问内核是操作系统的核心部分,为应用程序提供安全访问硬件资源的功能。直接操

4、作计算机硬件是很复杂的,内核通过硬件资源的功能。直接操作计算机硬件是很复杂的,内核通过硬件抽象的方法屏蔽了硬件的复杂性和多样性。通过硬件抽象硬件抽象的方法屏蔽了硬件的复杂性和多样性。通过硬件抽象的方法,内核向应用程序提供了统一和简洁的接口,应用程序的方法,内核向应用程序提供了统一和简洁的接口,应用程序设计复杂程度降低。实际上,内核可以被看做是一个系统资源设计复杂程度降低。实际上,内核可以被看做是一个系统资源管理器,内核管理计算机系统中所有的软件和硬件资源。管理器,内核管理计算机系统中所有的软件和硬件资源。应用程序可以直接运行在计算机硬件上而无需内核的支应用程序可以直接运行在计算机硬件上而无需内

5、核的支持,从这个角度看,内核不是必要的。在早期的计算机系统中,持,从这个角度看,内核不是必要的。在早期的计算机系统中,由于系统资源的局限,通常采用直接在硬件上运行应用程序的由于系统资源的局限,通常采用直接在硬件上运行应用程序的办法。运行应用程序需要一些辅助程序,如程序加载器、调试办法。运行应用程序需要一些辅助程序,如程序加载器、调试器等。随着计算机性能的不断提高,硬件和软件源都变得复杂,器等。随着计算机性能的不断提高,硬件和软件源都变得复杂,需要一个统一管理的程序,操作系统的概念也逐渐建立起来。需要一个统一管理的程序,操作系统的概念也逐渐建立起来。15.1.2 Linux15.1.2 Linu

6、x内核版本内核版本Linux内核版本号采用两个内核版本号采用两个“.”分割的三个数字来标分割的三个数字来标示,形式为示,形式为“X.Y.Z”。其中,。其中,X是主要版本号,是主要版本号,Y是次要版是次要版本号,本号,Z代表补丁版本号。奇数代表不稳定的版本;偶数代代表补丁版本号。奇数代表不稳定的版本;偶数代表稳定的版本。表稳定的版本。“稳定稳定”和和“不稳定不稳定”是相对的,如是相对的,如Linux内核内核1.1.0相对于相对于1.0.0来说是来说是“不稳定不稳定”版本,但是与版本,但是与1.1.1对比是对比是“稳定稳定”版本。在版本。在Linux内核开发过程中,内核开发过程中,“不稳定不稳定”

7、版本通常是在原有版本基础上增加了新的功能或者新的特版本通常是在原有版本基础上增加了新的功能或者新的特性。性。15.1.3 15.1.3 如何获取如何获取LinuxLinux内核代码内核代码在在PC上,一般的上,一般的Linux发行版都提供了内核代码。嵌发行版都提供了内核代码。嵌入式系统没有固定的发行版,需要用户自己获取内核代码。入式系统没有固定的发行版,需要用户自己获取内核代码。Linux内核代码的官方站点是内核代码的官方站点是http:/www.kernel.org,该站,该站点提供了点提供了2.4和和2.6所有版本的代码和补丁,用户可以打开该所有版本的代码和补丁,用户可以打开该地址找到和自

8、己所在物理位置就进的站点,下载自己需要的地址找到和自己所在物理位置就进的站点,下载自己需要的内核版本代码。高版本内核版本代码。高版本Linux内核代码文件比较大,对于国内核代码文件比较大,对于国内的用户推荐使用内的用户推荐使用ftp方式下载,或者使用断点续传工具下方式下载,或者使用断点续传工具下载,具体情况可根据读者自身的网络情况选择。载,具体情况可根据读者自身的网络情况选择。下载下载Linux内核代码后,会得到一个类似内核代码后,会得到一个类似“linux-2.6.xx.tar.gz”或者或者“linux-2.6.xx-tar.bz2”形式的压缩文件,形式的压缩文件,“xx”代表版本号。在代

9、表版本号。在Linux系统上,通常把这个文件存放系统上,通常把这个文件存放在在/usr/src目录下,便于以后使用。目录下,便于以后使用。15.1.4 15.1.4 编译内核编译内核学习学习Linux内核最好的开始是编译一次内核最好的开始是编译一次Linux内核代码,内核代码,通过配置通过配置Linux内核可以对内核代码有一个初步的了解。本内核可以对内核代码有一个初步的了解。本节介绍一下在节介绍一下在PC机上如何编译生成机上如何编译生成2.6版本的内核目标文件,版本的内核目标文件,在本书第在本书第20章移植章移植Linux部分会讲解如何交叉编译用于部分会讲解如何交叉编译用于ARM体系结构的体系

10、结构的Linux内核。内核。与与2.4版本相比,版本相比,2.6版本内核代码编译相对较容易。内版本内核代码编译相对较容易。内核编译主要分成配置和编译两部分,其中配置是关键,许多核编译主要分成配置和编译两部分,其中配置是关键,许多问题都是出在配置环节。问题都是出在配置环节。Linux内核编译配置提供多种方式:内核编译配置提供多种方式:make config:make menuconfig:make xconfig:make oldconfig:15.2 Linux15.2 Linux内核的子系统内核的子系统内核是操作系统的核心。内核是操作系统的核心。Linux内核提供很多基本功能,内核提供很多基

11、本功能,如虚拟内存、多任务、共享库、需求加载、共享写时拷贝如虚拟内存、多任务、共享库、需求加载、共享写时拷贝(Copy-On-Write)以及网络功能等。增加各种不同功能导)以及网络功能等。增加各种不同功能导致内核代码不断增加。致内核代码不断增加。Linux内核把不同功能分成不同的子内核把不同功能分成不同的子系统的方法,通过一种整体的结构把各种功能集合在一起,系统的方法,通过一种整体的结构把各种功能集合在一起,提高了工作效率。同时还提供动态加载模块的方式,为动态提高了工作效率。同时还提供动态加载模块的方式,为动态修改内核功能提供了灵活性。修改内核功能提供了灵活性。15.2.1 15.2.1 系

12、统调用接口系统调用接口15.2.1 15.2.1 系统调用接口系统调用接口系统调用是系统调用是Linux内核提供的,用户空间无法直接使用系内核提供的,用户空间无法直接使用系统调用。在用户进程使用系统调用必须跨越应用程序和内核的统调用。在用户进程使用系统调用必须跨越应用程序和内核的界限。界限。Linux内核向用户提供了统一的系统调用接口,但是在内核向用户提供了统一的系统调用接口,但是在不同处理器上系统调用的方法各不相同。不同处理器上系统调用的方法各不相同。Linux内核提供了大内核提供了大量的系统调用,本书从系统调用的基本原理出发讲解量的系统调用,本书从系统调用的基本原理出发讲解Linux系系统

13、调用的方法。统调用的方法。15.2.2 15.2.2 进程管理子系统进程管理子系统当一个用户进程被加载后,会进入就绪态,被加入到就当一个用户进程被加载后,会进入就绪态,被加入到就绪态队列,绪态队列,CPU时间被轮转到就绪态队列后,切换到进程的时间被轮转到就绪态队列后,切换到进程的代码,进程被执行,当进程的时间片到了以后被换出。如果代码,进程被执行,当进程的时间片到了以后被换出。如果进程发生进程发生I/O操作也会提前被换出,并且存放到等待队列,操作也会提前被换出,并且存放到等待队列,当当I/O请求返回后,进程又被放入就绪队列。请求返回后,进程又被放入就绪队列。Linux系统对进程队列的管理设计了

14、若干不同的方法,系统对进程队列的管理设计了若干不同的方法,主要的目的是提高进程调度的稳定性。主要的目的是提高进程调度的稳定性。15.2.3 15.2.3 内存管理子系统内存管理子系统内存是计算机的重要资源,也是内核的的重要部分。使内存是计算机的重要资源,也是内核的的重要部分。使用虚拟内存技术的计算机,内存管理的硬件按照分页方式管用虚拟内存技术的计算机,内存管理的硬件按照分页方式管理内存。分页方式是把计算机系统的物理内存按照相同大小理内存。分页方式是把计算机系统的物理内存按照相同大小等分,每个内存分片称作内存页,通常内存页大小是等分,每个内存分片称作内存页,通常内存页大小是4KB。Linux内核

15、的内存管理子系统管理虚拟内存与物理内存之间内核的内存管理子系统管理虚拟内存与物理内存之间的映射关系,以及系统可用内存空间。的映射关系,以及系统可用内存空间。内存管理要管理的不仅是内存管理要管理的不仅是4KB缓冲区。缓冲区。Linux提供了对提供了对4KB缓冲区的抽象,例如缓冲区的抽象,例如slab分配器。这种内存管理模式使分配器。这种内存管理模式使用用4KB缓冲区为基数,然后从中分配结构,并跟踪内存页使缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。这样就允许该模式根据系统需要来

16、动态调整哪些页面为空。这样就允许该模式根据系统需要来动态调整内存使用。内存使用。15.2.4 15.2.4 虚拟文件系统虚拟文件系统虚拟文件系统,即虚拟文件系统,即VFS(Virtual File System)是)是Linux内核中的一个软件抽象层。它通过一些数据结构及其内核中的一个软件抽象层。它通过一些数据结构及其方法向实际的文件系统如方法向实际的文件系统如ext2,vfat等提供接口机制。通过等提供接口机制。通过使用同一套文件使用同一套文件 I/O 系统调用即可对系统调用即可对Linux中的任意文件进中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,行操作而无需考虑其所在

17、的具体文件系统格式;更进一步,文件操作可以在不同文件系统之间进行。文件操作可以在不同文件系统之间进行。15.2.4 15.2.4 虚拟文件系统虚拟文件系统15.2.5 15.2.5 网络堆栈网络堆栈第九章介绍了第九章介绍了Linux系统下如何编写网络应用程序,使系统下如何编写网络应用程序,使用用socket通过通过TCP/IP协议与其他机器通信,和前面介绍的协议与其他机器通信,和前面介绍的内核子系统相似,内核子系统相似,socket相关的函数也是通过内核的子系统相关的函数也是通过内核的子系统完成的,担当这部分任务的是内核的网络子系统,一些资料完成的,担当这部分任务的是内核的网络子系统,一些资料

18、里也把这部分代码称为里也把这部分代码称为“网络堆栈网络堆栈”。Linux内核提供了优秀的网络处理能力和功能,这与网内核提供了优秀的网络处理能力和功能,这与网络堆栈代码的设计思想是分不开的,络堆栈代码的设计思想是分不开的,Linux的网络堆栈部分的网络堆栈部分沿袭了传统的层次结构,网络数据从用户进程到达实际的网沿袭了传统的层次结构,网络数据从用户进程到达实际的网络设备需要四个层次。络设备需要四个层次。15.2.5 15.2.5 网络堆栈网络堆栈15.2.6 15.2.6 设备驱动设备驱动Linux内核对设备按照主设备号和从设备号的方法访问,内核对设备按照主设备号和从设备号的方法访问,主设备号描述

19、控制设备的驱动程序,从设备号区分同一个驱动主设备号描述控制设备的驱动程序,从设备号区分同一个驱动程序的不同设备。也就是说,主设备号和设备驱动程序对应,程序的不同设备。也就是说,主设备号和设备驱动程序对应,代表某一类型的设备,从设备号和具体设备对应,代表同一类代表某一类型的设备,从设备号和具体设备对应,代表同一类的设备编号。如使用的设备编号。如使用IDE接口的两个硬盘,主设备号都相同,接口的两个硬盘,主设备号都相同,但是从设备号不同。但是从设备号不同。Linux提供了提供了mknod命令创建设备驱动程命令创建设备驱动程序的描述文件,后面设备驱动相关章节具体讲解。序的描述文件,后面设备驱动相关章节

20、具体讲解。Linux内核内核这种主从设备号的分类方法可以很好的管理设备。这种主从设备号的分类方法可以很好的管理设备。15.2.7 15.2.7 依赖体系结构的代码依赖体系结构的代码Linux内核支持众多体系结构,内核把与设备无关的代内核支持众多体系结构,内核把与设备无关的代码放在码放在arch目录,对应的头文件放在目录,对应的头文件放在include/asm-目录下。这样的划分代码结构清晰,同时提高了代码的目录下。这样的划分代码结构清晰,同时提高了代码的复用率。在复用率。在arch目录里,每个子目录对应一种体系结构,存目录里,每个子目录对应一种体系结构,存放这种体系结构对应的代码,如果代码较多

21、会单独建立一个放这种体系结构对应的代码,如果代码较多会单独建立一个目录,例如目录,例如arch/arm目录下,有一个目录下,有一个kernel目录,存放的是目录,存放的是kernel目录中在目录中在arm体系结构上特有的函数或者实现方法;体系结构上特有的函数或者实现方法;在在arch/i386目录存放了目录存放了Intel X86体系结构的代码,不仅有体系结构的代码,不仅有kernel目录,而且还有多个目录,例如目录,而且还有多个目录,例如mm目录包含了目录包含了x86体系上内存管理的实现方法,体系上内存管理的实现方法,math-emu包含了包含了x86体系上体系上浮点数模拟的实现等。读者在阅

22、读内核代码的时候可以从一浮点数模拟的实现等。读者在阅读内核代码的时候可以从一个体系结构代码入手,对不同体系结构移植代码的主要工作个体系结构代码入手,对不同体系结构移植代码的主要工作是是arch里面的代码。里面的代码。15.3 Linux15.3 Linux内核代码的工程结构内核代码的工程结构随着随着Linux内核功能的不断增加,内核代码也在飞速增内核功能的不断增加,内核代码也在飞速增长,目前长,目前2.6版本的内核代码早已达到数百万行。如此庞大版本的内核代码早已达到数百万行。如此庞大的代码量,不仅给学习带来困难,对代码的维护也是一个不的代码量,不仅给学习带来困难,对代码的维护也是一个不小的挑战

23、,幸好小的挑战,幸好Linux内核开发人员早就考虑到了这一点,内核开发人员早就考虑到了这一点,使得使得Linux内核代码组织有序,本节重点讲述内核代码组织有序,本节重点讲述Linux内核代内核代码的结构。码的结构。15.3.1 15.3.1 源代码目录布局源代码目录布局15.1.3节讲述了如何获取到节讲述了如何获取到Linux内核代码,通常会存内核代码,通常会存放在放在/usr/src目录下,如果是目录下,如果是2.6版本的内核解压后会得到版本的内核解压后会得到例如例如linux-2.6.xx类型的目录,这个目录下存放的就是类型的目录,这个目录下存放的就是Linux内核代码。进入内核代码目录,

24、查看文件列表,会看内核代码。进入内核代码目录,查看文件列表,会看到许多的目录和文件,如果读者的系统有到许多的目录和文件,如果读者的系统有tree这个命令或者这个命令或者脚本,可以查看到脚本,可以查看到Linux内核代码的文件数,那会是一个很内核代码的文件数,那会是一个很庞大的结构。好在庞大的结构。好在Linux内核代码的工程组织是很好的,对内核代码的工程组织是很好的,对于不同版本的内核,在工程组织上是基本一致的,有的仅是于不同版本的内核,在工程组织上是基本一致的,有的仅是功能上的差别。功能上的差别。15.3.2 15.3.2 几个重要的几个重要的LinuxLinux内核文件内核文件当用户编译一

25、个当用户编译一个Linux内核代码后,会生成几个文件:内核代码后,会生成几个文件:vmlinuz,initrd.img,以及,以及System.map,如果读者配置过,如果读者配置过grub引导管理器程序,会在引导管理器程序,会在/boot目录下看到这几个文件。目录下看到这几个文件。1vmlinuz文件文件2initrd文件文件3System.map文件文件15.4 15.4 内核编译系统内核编译系统Linux内核代码的复杂,需要一个强大的工程管理系统,内核代码的复杂,需要一个强大的工程管理系统,幸好幸好GNU提供了提供了Makefile机制,此外,内核的开发者们还提机制,此外,内核的开发者们

26、还提供了供了KBuild机制。通过机制。通过Makefile和和KBuild的结合,可以出的结合,可以出色的管理色的管理Linux内核代码。内核代码。Linux内核的编译系统和代码结内核的编译系统和代码结构是紧密联系的,了解内核编译系统对分析内核代码和编译构是紧密联系的,了解内核编译系统对分析内核代码和编译内核都有帮助作用。内核都有帮助作用。15.4.1 15.4.1 内核编译系统基本架构内核编译系统基本架构Linux内核编译系统有内核编译系统有5种类型的文件。种类型的文件。文件类型文件类型作用作用Makefile顶层Makefile文件.config内核配置文件arch/$(ARCH)/Ma

27、kefile机器体系Makefile文件scripts/Makefile.*所有内核Makefiles共用规则kbuild Makefiles其它Makefile文件15.4.2 15.4.2 内核顶层内核顶层MakefileMakefile分析分析编译内核代码的时候,顶层编译内核代码的时候,顶层Makefile文件在开始编译子文件在开始编译子目录下的代码之前,设置编译环境和需要用到的变量。顶层目录下的代码之前,设置编译环境和需要用到的变量。顶层Makefile文件包含通用部分,文件包含通用部分,arch/$(ARCH)/Makefile包含包含该体系架构所需的设置。因此该体系架构所需的设置。

28、因此arch/$(ARCH)/Makefile会设会设置一些变量和少量的目标。置一些变量和少量的目标。1设置变量设置变量2增加预设置项增加预设置项3目录表目录表4引导映像引导映像5编译非内核目标编译非内核目标6编译引导映像命令编译引导映像命令7定制编译命令定制编译命令8预处理连接脚本预处理连接脚本15.4.3 15.4.3 内核编译文件分析内核编译文件分析Linux内核代码使用内核代码使用KBuild作为作为Makefile的基础架构。的基础架构。Kbuild定义了若干的内置变量,本节介绍定义了若干的内置变量,本节介绍Kbuild的主要内置的主要内置变量和常用方法。变量和常用方法。1目标定义目

29、标定义2内嵌对象内嵌对象-obj-y3可加载模块可加载模块-obj-m4导出符号目标导出符号目标5库文件库文件-lib-y6目录递归目录递归7编译标记编译标记8依赖关系依赖关系9特殊规则特殊规则10$(CC)支持功能支持功能15.4.4 15.4.4 目标文件清除机制目标文件清除机制make clean命令删除在编译内核生成的大部分文件如命令删除在编译内核生成的大部分文件如主机程序。列举在主机程序。列举在$(hostprogs-y)、$(hostprogs-m)、$(always)、$(extra-y)和和$(targets)中目标文件都将被删除。中目标文件都将被删除。代码目录数中的代码目录数

30、中的*.oas、*.ko文件和一些由编译系统文件和一些由编译系统产生的附加文件也将被删除。附加文件可以使用产生的附加文件也将被删除。附加文件可以使用$(clean-files)进行定义。例如:进行定义。例如:#drivers/pci/Makefileclean-files:=devlist.h classlist.h15.4.5 15.4.5 编译辅助程序编译辅助程序内核编译系统支持在编译(内核编译系统支持在编译(compliation)阶段编译主)阶段编译主机可执行程序。为了使用主机程序需要两个步骤:第一个步机可执行程序。为了使用主机程序需要两个步骤:第一个步骤使用骤使用hostprogs-

31、y变量告变量告 诉内核编译系统有主机程序可诉内核编译系统有主机程序可用。第二步给主机程序添加潜在的依赖关系。有两种方法,用。第二步给主机程序添加潜在的依赖关系。有两种方法,在规则中增加依赖关系或使用在规则中增加依赖关系或使用$(always)变量。具体描述如变量。具体描述如下。下。1简单辅助程序简单辅助程序2组合辅助程序组合辅助程序3定义共享库定义共享库4C+语言使用方法语言使用方法5辅助程序编译控制选项辅助程序编译控制选项6何时建立辅助程序何时建立辅助程序7使用使用hostprogs-$(CONFIG_FOO)15.4.6 15.4.6 KBuildKBuild变量变量KBuild内置了一些

32、变量供顶层内置了一些变量供顶层Makefile使用,顶层使用,顶层Makefile文件导出下面这些变量:文件导出下面这些变量:VERSION,PATCHLEVEL,SUBLEVEL,EXTRAVERSION这几个变量定义了当前内核版本号。很少体系体系这几个变量定义了当前内核版本号。很少体系体系Makefiles文件直接使用他们,常用文件直接使用他们,常用$(KERNELRELEASE)代替。代替。15.5 15.5 小结小结Linux内核代码非常庞大复杂,对任何人来说学习都是内核代码非常庞大复杂,对任何人来说学习都是一个不小的挑战,本章讲解了一个不小的挑战,本章讲解了Linux内核的工程结构和代码内核的工程结构和代码结构,从嵌入式系统开发的角度来说,大多数没有必要一行结构,从嵌入式系统开发的角度来说,大多数没有必要一行一行的研究内核代码,开发人员需要了解内核的机构和工作一行的研究内核代码,开发人员需要了解内核的机构和工作流程,以及常见的开发方法即可,学习内核最基本的技能是流程,以及常见的开发方法即可,学习内核最基本的技能是编译内核,在此基础上通过学习驱动开发和内核移植。第编译内核,在此基础上通过学习驱动开发和内核移植。第16章讲解嵌入式章讲解嵌入式Linux内核启动过程。内核启动过程。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁