Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830890
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: LINUX

2017-03-01 14:28:43

1.6 配置和编译 Linux 内核
    对内核进行正确配置后,才能进行编译。配置不当的内核,很有可能编译出错,或者不
    能正确运行。
    
    1.6.1 快速配置内核
        进入 Linux 内核源码数顶层目录,输入 make menuconfig 命令, 可进入
        基于 Ncurses 的 Linux 内核配置主界面( 注意:主机须安装 ncurses 相关库才能正确运行该
        命令并出现配置界面)。如果没有在 Makefile 中指定 ARCH,则须在命令行中指定:
        $ make ARCH=arm menuconfig
                
        配置完毕,将光标移动到配置界面末尾,选中“ Save an Alternate Configuration File”后
        回车,保存当前内核配置,默认配置文件名为.config
        
        保存完毕,选择退出内核配置界面,回到终端命令行。
        当然,也可以将配置文件命名为其它文件名,如 config-bak 等,但该配置不会被 Makefile
        文件使用, Makefile 默认使用文件名为.config 的配置文件,所以重新命名配置文件通常在保
        留或者备份内核配置信息时使用。
        也可以不用“ Save an Alternate Configuration File”操作,连按 ESC 或选择退出内
        核配置界面,将会出现保存配置提示信息,选择后回车,内核配置
        将会被保存为.config 文件。
        
        备份内核配置,在命令行下将.config 文件复制为其它文件名来得更简单快捷:
        $ cp .config config-bak

        装载某个配置文件,可在配置界面选中“ Load an Alternate Configuration File”,然后填
        入已存在的配置文件名称。 也可在命令行下将配置文件复制为.config:
        $ cp config-bak .config
        
        目录下有很多*_defconfig 文件, 这些都是内核的预设配置文件,
        分别对应各种不同的参考板。如果要使用其中的配置文件作为内核编译配置,可用“ make
        xxx_defconfig”命令来完成。对于已经设定好的内核配置,也可以命名为某个文件名,放到
        目录下,在以后直接用 make 来调用该配置即可。例如将当前配置命名为
        m3352_defconfig 并放到目录下,后续只需执行下列命令即可使用当前配
        置:
        $ make m3352_defconfig 或者
        $ make ARCH=arm CROSS_COMPILE= arm-linux-gnueabihf- m3352_defconfig
        
    1.6.2 内核配置详情
        Linux 内核配置菜单比较复杂,下面对一些比较重要的配置界面进行介绍,更多的详细
        配置,建议进行实际操作。另外,由于 Linux 内核版本差异,实际看到的内核配置界面可能
        与本节的介绍有所差异。

        表 1.4 内核配置界面一级菜单
                菜单项                             说明
            -----------------------------------------------------------------------------------------------
            General setup --->     内核通用配置选项,包括交叉编译器前缀、本地版本、内核
                                   压缩模式、 config.gz 支持、内核 log 缓冲区大小、 initramfs
                                   以及更多的内核运行特性支持等
                                
            [ ] Enable loadable module support    ---> 内核模块加载支持,通常都需要
            [ ] Enable the block layer            ---> 使能块设备。如果未选中使能,块设备将不能使用, SCSI
                                                       类字符设备和 USB 大容量类设备也将不能使用。
                                                    
            System Type     ---> 系统类型,设置 ARM 处理器型号、处理器的特性以及默认的评估板主板。
            Bus support     ---> PCMCIA/CardBUS 总线支持,目前已经很少使用
            Kernel Features ---> 内核特性,包括内核空间分配、实时性配置等特性配置
            Boot options     ---> 内核启动选项,如果采用内置启动参数,则在这里设置
           
            CPU Power Management         ---> CPU 电源管理,包括处理器频率降频、休眠模式支持等

            Floating point emulation     ---> 浮点模拟
            Userspace binary formats     ---> 用户空间二进制支持
            Power management options     ---> 电源管理选项
            [ ] Networking support       ---> 网络协议支持,包括网络选项、 CAN-Bus、红外、无线、 NFC
                                             等。其中的网络选项还有更多配置项,如 IPv4、 IPv6 等
                                            
            Device Drivers     ---> 设备驱动,包含多级下级菜单,包括驱动通用选项、 MTD
                                    设备、字符设备、网络设备、输入设备、 I2C 总线、 SPI 总
                                    线、 USB 总线、 GPIO、声卡、显卡等各种外设配置菜单
                                    
            File systems     ---> 文件系统, 包含 Ext2、 Ext3、 Ext4、 JFFS、 NFS、 DOS 等各
                                  种文件系统, 以及本地语言支持等
                                
            Kernel hacking     ---> 内核 Hacking,在内核调试阶段可酌情使能其中的选项,以
                                    获得需要的调试信息
            Security options         ---> 安全选项
            < > Cryptographic API    ---> 加密接口,内核提供的一些加密算法如 CRC32、MD5、SHA1、SHA224 等
            OCF Configuration        ---> 开放的加密框架
            Library routines         ---> 库例程
            Load an Alternate Configuration File 装载一个配置文件
            Save an Alternate Configuration File 保存为一个配置文件
            
            一级菜单下的每一项几乎都有复杂的下级子菜单,各自的配置选项也很丰富,每项的意
            义也各不相同,如果逐一进行描述,将会是一件非常繁琐的事。而实际产品开发中,并不需
            要完全了解内核的每一个配置项,通常只需要了解其中一些相关项即可。

    1.6.3 编译内核
        内核配置完成,输入 make 命令即可开始编译内核。如果没有修改 Makefile 文件并指定
        ARCH 和 CROSS_COMPILE 参数,则须在命令行中指定:
        $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
        
        目前大多数主机都是多核处理器,为了加快编译进度,可以开启多线程编译在 make
        的时候加上“ -jN”即可, N 的值为处理器核心数目的 2 倍。例如对于 I7 4核处理器,可将
        N 设置为 8:
        $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8
        
        采用多线程编译的优点是能加快编译进度,缺点是如果内核中有错误,某个编译线程遇
        到错误终止了编译,而其它编译线程却还在继续,出错线程的错误提示通常会被其它编译线
        程的输出信息淹没,不利于排查。对于这种情况,则建议改为单线程编译,直到错误排除。
        如果编译不出错,编译完成,会生成 vmlinux、 Image、 zImage 等文件,各文件说明如
        表 1.10 所列。
        
        表 1.10 内核编译生成文件说明
            文件            说明
            -----------------------------------------------------------------------------------------

            vmlinux     
                未经压缩、带调试信息和符号表的内核文件,elf 格式,在顶层目录下
            
            arch/arm/boot/compressed/vmlinux     
                经过压缩的 Image(这个Image就是上面的在顶层目录下生成的vmlinux,只是名字一样容易混淆)
                并加入了解压头的 elf 格式文件
            
            arch/arm/boot/Image
                将 vmlinux 去除调试信息、注释和符号表等,只包含内核代码和数据后得到的非 elf 格式文件   
             

            arch/arm/boot/zImage
                经过 objcopy 处理,能直接下载到内存中执行的内核映像文件
        
        1. zImage
            zImage 是通常情况下默认的压缩内核,可以直接加载到内存地址并开始执行。它从
            文件经过 objcopy 处理得到。在 ARM Linux 下最终生成
            zImage 的各个参数记录在文件中。
            
            中的信息如下:也就是利用命令arm-linux-objcopy,将内核镜像的格式进行转换。
                cmd_arch/arm/boot/zImage := arm-linux-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S  
                arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage

            
        2. uImage
            对于 ARM Linux 系统,大多数采用 U-Boot 引导,很少直接使用 zImage 映像,实际上
            更多的是 uImage。 uImage 是 U-Boot 默认采用的内核映像文件,它是在 zImage 内核映像之
            前加上了一个长度为 64 字节信息头的映像。这 64 字节信息头包括映像文件的类型、加载位
            置、生成时间、大小等信息( 可参考 U-Boot 源码文件的 image_header_t 数
            据结构定义)。进入目录,用 ls 命令查看, uImage 文件大小比 zImage 大 64
            字节:
            $ cd arch/arm/boot
            $ ls -la Image zImage uImage
                r-xr-x 1 root root 4222656 2017-01-10 16:42 Image
                -rw-r--r-- 1 root root 2070660 2017-01-11 09:11 uImage
                -rwxr-xr-x 1 root root 2070596 2017-01-11 09:11 zImage
            在 U-Boot 下,通过 bootm 命令可以引导 uImage 映像文件启动。
            
        3. mkimage 工具
            从 zImage 生成 uImage 需要用到 mkimage 工具。该工具可在编译 U-Boot 源码后从 tools
            目录下获得,复制到系统/usr/bin 目录即可;对于 Ubuntu 系统,还可用 sudo apt-get install
            u-boot-tools 命令安装得到。进入 mkimage 文件所在目录执行该文件,或者在安装 mkimage
            工具后,直接在终端输入 mkimage 命令,可以得到 mkimage 工具的用法:
            $ ./mkimage 或者 mkimage
            Usage: ./mkimage -l image
                -l ==> list image header information
                ./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
                -A ==> set architecture to 'arch'
                -O ==> set operating system to 'os'
                -T ==> set image type to 'type'
                -C ==> set compression type 'comp'
                -a ==> set load address to 'addr' (hex)
                -e ==> set entry point to 'ep' (hex)
                -n ==> set image name to 'name'
                -d ==> use image data from 'datafile'
                -x ==> set XIP (execute in place)
                ./mkimage [-D dtc_options] -f fit-image.its fit-image
                ./mkimage -V ==> print version information and exit
                
        使用 mkimage 工具根据 zImage 制作 uImage 映像文件的命令如下:
        $ mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
        
        对于 EPC-28x 处理器,内存起始地址为 0x40000000 (0x40008000),从 zImage 生成 uImage 映像文件
        的命令实际操作范例:
       
