zoukankan      html  css  js  c++  java
  • centos6 cgroup及cgred简介和简单使用

    一、cgroup简介

      Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。这个项目最早是由Google的工程师在2006年发起(主要是Paul Menage和Rohit Seth),最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器(container)这个名词太过广泛,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。然后,其它开始了他的发展。 
    
      Linux CGroupCgroup 可​​​让​​​您​​​为​​​系​​​统​​​中​​​所​​​运​​​行​​​任​​​务​​​(进​​​程​​​)的​​​用​​​户​​​定​​​义​​​组​​​群​​​分​​​配​​​资​​​源​​​ — 比​​​如​​​ CPU 时​​​间​​​、​​​系​​​统​​​内​​​存​​​、​​​网​​​络​​​带​​​宽​​​或​​​者​​​这​​​些​​​资​​​源​​​的​​​组​​​合​​​。​​​您​​​可​​​以​​​监​​​控​​​您​​​配​​​置​​​的​​​ cgroup,拒​​​绝​​​ cgroup 访​​​问​​​某​​​些​​​资​​​源​​​,甚​​​至​​​在​​​运​​​行​​​的​​​系​​​统​​​中​​​动​​​态​​​配​​​置​​​您​​​的​​​ cgroup。

    主要功能:

    1 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
    2 优先级控制,CPU利用和磁盘IO吞吐。
    3 一些审计或一些统计,主要目的是为了计费。
    4 挂起进程,恢复执行进程。

    cgroups子系统:

     1 cpu 子系统,主要限制进程的 cpu 使用率。
     2 cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
     3 cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
     4 memory 子系统,可以限制进程的 memory 使用量。
     5 blkio 子系统,可以限制进程的块设备 io。
     6 devices 子系统,可以控制进程能够访问某些设备。
     7 net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
     8 net_prio — 这个子系统用来设计网络流量的优先级
     9 freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
    10 ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace
    11 hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统。

    cgred简介

    Cgred 是​​​一​​​个​​​守​​​护​​​进​​​程​​​,它​​​可​​​根​​​据​​​在​​​ /etc/cgrules.conf 文​​​件​​​中​​​设​​​定​​​的​​​参​​​数​​​将​​​任​​​务​​​移​​​动​​​到​​​ cgroup 中​​​。​​​/etc/cgrules.conf 文​​​件​​​中​​​的​​​条​​​目​​​可​​​以​​​使​​​用​​​以​​​下​​​两​​​个​​​格​​​式​​​之​​​一​​​:
    user hierarchies control_group
    user:command hierarchies control_group
    例​​​如​​​:
    maria            devices        /usergroup/staff
    这​​​个​​​条​​​目​​​指​​​定​​​任​​​何​​​属​​​于​​​名​​​为​​​ maria 用​​​户​​​的​​​进​​​程​​​根​​​据​​​在​​​
    /usergroup/staff cgroup 中​​​指​​​定​​​的​​​参​​​数​​​访​​​问​​​设​​​备​​​子​​​系​​​统​​​。​​​要​​​将​​​具​​​体​​​命​​​令​​​与​​​具​​​体​​​ cgroup 关​​​联​​​,请​​​添​​​加​​​ command 参​​​数​​​,如​​​下​​​: maria:ftp devices /usergroup/staff/ftp
    该​​​条​​​目​​​现​​​在​​​指​​​定​​​何​​​时​​​名​​​为​​​ maria 的​​​用​​​户​​​使​​​用​​​ ftp 命​​​令​​​,自​​​动​​​将​​​该​​​进​​​程​​​移​​​动​​​到​​​包​​​含​​​ devices 子​​​系​​​统​​​的​​​层​​​级​​​中​​​的​​​
    /usergroup/staff/ftp cgroup 中​​​。​​​请​​​注​​​意​​​:该​​​守​​​护​​​进​​​程​​​只​​​有​​​在​​​符​​​合​​​适​​​当​​​的​​​条​​​件​​​后​​​才​​​可​​​将​​​该​​​进​​​程​​​移​​​动​​​到​​​该​​​ cgroup 中​​​。​​​因​​​此​​​,ftp 可​​​能​​​会​​​在​​​错​​​误​​​的​​​组​​​群​​​中​​​短​​​暂​​​运​​​行​​​。​​​再​​​有​​​,如​​​果​​​该​​​进​​​程​​​在​​​错​​​误​​​组​​​群​​​中​​​迅​​​速​​​生​​​出​​​子​​​进​​​程​​​,则​​​不​​​会​​​移​​​动​​​这​​​些​​​子​​​进​​​程​​​。​​​ /etc/cgrules.conf 文​​​件​​​中​​​的​​​条​​​目​​​可​​​包​​​括​​​以​​​下​​​额​​​外​​​符​​​号​​​: @ - 当​​​在​​​ user 使​​​用​​​前​​​缀​​​时​​​,代​​​表​​​是​​​一​​​个​​​组​​​群​​​而​​​不​​​是​​​单​​​独​​​用​​​户​​​。​​​例​​​如​​​:@admins 是​​​ admins 组​​​群​​​中​​​的​​​所​​​有​​​用​​​户​​​。​​​ * - 代​​​表​​​“​​​所​​​有​​​”​​​。​​​例​​​如​​​:subsystem 字​​​段​​​中​​​的​​​ * 代​​​表​​​所​​​有​​​子​​​系​​​统​​​。​​​ % - 代​​​表​​​与​​​以​​​上​​​行​​​中​​​项​​​目​​​相​​​同​​​的​​​项​​​目​​​。​​​例​​​如​​​: @adminstaff devices /admingroup @labstaff % %

    小结:通过cgroup设置我们想要的规则,通过cgred将规则应用到进程之上

    二、CPU限制

    1.查看已经使用的子系统

    [root@reddhat6_155_200 ~]# lssubsys -m
    cpuset /cgroup/cpuset
    cpu /cgroup/cpu
    cpuacct /cgroup/cpuacct
    memory /cgroup/memory
    devices /cgroup/devices
    freezer /cgroup/freezer
    net_cls /cgroup/net_cls
    blkio /cgroup/blkio

    2.编辑cgroup配置文件,添加两个group对CPU使用率的限制

    [root@reddhat6_155_200 ~]# vim /etc/cgconfig.conf  #添加以下两段
    group lesscpu{
        cpu{
    
    }
    }
    
    group morecpu{
        cpu{
    }
    }

    3.重启并查看CPU子系统目录

    [root@reddhat6_155_200 ~]# /etc/init.d/cgconfig restart
    Stopping cgconfig service:                                 [确定]
    Starting cgconfig service:                                 [确定]
    [root@reddhat6_155_200 ~]# ll /cgroup/cpu
    总用量 0
    --w--w--w-. 1 root root 0 2019-09-07 15:50 cgroup.event_control
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cgroup.procs
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cpu.cfs_period_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cpu.cfs_quota_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cpu.rt_period_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cpu.rt_runtime_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 cpu.shares
    -r--r--r--. 1 root root 0 2019-09-07 15:50 cpu.stat
    drwxr-xr-x. 2 root root 0 2019-09-07 15:50 lesscpu    #多出两个目录,和我们定义的group名称是一至的
    drwxr-xr-x. 2 root root 0 2019-09-07 15:50 morecpu
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 notify_on_release
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 release_agent
    -rw-r--r--. 1 root root 0 2019-09-07 15:50 tasks

    4.查看目录内容

    [root@reddhat6_155_200 ~]# ll /cgroup/cpu         仔细观察可以发现每个目录中的文件都是相同的,也就是默认情况下group会继承该子系统的所有规则
    [root@reddhat6_155_200 ~]# ll /cgroup/cpu/morecpu/   
    [root@reddhat6_155_200 ~]# ll /cgroup/cpu/morecpu/

    5.添加group规则

    [root@reddhat6_155_200 ~]# cat /cgroup/cpu/cpu.shares  #cpu.shares表示程序可以在​​​ cgroup 中​​​的​​​任​​​务​​​可​​​用​​​的​​​相​​​对​​​共​​​享​​​ CPU 时​​​间​​​的​​​整​​​数​​​值​​​,默认为1024
    1024
    [root@reddhat6_155_200 ~]# vim /etc/cgconfig.conf 
    group lesscpu{
        cpu{
              cpu.shares=100;    #该值不可以超过总大小(1024)
    }
    }
    
    group morecpu{
        cpu{
              cpu.shares=200;
    }
    }
    [root@reddhat6_155_200 ~]# /etc/init.d/cgconfig restart
    Stopping cgconfig service:                                 [确定]
    Starting cgconfig service:                                 [确定]

     [root@reddhat6_155_200 ~]# cat /cgroup/cpu/lesscpu/cpu.shares
     100
     [root@reddhat6_155_200 ~]# cat /cgroup/cpu/morecpu/cpu.shares
     200

    6.为了减少演示的复杂度,我们下线其他CPU,只保留一个CPU

    [root@reddhat6_155_200 ~]# lscpu |grep -A 1  "^CPU(s):"  #查看当前CPU个数及在线个数
    CPU(s):                2
    On-line CPU(s) list:   0,1
    [root@reddhat6_155_200 ~]# echo 0 > /sys/devices/system/cpu/cpu1/online   #将cpu1下线,cpu0为主cpu无法下线
    [root@reddhat6_155_200 ~]# lscpu |grep -A 1  "^CPU(s):"   #查看在线状态,目前只有cpu0在线
    CPU(s):                2
    On-line CPU(s) list:   0

    7.新开一个窗口,同时执行dd命令,分别选择lesscpu和morecpu

    [root@reddhat6_155_200 ~]# cgexec -g cpu:lesscpu time dd if=/dev/zero of=/dev/null bs=1M count=200000   #窗口1 分配少的先执行
    [root@reddhat6_155_200 ~]# cgexec -g cpu:morecpu time dd if=/dev/zero of=/dev/null bs=1M count=200000   #窗口2
    [root@reddhat6_155_200 ~]# top   #窗口3 使用top命令监控命令状态

    注意观察两个dd命令CPU使用率

    lesscpu结果:

    [root@reddhat6_155_200 ~]# cgexec -g cpu:lesscpu time dd if=/dev/zero of=/dev/null bs=1M count=200000
    记录了200000+0 的读入
    记录了200000+0 的写出
    209715200000字节(210 GB)已复制,21.7357 秒,9.6 GB/秒   #注意CPU使用时间
    0.01user 10.83system 0:21.73elapsed 33%CPU (0avgtext+0avgdata 7776maxresident)k   #注意CPU使用率
    0inputs+0outputs (0major+521minor)pagefaults 0swaps

    morecpu结果:

    [root@reddhat6_155_200 ~]# cgexec -g cpu:morecpu time dd if=/dev/zero of=/dev/null bs=1M count=200000
    记录了200000+0 的读入
    记录了200000+0 的写出
    209715200000字节(210 GB)已复制,16.26 秒,12.9 GB/0.02user 10.77system 0:16.26elapsed 66%CPU (0avgtext+0avgdata 7744maxresident)k
    0inputs+0outputs (0major+519minor)pagefaults 0swaps

     三、MEM限制

    1.编辑cgroup配置文件,添加一个mem限制

    [root@reddhat6_155_200 ~]# cat /cgroup/memory/memory.limit_in_bytes  #查看MEM(物理内存)默认限制大小 单位为字节 以目前机器配置,等同于无限制
    9223372036854775807
    [root@reddhat6_155_200 ~]# cat /cgroup/memory/memory.memsw.limit_in_bytes #查看MEM(物理内存)+Swap总的大小 此值必须大于等于 memory.limit_in_bytes 
    9223372036854775807
    [root@reddhat6_155_200 ~]# vim /etc/cgconfig.conf     #添加一个MEM 限制
    group poormem{
        memory{
            memory.limit_in_bytes=268435456;   #限制可以使用内存大小为256M
    }
    [root@reddhat6_155_200 ~]# /etc/init.d/cgconfig restart
    Stopping cgconfig service:                                 [确定]
    Starting cgconfig service:                                 [确定]
    [root@reddhat6_155_200 ~]# cat /cgroup/memory/poormem/memory.limit_in_bytes

    268435456

     2.创建一个内存盘

    [root@reddhat6_155_200 ~]# mkdir /mnt/tmpfs
    [root@reddhat6_155_200 ~]# mount -t tmpfs none /mnt/tmpfs  #注意没有挂载源 使用none
    [root@reddhat6_155_200 ~]# df -h
    Filesystem            Size  Used Avail Use% Mounted on
    /dev/mapper/vg_redhat6demo01-lv_root
                           50G  5.4G   42G  12% /
    tmpfs                 2.0G  224K  2.0G   1% /dev/shm
    /dev/vda1             477M   33M  419M   8% /boot
    /dev/mapper/vg_redhat6demo01-lv_home
                          5.5G   12M  5.2G   1% /home
    none                  2.0G     0  2.0G   0% /mnt/tmpfs   #大小2G,具体大小和系统剩余内存大小有关

    3.测试tmpfs特性

    [root@reddhat6_155_200 ~]# free -m  #查看当前内存大小
                 total       used       free     shared    buffers     cached
    Mem:          3959       2508       1451          2        246       1784
    -/+ buffers/cache:        477       3482
    Swap:         3967          0       3967
    [root@reddhat6_155_200 ~]# dd if=/dev/zero of=/mnt/tmpfs/test bs=1M count=1000  #向 tmpfs 挂载点写入1G内存
    记录了1000+0 的读入
    记录了1000+0 的写出
    1048576000字节(1.0 GB)已复制,0.466811 秒,2.2 GB/秒
    [root@reddhat6_155_200 ~]# free -m   #查看系统内存  少了1G
                 total       used       free     shared    buffers     cached
    Mem:          3959       3511        448       1002        246       2784
    -/+ buffers/cache:        480       3479
    Swap:         3967          0       3967
    [root@reddhat6_155_200 ~]# rm -f /mnt/tmpfs/test  #删除刚刚创建的文件
    [root@reddhat6_155_200 ~]# free -m   #查看当前剩余内存
                 total       used       free     shared    buffers     cached
    Mem:          3959       2509       1450          2        246       1784
    -/+ buffers/cache:        478       3481
    Swap:         3967          0       3967

    4.测试

    [root@reddhat6_155_200 ~]# cgexec -g memory:poormem dd if=/dev/zero of=/mnt/tmpfs/test bs=1M count=200 #配置的为256M 先创建一个200M 测试文件
    记录了200+0 的读入
    记录了200+0 的写出
    209715200字节(210 MB)已复制,0.097221 秒,2.2 GB/秒
    [root@reddhat6_155_200 ~]# rm -f /mnt/tmpfs/test 
    [root@reddhat6_155_200 ~]# cgexec -g memory:poormem dd if=/dev/zero of=/mnt/tmpfs/test bs=1M count=300 #创建一个300M测试文件 挂了  很奇怪,按照文档说明此处不应该挂的,应该不够的会从Swap中读取 只有 memory.memsw.limit_in_bytes 也设置了才会限制从Swap中读取 不知道为啥??????
    已杀死 [root@reddhat6_155_200 ~]# ll -h /mnt/tmpfs/test #查看大小只有
    255M -rw-r--r--. 1 root root 255M 2019-09-07 22:03 /mnt/tmpfs/test

    四、磁盘IO限制  #使用IO限制时当前系统调度算法必须为cfq算法

    [root@reddhat6_155_200 ~]# cat /sys/block/vda/queue/scheduler   #查看下当前系统磁盘调度算法 vda表示磁盘名称
    noop anticipatory deadline [cfq] 
    [root@reddhat6_155_200 ~]# cat /cgroup/blkio/blkio.weight       #查看磁盘io权重默认值
    1000
    [root@reddhat6_155_200 ~]# vim /etc/cgconfig.conf  #创建io限制规则
    group lowio{
            blkio{
              blkio.weight=100;   #设置io优先级 一个低 一个高
    }
    }
    
    group highio{
            blkio{
              blkio.weight=200;
    }
    }
    
    group ddio{
            blkio{
              blkio.throttle.read_bps_device="252:0 1000000";   
    #限制程序读取磁盘的速度 252表示当前主盘符号 0表示副盘符号 1000000表示读取速率 单位为字节 即1M 需要注意的是,如果是物理设备 SCSI设备重启后主副盘符会发生变化 可以通过设置逻辑卷 } } [root@reddhat6_155_200
    ~]# /etc/init.d/cgconfig restart Stopping cgconfig service: [确定] Starting cgconfig service: [确定]

    测试

    [root@reddhat6_155_200 ~]# dd if=/dev/zero of=/root/bigfile1 bs=1M count=10000 #创建两个大的文件用于实验
    [root@reddhat6_155_200 ~]# dd if=/dev/zero of=/root/bigfile2 bs=1M count=10000
    [root@reddhat6_155_200 ~]# echo 3 > /proc/sys/vm/drop_caches    #情况缓存 避免影响结果
    [root@reddhat6_155_200 ~]# iotop       #使用iotop命令监控io状态

    新开两个窗口,分别使用lowio和highio

    [root@reddhat6_155_200 ~]# cgexec -g blkio:lowio time cat /root/bigfile1 > /dev/null 
    [root@reddhat6_155_200 ~]# cgexec -g blkio:highio time cat /root/bigfile2 > /dev/null

    结果:当两个cat命令都读取时,使用highio磁盘速度大约是lowio的两倍

    当highio执行完成后lowio开始独占磁盘io

    [root@reddhat6_155_200 ~]# cgexec -g blkio:lowio time cat /root/bigfile1 > /dev/null 
    0.08user 7.52system 0:40.54elapsed 18%CPU (0avgtext+0avgdata 2416maxresident)k
    20480360inputs+0outputs (1major+182minor)pagefaults 0swaps
    
    [root@reddhat6_155_200 ~]# cgexec -g blkio:highio time cat /root/bigfile2 > /dev/null
    0.08user 7.16system 0:32.64elapsed 22%CPU (0avgtext+0avgdata 2432maxresident)k
    20480072inputs+0outputs (1major+183minor)pagefaults 0swaps

    限制指定用户执行指定命令

    [root@reddhat6_155_200 ~]# vim /etc/cgrules.conf 
    admin:dd    blkio   ddio/        #此行配置表示 admin用户执行dd命令时 使用 blkio子系统下ddio group进行限制  此处不仅可以现在命令也可以现在程序 添加程序的启动命令即可 例 nginx java等
    [root@reddhat6_155_200 ~]# /etc/init.d/cgred restart
    正在停止 CGroup Rules Engine 守护进程......                [确定]
    Starting CGroup Rules Engine Daemon:                    [确定]

    使用root用户测试dd命令

    [root@reddhat6_155_200 ~]# dd if=/tmp/bigfile1 of=/dev/null
    记录了20480000+0 的读入
    记录了20480000+0 的写出
    10485760000字节(10 GB)已复制,18.5243 秒,566 MB/秒  #速度正常

    切换至admin用户执行dd命令

    [root@reddhat6_155_200 ~]# mv /root/bigfile1 /tmp/
    [root@reddhat6_155_200 ~]# su -  admin
    [admin@reddhat6_155_200 ~]$ dd if=/tmp/bigfile1 of=/dev/null 

    新开一个窗口,使用iotop命令监控

    [admin@reddhat6_155_200 ~]$ dd if=/tmp/bigfile1 of=/dev/null 
    记录了210657+0 的读入
    记录了210656+0 的写出
    107855872字节(108 MB)已复制,107.986 秒,999 kB/秒  #注意此处的速率  时间是因为我提前中断了程序

    我们发现,无论怎样,IO读取不会大于1M

    注意事项:

    1 磁盘IO调度算法必须为cfq
    2 测试前需要先清空磁盘缓存
    3 不要使用SSD硬盘
    4 读取速率注意SCSI物理硬盘盘符会随机更改

    五、创建两个及以上资源控制子系统(默认每种资源只能单独控制)

    1.修改配置文件,配置一个多控制项的子系统

    [root@reddhat6_155_200 ~]# vim /etc/cgconfig.conf 
    mount {
        cpuset  = /cgroup/cpuset;
    #   cpu = /cgroup/cpu;                  #以CPU内存为例,注释cpu、memory字段
        cpuacct = /cgroup/cpuacct;
    #   memory  = /cgroup/memory;
        cpu = /cgroup/cpumem;               #新添加cpu、memory字段将其路径指向同一路径
        memory = /cgroup/cpumem;
        devices = /cgroup/devices;
        freezer = /cgroup/freezer;
        net_cls = /cgroup/net_cls;
        blkio   = /cgroup/blkio;
    }

    2.重启服务(注意:重启时需要退出/cgroup目录,否则会重启失败)

    [root@reddhat6_155_200 ~]# /etc/init.d/cgconfig restart
    Stopping cgconfig service:                                 [确定]
    Starting cgconfig service:                                 [确定]

    3.检查目录

    [root@reddhat6_155_200 ~]# ll /cgroup/
    总用量 8
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 blkio
    drwxr-xr-x. 2 root root 4096 2019-08-30 17:24 cpu
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 cpuacct
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 cpumem     #我们自定义的 
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 cpuset
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 devices
    drwxr-xr-x. 3 root root    0 2019-09-07 15:07 freezer
    drwxr-xr-x. 2 root root 4096 2019-08-30 17:24 memory
    drwxr-xr-x. 2 root root    0 2019-09-07 15:07 net_cls
    [root@reddhat6_155_200 ~]# ll /cgroup/cpu                  #原先的cpu及memory已经失效了
    总用量 0
    [root@reddhat6_155_200 ~]# ll /cgroup/memory/
    总用量 0
    [root@reddhat6_155_200 ~]# ll /cgroup/cpumem/              #所有mem和cpu配置都在cpumem目录下
    总用量 0
    --w--w--w-. 1 root root 0 2019-09-07 15:07 cgroup.event_control
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cgroup.procs
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cpu.cfs_period_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cpu.cfs_quota_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cpu.rt_period_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cpu.rt_runtime_us
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 cpu.shares
    -r--r--r--. 1 root root 0 2019-09-07 15:07 cpu.stat
    -rw-r--r--. 1 root root 0 2019-09-07 15:07 memory.failcnt
    --w-------. 1 root root 0 2019-09-07 15:07 memory.force_empty
    ......

    参考文档:https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/6/html/resource_management_guide/sec-moving_a_process_to_a_control_group#The_cgred_Daemon

  • 相关阅读:
    [SHOI2015]自动刷题机
    【教程】AI画放射图
    AI画圆角矩形
    极限运动:街头极限单车,不只是牛逼!
    DPK750针式打印机驱动,750u.dll下载
    文艺青年必看的Ⅹ部心理电影
    C语言程序设计-第2章 算法-程序的灵魂
    C语言程序设计-第1章 程序设计和C语言
    20151127笔记
    20151125小概念
  • 原文地址:https://www.cnblogs.com/panwenbin-logs/p/11481108.html
Copyright © 2011-2022 走看看