$ mkimage -A arm -O linux -T kernel -C none -a 0x40008000 -e 0x40008000 -n 'Linux-2.6.35' -d arch/arm/boot/zImage arch/arm/boot/uIma
        【注意:上面的命令在一行输入完成】

        说明:内存地址与处理器相关,在不同处理器上可能有差异。
        mkimage 除了可以制作 uImage 映像文件之外, 还可以查看一个 uImage 映像文件的文件
        头信息, 用法:
        $ mkimage -l uImage_file
        
        例如,用 mkimage 工具查看 EPC-28x 工控主板的 uImage 内核映像,可以得到如下信息:
        $ mkimage -l uImage
            Image Name: Linux-2.6.35.3-571-gcca29a0-g191
            Created: Tue Nov 17 11:57:47 2015
            Image Type: ARM Linux Kernel Image (uncompressed)
            Data Size: 2572336 Bytes = 2512.05 kB = 2.45 MB
            Load Address: 40008000
            Entry Point: 40008000
            
        如果只有 zImage 内核映像文件,需要转换成 uImage 映像文件,则只能通过上述命令来
        实现。但是如果有内核源码,那生成 uImage 的方法就简单很多。实际上, Linux 内核已经
        支持直接生成 uImage 格式映像文件,在文件中给出了 uImage 的生
        成规则:
            quiet_cmd_uimage = UIMAGE $@
            cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
            -C none -a $(LOADADDR) -e $(STARTADDR) \
            -n 'Linux-$(KERNELRELEASE)' -d $< $@
            
        生成 uImage 的编译命令为 make uImage:
        $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8 uImage
        
        在 ARM Linux 下最终生成 uImage 的各个参数记录在文件
        中。 对于在 EPC-28x 的 Linux 内核, 实际参数为:
            cmd_arch/arm/boot/uImage := /bin/bash /home/vmuser/prj/m28x/kernel/linux-2.6.35.3/scripts/mkuboot.sh -A arm
            -O linux -T kernel -C none -a 0x40008000 -e 0x40008000 -n 'Linux-2.6.35.3-571-gcca29a0-g1914ba0' -d
            arch/arm/boot/zImage arch/arm/boot/uImage
        说明:路径信息与实际具体编译环境有关。

4. 编译内核模块
        模块编译:
            如果内核中有配置为的模块或者驱动,需要在编译内核后再通过 make modules 命令编译这些模块或者驱动
            $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules
            
            编译得到的内核模块文件以“ .ko”结尾,这些可以通过 insmod 命令插入到运行的内核中。
            有的模块编译得到单一的“ .ko”文件,且不依赖于其它模块,这样的模块可以直接用insmod 命令插入系统而不会出现错误。
            有的模块则可能编译后得到多个“ .ko”文件,或者依赖于其它模块文件,且各文件插入还有顺序要求,这就是常说的
            模块依赖。对于这样的情况,用 insmod 命令手工尝试得到依赖关系,然后按顺序插入也是可以的,但不推荐这样做,
            毕竟很麻烦。
            
        模块安装:
            建议编译模块后,再通过 make modules_install 命令安装模块,可将编译得到的全部模块安装到某一目录下,
            并且还会生成模块的依赖关系文件。默认情况下会将内核模块安装到编译机器的“ /”目录下,这一方面需要root
            权限,另一方面容易与主机文件混淆。
            
            建议通过 INSTALL_MOD_PATH 参数指定模块安装路径:
            $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- INSTALL_MOD_PATH=/work/rootfs  modules_install
            
            安装后将在安装目录下生成 “lib/modules/内核版本/” 目录,该目录下通常有下列文件和目录:
                build modules.alias modules.builtin modules.dep modules.devname
                modules.softdep modules.symbols.bin kernel/ modules.alias.bin modules.builtin.bin
                modules.dep.bin modules.order modules.symbols source
            
            所有的内核模块都在 kernel 目录下, modules.dep 是全部模块的依赖关系文件。将
            “lib/modules/内核版本/” 复制到目标系统后根目录后,就可以用 modprobe 命令进行模块安
            装,而不用手工逐一加载各个模块。该文件内容多少与内核模块多少相关,现在摘取一个实
            例片段进行说明:
            kernel/drivers/net/bonding/bonding.ko:  (1)
            kernel/drivers/usb/serial/usbserial.ko: (2)
            kernel/drivers/usb/serial/ftdi_sio.ko: kernel/drivers/usb/serial/usbserial.ko (3)
            每行开头至冒号(:)之前的表示一个内核模块,冒号之后的表示该模块所依赖的其它模块,
            必须先加载后面的模块才能加载该模块文件。冒号后面为空则表示该模块没有依赖关系。
            第(1)行表示模块文件 bonding.ko 没有依赖关系,可以直接用 insmod 命令加载到内核中:
            # insmod kernel/drivers/net/bonding/bonding.ko
            
            用 insmod 加载模块,必须指明文件路径,否则不能加载。用 modprobe 命令加载则无需带路径
            # modprobe bonding
            
            第(2)和(3)则共同说明了模块文件 ftdi_sio.ko 依赖于 usbserial.ko 文件, usbserial.ko 没有
            依赖文件。用 insmod 命令用法如下:
            # indmod kernel/drivers/usb/serial/usbserial.ko
            # insmod kernel/drivers/usb/serial/ftdi_sio.ko
            
            用 modprobe 命令就简单了:
            # modprobe ftdi_sio
            
    1.6.4 运行内核
        得到 uImage 映像文件后,将 uImage 加载到内存地址 ep-0x40 处,通过 bootm 命令即可
        运行内核:(zImage为真正的可以烧写的内核压缩镜像,而uImage为uboot启动的内核镜像,在zImage基础上加了64Bytes头信息。)
        # tftp 40007fc0 uImage     (地址为:40008000 - 64 = 40007fc0)
        # bootm 40007fc0
        uImage 启动会打印文件头信息并进行校验和计算,校验通过后开始内核自解压并运行:
        ## Booting kernel from Legacy Image at 40007fc0 ...
            Image Name: Linux-2.6.35.3-571-gcca29a0-gd43
            Image Type: ARM Linux Kernel Image (uncompressed)
            Data Size: 2653928 Bytes = 2.5 MB
            Load Address: 40008000
            Entry Point: 40008000
            Verifying Checksum ... OK
            Loading Kernel Image ... OK
            OK
            Starting kernel ...
            Uncompressing Linux... done, booting the kernel.
            ……
            以下省略
            
1.7 Linux 内核裁剪实例
    从零开始配置内核是不明智的,建议在某一个默认配置的基础上进行修改,以达到自己产品的实际需求。
    裁剪和配置内核的基本原则:
        a. 基于某一个最接近的主板配置来修改;
        b. 必须的、 能确定的选项选中;
        c. 不能确定的则不要改变原来配置;
        d. 可选可不选的,建议根据 help 信息决定或者不选;
        e. 一次改动不要太多,渐进式修改和验证;
        f. 注意及时备份配置文件,出现意外可以回退恢复。
        
    1.7.1 GPIO 子系统配置
        Linux 2.6 以上内核引入了子系统, GPIO 子系统将全部 GPIO 的操作接口都通过“ /sys/class/gpio/” 目录导出,
        非常方便用户使用。
        
    1.7.2 LED 子系统配置
        Linux LED 子系统提供了“ /sys/class/leds/”的访问接口,启用 LED 子系统能很方便地操作系统的 LED 资源。
        在“ Device Drivers”配置界面,选中“ LED Support”支持:
            <*> MMC/SD/SDIO card support --->
            < > Sony MemoryStick card support (EXPERIMENTAL) --->
            [*] LED Support --->
            [ ] Accessibility support --->
        进入“ LED Support” 子菜单, 选中 LED 类支持和 LED 触发器支持, 并根据需要设置触发器:
            --- LED Support
            [*] LED Class Support
            *** LED drivers ***
            ...
            [*] LED Trigger support
            *** LED Triggers ***
            <*> LED Timer Trigger
            <*> LED Heartbeat Trigger
            < > LED backlight Trigger
            <*> LED GPIO Trigger
            <*> LED Default ON Trigger
        只要将系统的 LED 设备驱动添加到 LED 子系统中,即可通过“ /sys/class/leds/”接口来进行访问。
        
    1.7.3 串口配置
        串口是嵌入式 Linux 必不可少的外设,默认控制台通常就是串口,所以必须在内核中使
        能串口以及串口控制台支持。
    
    1.7.4 USB Host 驱动配置
        USB 可以外接多种设备,不同设备的驱动配置也是不同的。下面以常用的 U 盘、 USB鼠标键盘配置为例进行介绍。
        1. 使用 U 盘
            U 盘在 Linux 系统下被认为是 SCSI 设备,所以必须在内核中选择支持 SCSI。在主菜单
            界面选择“ Device Drivers”,进入设备驱动配置界面,选择“ SCSI device support”。
        
        2. 使用 USB 键盘和鼠标
            使用 USB 键盘或者鼠标,需要在内核中使能 HID 支持。在“ Device Drivers”菜单界面,
            选中“ HID Devices”:
                <*> Sound card support --->
                [*] HID Devices --->
                [*] USB support --->
                <*> MMC/SD/SDIO card support --->
            进入“ HID Devices”,选中“ USB Human Interface Device (full HID) support”。
        
    1.7.5 USB Gadget 驱动配置
        USB Gadget 能通过 USB Device 实现诸如 U 盘模拟、USB 串口、USB 网卡等多种功能。
        首先在内核配置使能“ USB Gadget Support”。
        ....
        
    1.7.6 SD/MMC 驱动配置
        在“ Device Drivers”菜单中使能“ MMC/SD/SDIO card support”:
            Device Drivers --->
            <*> MMC/SD/SDIO card support --->
        进入“ MMC/SD/SDIO card support”,使能 “ MMC block device driver”。在 “ MMC/SD/SDIO
        Host Controller Drivers”下选择处理器对应的 SD/MMC 控制器。

        另外还需根据 SD/MMC 卡的文件系统格式在内核中配置相应的文件系统支持。如果是
        FAT 格式,请参考前面“使用 U 盘”中 VFAT 的配置;如果采用 Ext2/3/4 格式,则进行如下配置:
            File systems --->
            <*> Second extended fs support
            <*> Ext3 journalling file system support
            <*> The Extended 4 (ext4) filesystem
        
    1.7.7 网卡驱动配置
        配置网卡首先要在主菜单中使能网络,即选中“ Networking support”:
            Power management options --->
            [*] Networking support --->
            Device Drivers --->
            File systems --->
        为了正常使用网络,通常还需在“ Networking options” 中配置 TCP/IP。
        
    1.7.8 NFS Client 配置
        使用 NFS 文件系统,首先需要保证网卡可用,且在内核已经配置了网卡。在“ File system”
        配置界面使能“ Network File Systems”并进行配置。
        
    1.7.9 PPP 拨号配置
        PPP 拨号配置, 在“ Device Drivers” 的“ Network device support” 菜单下。选中并使能
        “ PPP (point-to-point protocol) support” 及子选项即可使用 PPP 拨号功能。这里以模块方式
        编译。
        
    1.7.10 MTD 配置
        在内核配置主菜单界面,进入“ Device Drivers”界面,选择“ Memory Technology Device(MTD) support”:
            < > Connector - unified userspace <-> kernelspace linker --->
            <*> Memory Technology Device (MTD) support --->
                Device Tree and Open Firmware support --->
            < > Parallel port support --->
        并进入“ Memory Technology Device (MTD) support”,进行配置。
    
    1.7.11 UBIFS 文件系统配置
        UBIFS 是工作于 UBI 子系统之上的文件系统,而 UBI 又工作于 MTD 设备上,所以首
        先需要在 MTD 中使能 UBI:
            Device Drivers --->
            <*> Memory Technology Device (MTD) support --->
            <*> Enable UBI - Unsorted block images --->
        进入“ Enable UBI - Unsorted block images”, 对 UBI 进行配置:
            --- Enable UBI - Unsorted block images
            (4096) UBI wear-leveling threshold
            (1) Percentage of reserved eraseblocks for bad eraseblocks handling
            < > MTD devices emulation driver (gluebi)
            [ ] UBI debugging
        其中“ Percentage of reserved eraseblocks for bad eraseblocks handling” 设置用于坏块管理
        的保留块的百分比, 默认是 1%, 可以适当调整大一些, 不过必须与 U-Boot 中的设置一致。
        还需在文件系统设置中使能和配置 UBIFS:
            File systems --->
            [*] Miscellaneous filesystems --->
            <*> UBIFS file system support
            [*] Extended attributes support
            [*] Advanced compression options
            [*] LZO compression support (NEW)
            [*] ZLIB compression support (NEW)
            
    1.7.12 CAN 驱动配置
        前面已经提到过, CAN 设备驱动的配置路径不在“ Devie Drivers”下,而是在 “ Networking
        support” 中。进入内核配置主菜单,选择“ Networking support”。

        
1.8 EPC-28x 平台内核快速编译
    从 EPC-28x光盘内获取内核源码包 EPC-28x.xxxxx.tar.bz2,然后把它拷贝到 Ubuntu 下面,执行如下步骤:
    1. 解压缩
        vmuser@Linux-host ~$ tar -vxjf EPC-28x.xxxxx.tar.bz2
        解压后产生内核目录: linux-2.6.35.3
        
    2. 编译内核
        EPC-28x 内核源码的 Makefile 文件内已经配置好了 ARCH 和 CROSS_COMPILE,所以在 make 时无需指定
        ARCH 和 CROSS_COMPILE。
        EPC-28x 的源码已经包含配置好的.config 文件, 无需 make menuconfig 配置即可使用默认配置, 除非需要改动内核配置。
        vmuser@Linux-host ~$ cd linux-2.6.35.3
        vmuser@Linux-host ~/ linux-2.6.35.3$ make uImage
        
        编译完成,将得到内核文件
        另外,在执行 make distclean 或者 make mrproper 之前, 请先将.config 配置文件备份,
        如:vmuser@Linux-host ~/ linux-2.6.35.3$cp .config config-bak


阅读(4115) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~