• Android TV : 系统分区配置及增加私有分区


    一、系统分区配置及解析流程

      Android系统开发时,经常会遇到添加或者调整系统分区大小的问题,下面以mstar的一款产品(M8386)为例进行分析。

    (1)mount指令可以查看到板子中挂载的分区,主要关注ext4类型分区,例如tvservice,tvconfig,tvconfig,tvcustomer :

    sugarcane:/ # mount
    rootfs on / type rootfs (ro,seclabel)
    tmpfs on /dev type tmpfs (rw,seclabel,nosuid,relatime,mode=755)
    devpts on /dev/pts type devpts (rw,seclabel,relatime,mode=600,ptmxmode=000)
    proc on /proc type proc (rw,relatime)
    sysfs on /sys type sysfs (rw,seclabel,relatime)
    selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)
    /dev/block/mmcblk0p11 on /system type ext4 (rw,seclabel,relatime,data=ordered)
    /dev/block/mmcblk0p13 on /vendor type ext4 (rw,seclabel,relatime,data=ordered)
    debugfs on /sys/kernel/debug type debugfs (rw,seclabel,relatime)
    none on /acct type cgroup (rw,relatime,cpuacct)
    none on /dev/stune type cgroup (rw,relatime,schedtune)
    tmpfs on /mnt type tmpfs (rw,seclabel,relatime,mode=755,gid=1000)
    none on /config type configfs (rw,relatime)
    none on /dev/cpuctl type cgroup (rw,relatime,cpu)
    none on /dev/cpuset type cgroup (rw,relatime,cpuset,noprefix,release_agent=/sbin/cpuset_release_agent)
    pstore on /sys/fs/pstore type pstore (rw,seclabel,relatime)
    tmpfs on /var type tmpfs (rw,seclabel,relatime,mode=775,gid=1000)
    /dev/block/mmcblk0p23 on /data type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p12 on /cache type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p14 on /tvservice type ext4 (ro,seclabel,relatime,data=ordered)
    /dev/block/mmcblk0p15 on /tvconfig type ext4 (ro,seclabel,relatime,data=ordered)
    /dev/block/mmcblk0p16 on /tvdatabase type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p17 on /tvcustomer type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p22 on /tvcertificate type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p18 on /cusswap type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p19 on /cusdata type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    /dev/block/mmcblk0p21 on /cusparam type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)
    tmpfs on /storage type tmpfs (rw,seclabel,relatime,mode=755,gid=1000)
    tracefs on /sys/kernel/debug/tracing type tracefs (rw,seclabel,relatime)
    /data/media on /mnt/runtime/default/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,reserved=50MB)
    /data/media on /storage/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,reserved=50MB)
    /data/media on /mnt/runtime/read/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=23,reserved=50MB)
    /data/media on /mnt/runtime/write/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=7,reserved=50MB)

     (2)查看分区文件 /device/mstar/sugarcane/fstab.m7221 (android平台不同厂商可能名称不一样,但是都是fstab.xxx的形式) ,截取部分信息如下:

    /dev/block/platform/mstar_mci.0/by-name/system          /system             ext4      ro                                                    wait,recoveryonly
    /dev/block/platform/mstar_mci.0/by-name/userdata        /data               ext4      noatime,nosuid,nodev                                  wait,check
    /dev/block/platform/mstar_mci.0/by-name/cache           /cache              ext4      noatime,nosuid,nodev                                  wait,check
    /dev/block/platform/mstar_mci.0/by-name/vendor          /vendor             ext4      ro                                                    wait,recoveryonly
    /dev/block/platform/mstar_mci.0/by-name/tvservice       /tvservice          ext4      ro                                                    wait
    /dev/block/platform/mstar_mci.0/by-name/tvconfig        /tvconfig           ext4      ro                                                    wait
    /dev/block/platform/mstar_mci.0/by-name/tvdatabase      /tvdatabase         ext4      noatime,nosuid,nodev                                  wait,check
    /dev/block/platform/mstar_mci.0/by-name/tvcustomer      /tvcustomer         ext4      noatime,nosuid,nodev                                  wait,check
    /dev/block/platform/mstar_mci.0/by-name/tvcertificate   /tvcertificate      ext4      noatime,nosuid,nodev                                  wait,check

     (3)指定各个分区的大小,device/mstar/sugarcane/BoardConfig.mk 文件指定各自大小可以根据需要进行修改

    # mmc part
    # :  type name      (size)
    #1.  recovery       (30M)
    #2.  boot           (20M)
    #3.  tee            (6M)
    #4.  rtpm           (256K)
    #5.  dtb            (1M)
    #6.  frc            (1M)
    #7.  optee          (6M)
    #8.  armfw          (64K)
    #9.  system         (1200M)
    #10. userdata       (4400M)
    #11. cache          (1G)
    #12. vendor         (300M)
    #13. tvservice      (160M)
    #14. tvconfig       (19M)
    #15. tvdatabase     (8M)
    #16. tvcustomer     (16M)
    #17. tvcertificate  (8M)
    #18. cm4            (512K)
    #19. cusswap        (5M)
    #20. cusdata        (5M)
    #21. cusparam       (512M)
    BOARD_RECOVERYIMAGE_PARTITION_SIZE      := 0x02000000
    BOARD_BOOTIMAGE_PARTITION_SIZE          := 0x01400000
    BOARD_OPTEEIMAGE_PARTITION_SIZE         := 0x00600000
    BOARD_ARMFWIMAGE_PARTITION_SIZE         := 0x00010000
    BOARD_TEEIMAGE_PARTITION_SIZE           := 0x00600000
    BOARD_RTPMIMAGE_PARTITION_SIZE          := 0x00040000
    BOARD_DTBIMAGE_PARTITION_SIZE           := 0x00100000
    BOARD_FRCIMAGE_PARTITION_SIZE           := 0x00100000
    BOARD_CACHEIMAGE_PARTITION_SIZE         := 1073741824
    ifeq ($(BOARD_EMMC_FLASH_SIZE),16G)
        BOARD_SYSTEMIMAGE_PARTITION_SIZE    := 2147483648
        BOARD_VENDORIMAGE_PARTITION_SIZE    := 3221225472
    else
        BOARD_SYSTEMIMAGE_PARTITION_SIZE    := 1992294400 
        BOARD_VENDORIMAGE_PARTITION_SIZE    := 419430400 
    endif
    BOARD_TVSERVICEIMAGE_PARTITION_SIZE     := 0x0A000000
    BOARD_TVCONFIGIMAGE_PARTITION_SIZE      := 0x01000000
    BOARD_TVDATABASEIMAGE_PARTITION_SIZE    := 0x00800000
    BOARD_TVCUSTOMERIMAGE_PARTITION_SIZE    := 0x01000000
    BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE := 0x00800000
    BOARD_CM4IMAGE_PARTITION_SIZE           := 0x00080000
    BOARD_CUSSWAP_PARTITION_SIZE            := 5242880
    BOARD_CUSDATA_PARTITION_SIZE            := 5242880
    ifeq ($(BOARD_EMMC_ENLARGE_PARAM),Y)
        BOARD_CUSPARAM_PARTITION_SIZE       := 536870912
    else
        BOARD_CUSPARAM_PARTITION_SIZE       := 5242880
    endif
    BOARD_USERDATAIMAGE_PARTITION_SIZE      := 817889280
    
    BOARD_FLASH_BLOCK_SIZE := 512

     (4)分区调整后在device/mstar/sugarcane/ 下的 fstab.m7221 中指定挂载节点及其他属性,由nit.m7221.rc脚本中on fs 模块启动:

    on fs
        write /proc/sys/vm/page-cluster 0
        mount_all /fstab.m7221
        swapon_all /fstab.m7221

    (5)init进程解析fstab.monet文件,keywords.h文件中注册mount_all操作方法 :

    enum {
        K_UNKNOWN,
    #endif
        KEYWORD(capability,  OPTION,  0, 0)
        KEYWORD(chdir,       COMMAND, 1, do_chdir)
        KEYWORD(chroot,      COMMAND, 1, do_chroot)
        KEYWORD(class,       OPTION,  0, 0)
        KEYWORD(class_start, COMMAND, 1, do_class_start)
        KEYWORD(class_stop,  COMMAND, 1, do_class_stop)
        KEYWORD(class_reset, COMMAND, 1, do_class_reset)
        KEYWORD(console,     OPTION,  0, 0)
        KEYWORD(critical,    OPTION,  0, 0)
        KEYWORD(disabled,    OPTION,  0, 0)
        KEYWORD(domainname,  COMMAND, 1, do_domainname)
        KEYWORD(enable,      COMMAND, 1, do_enable)
        KEYWORD(exec,        COMMAND, 1, do_exec)
        KEYWORD(export,      COMMAND, 2, do_export)
        KEYWORD(group,       OPTION,  0, 0)
        KEYWORD(hostname,    COMMAND, 1, do_hostname)
        KEYWORD(ifup,        COMMAND, 1, do_ifup)
        KEYWORD(insmod,      COMMAND, 1, do_insmod)
        KEYWORD(import,      SECTION, 1, 0)
        KEYWORD(keycodes,    OPTION,  0, 0)
        KEYWORD(mkdir,       COMMAND, 1, do_mkdir)
        KEYWORD(mount_all,   COMMAND, 1, do_mount_all)
        KEYWORD(mount,       COMMAND, 3, do_mount)
        KEYWORD(on,          SECTION, 0, 0)
        KEYWORD(oneshot,     OPTION,  0, 0)
        KEYWORD(onrestart,   OPTION,  0, 0)
        KEYWORD(powerctl,    COMMAND, 1, do_powerctl)
        KEYWORD(restart,     COMMAND, 1, do_restart)
        KEYWORD(restorecon,  COMMAND, 1, do_restorecon)
        KEYWORD(restorecon_recursive,  COMMAND, 1, do_restorecon_recursive)
        KEYWORD(rm,          COMMAND, 1, do_rm)
        KEYWORD(rmdir,       COMMAND, 1, do_rmdir)
        KEYWORD(seclabel,    OPTION,  0, 0)
        KEYWORD(service,     SECTION, 0, 0)
        KEYWORD(setcon,      COMMAND, 1, do_setcon)
        KEYWORD(setenforce,  COMMAND, 1, do_setenforce)
        KEYWORD(setenv,      OPTION,  2, 0)
        KEYWORD(setkey,      COMMAND, 0, do_setkey)
        KEYWORD(setprop,     COMMAND, 2, do_setprop)
        KEYWORD(setrlimit,   COMMAND, 3, do_setrlimit)
        KEYWORD(setsebool,   COMMAND, 2, do_setsebool)
        KEYWORD(socket,      OPTION,  0, 0)
        KEYWORD(start,       COMMAND, 1, do_start)
        KEYWORD(stop,        COMMAND, 1, do_stop)
        KEYWORD(swapon_all,  COMMAND, 1, do_swapon_all)
        KEYWORD(trigger,     COMMAND, 1, do_trigger)
        KEYWORD(symlink,     COMMAND, 1, do_symlink)
        KEYWORD(sysclktz,    COMMAND, 1, do_sysclktz)
        KEYWORD(user,        OPTION,  0, 0)
        KEYWORD(wait,        COMMAND, 1, do_wait)
        KEYWORD(write,       COMMAND, 2, do_write)
        KEYWORD(copy,        COMMAND, 2, do_copy)
        KEYWORD(chown,       COMMAND, 2, do_chown)
        KEYWORD(chmod,       COMMAND, 2, do_chmod)
        KEYWORD(loglevel,    COMMAND, 1, do_loglevel)
        KEYWORD(load_persist_props,    COMMAND, 0, do_load_persist_props)
        KEYWORD(load_all_props,        COMMAND, 0, do_load_all_props)
        KEYWORD(ioprio,      OPTION,  0, 0)
    #ifdef __MAKE_KEYWORD_ENUM__
        KEYWORD_COUNT,
    }

      builtins.c文件中do_mount_all,启动一个进程调用fs_mgr_read_fstab,fs_mgr_mount_all启动解析,其中systemcorefs_mgr又被vold,adb等模块用来解析fstab.xxx等分区文件。

    (6)根据第三步中指定的分区大小,进行打包对应分区的img文件

        releaseimage.sh, mkimage.sh, build_image.sh, make_usb_upgrade.sh等脚本(vendormstarcommonscripts目录下),会根据第三步设置的大小来制作img文件

             mkimage.sh           

    ...
    function make-images()
    {
        mkdir -p $RELEASE_OUT
        mkdir -p $RELEASE_OUT/scripts
    
        gernerate-script-start
    
        # Raw partition must be first.
        make-raw-partition
        make-split-fs-partition system $BOARD_SYSTEMIMAGE_PARTITION_SIZE true
        make-fs-partition userdata $BOARD_USERDATAIMAGE_PARTITION_SIZE true
        make-fs-partition cache $BOARD_CACHEIMAGE_PARTITION_SIZE true
        make-split-fs-partition vendor $BOARD_VENDORIMAGE_PARTITION_SIZE true
        make-fs-partition tvservice $BOARD_TVSERVICEIMAGE_PARTITION_SIZE false
        make-fs-partition tvconfig $BOARD_TVCONFIGIMAGE_PARTITION_SIZE false
        make-fs-partition tvdatabase $BOARD_TVDATABASEIMAGE_PARTITION_SIZE false
        make-fs-partition tvcustomer $BOARD_TVCUSTOMERIMAGE_PARTITION_SIZE false
        make-fs-partition tvcertificate $BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE false
        if [ "$BOARD_SYSTEMBACKUP" == "true" ]; then
            split-fs-partition systembackup $BOARD_SYSTEMBACKUPIMAGE_PARTITION_SIZE true
        fi
        if [ "$BOARD_CERTIFICATIONIMAGE" == "true" ]; then
            make-fs-partition certificate $BOARD_CERTIFICATEIMAGE_PARTITION_SIZE false
        fi
        # You can make-fs-partition() or make-split-fs-partition() here...
    
      ......
    
    }

       buiild_image.sh

    ......
    #make-fs-partition $PARTITION_NAME $PARTITION_SIZE $PARTITION_ANDROID
    function make-fs-partition()
    {
        echo -e "33[31mMake fs $1 partition...33[0m"
        local PARTITION_NAME=$1
        local PARTITION_SIZE=$2
        local PARTITION_ANDROID=$3
    
        # Generate image
        gernerate-fs-image $PARTITION_NAME $PARTITION_SIZE $PARTITION_ANDROID
    
        release-fs-partition $PARTITION_NAME $PARTITION_SIZE $PARTITION_ANDROID
    }
    .......
    # Generate system/userdate/cache/... image
    function gernerate-fs-image()
    {
        local PARTITION_NAME=$1
        local PARTITION_SIZE=$2
        local PARTITION_ANDROID=$3
    
        if [ "$PARTITION_NAME" == "userdata" ]; then
            local MOUNT_POINT=data
        else
            local MOUNT_POINT=$PARTITION_NAME
        fi
    
        local TARGET_OUT=$PRODUCT_OUT/$MOUNT_POINT
        if [ ! -d "$TARGET_OUT" ]; then
            echo "No $TARGET_OUT directory to gernerate image."
            return
        fi
    
        if [ "$PARTITION_NAME" == "system" -o "$PARTITION_NAME" == "userdata" -o "$PARTITION_NAME" == "cache" -o "$PARTITION_NAME" == "vendor" -o "$PARTITION_NAME" == "systembackup" ]; then
            if [  $PARTITION_NAME == "system" ]; then
                local IMAGE_INFO=$PRODUCT_OUT/obj/PACKAGING/systemimage_intermediates/system_image_info.txt
            else
                local IMAGE_INFO=$PRODUCT_OUT/obj/PACKAGING/"$PARTITION_NAME"_intermediates/"$PARTITION_NAME"_image_info.txt
            fi
    
            generate-userimage-prop-dictionary $IMAGE_INFO
            ./build/tools/releasetools/build_image.py $TARGET_OUT $IMAGE_INFO $PRODUCT_OUT/$PARTITION_NAME.img $PRODUCT_OUT/system
        else
            make_ext4fs -S $SELINUX_FC -l $PARTITION_SIZE -a $MOUNT_POINT $PRODUCT_OUT/$PARTITION_NAME.img $TARGET_OUT
        fi
    }

      最后make_use_upgrade.sh打包,发布整体软件。  

    二、M8386平台新增cusdata、cusparam分区

    (1)device

        device/mstar/sugarcane/BoardConfigCommon.mk

     #18. cm4            (512K)
    +#19. cusdata        (5M)
    +#20. cusparam       (512M)
     BOARD_CM4IMAGE_PARTITION_SIZE           := 0x00080000
    +BOARD_CUSDATA_PARTITION_SIZE            := 0x00500000
    +BOARD_CUSPARAM_PARTITION_SIZE       := 0x20000000

        device/mstar/sugarcane/fstab.m7221

     /dev/block/platform/mstar_mci.0/by-name/tvcertificate   /tvcertificate      ext4      noatime,nosuid,nodev                                  wait,check
    +/dev/block/platform/mstar_mci.0/by-name/cusdata         /cusdata            ext4      noatime,nosuid,nodev                                  wait,check
    +/dev/block/platform/mstar_mci.0/by-name/cusparam        /cusparam           ext4      noatime,nosuid,nodev                                  wait,check

    (2)vendor

        vendor/mstar/common/scripts/build_image.sh

       BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE=$(get_build_var BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE)
      +BOARD_CUSDATA_PARTITION_SIZE=$(get_build_var BOARD_CUSDATA_PARTITION_SIZE)
    +BOARD_CUSPARAM_PARTITION_SIZE=$(get_build_var BOARD_CUSPARAM_PARTITION_SIZE)

        vendor/mstar/common/scripts/make_usb_upgrade.sh

         fullUpgrade=$1
         if [ "$fullUpgrade" == "Y" ]  || [ "$fullUpgrade" == "y" ] ; then
             mainScript=$(grep -Ev "^$|#|%" $AUTO_UPDATE_SCRIPT)
    +    elif [ "$fullUpgrade" == "M" ]  || [ "$fullUpgrade" == "m" ] ; then
    +       #confirm each image is upgrade or not.
    +        mainScript=""
    +        tmp2="
    +"
    +        tmpScript=$(grep "^mstar" $AUTO_UPDATE_SCRIPT | grep "[[")
    +        for mainContent in $tmpScript
    +        do
    +            imageName=$(echo $mainContent | awk '{print $2}' | cut -d '/' -f 2)
    +            if [ "$imageName" != "[[cusdata" ]; then
    +                mainScript=$mainScript$mainContent$tmp2
    +            fi
    +        done
    +        #pad set_config to usb script
    +        tmpScript=$(grep "set_config" $AUTO_UPDATE_SCRIPT)
    +        mainScript=$mainScript$tmpScript
         else
         if [ "$FullUpgrade" == "Y" ];then
             tmp=$FullUpgrade
    +    elif [ "$FullUpgrade" == "M" ];then
    +        tmp=$FullUpgrade

        else

        vendor/mstar/common/scripts/releaseimage.sh

         release-fs-partition tvcustomer $BOARD_TVCUSTOMERIMAGE_PARTITION_SIZE false
    +    make_ext4fs -l $BOARD_CUSDATA_PARTITION_SIZE  $PRODUCT_OUT/cusdata.img $TARGET_OUT
    +    release-fs-partition cusdata $BOARD_CUSDATA_PARTITION_SIZE false
    +    make-split-fs-partition cusparam $BOARD_CUSPARAM_PARTITION_SIZE false
         if [ -n "$BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE" ]; then
             release-fs-partition tvcertificate $BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE false
         fi

        vendor/mstar/common/sepolicy/device.te

     type mstar_tvservice_block_device, dev_type;
    +type mstar_cusdata_block_device, dev_type;
    +type mstar_cusparam_block_device, dev_type;

        vendor/mstar/common/sepolicy/file.te

     type tv_service_file, exec_type, vendor_file_type, file_type;
    +type cusdata_file, file_type;
    +type cusparam_file, file_type;

        vendor/mstar/common/sepolicy/file_contexts

     /tvservice(/.*)?                                       u:object_r:tv_service_file:s0
    +/cusdata(/.*)?                                         u:object_r:cusdata_file:s0
    +/cusparam(/.*)?                                        u:object_r:cusparam_file:s0
     /dev/block/platform/mstar_mci.0/by-name/tvservice       u:object_r:mstar_tvservice_block_device:s0
    +/dev/block/platform/mstar_mci.0/by-name/cusdata       u:object_r:mstar_cusdata_block_device:s0
    +/dev/block/platform/mstar_mci.0/by-name/cusparam       u:object_r:mstar_cusparam_block_device:s0

        vendor/mstar/common/sepolicy_non_treble/device.te

     type mstar_tvservice_block_device, dev_type;
    +type mstar_cusdata_block_device, dev_type;
    +type mstar_cusparam_block_device, dev_type;

        vendor/mstar/common/sepolicy_non_treble/file.te

     type tv_service_file, exec_type, vendor_file_type, file_type;
    +type cusdata_file, file_type;
    +type cusparam_file, file_type;

        vendor/mstar/common/sepolicy_non_treble/file_contexts

     /tvservice(/.*)?                                        u:object_r:tv_service_file:s0
    +/cusdata(/.*)?                                        u:object_r:cusdata_file:s0
    +/cusparam(/.*)?                                        u:object_r:cusparam_file:s0
     /dev/block/platform/mstar_mci.0/by-name/tvservice       u:object_r:mstar_tvservice_block_device:s0
    +/dev/block/platform/mstar_mci.0/by-name/cusdata       u:object_r:mstar_cusdata_block_device:s0
    +/dev/block/platform/mstar_mci.0/by-name/cusparam       u:object_r:mstar_cusparam_block_device:s0

    (3)supernova

         vendor/mstar/supernova/projects/board/m7221/target/dvb/customized.mk

     # define ext4 image size need to less than partition size
     TVSERV_EXT4_SIZE = 0x9D00000
    -TVCFG_EXT4_SIZE = 0xC00000
    +TVCFG_EXT4_SIZE = 0x1000000
     TVCTFC_EXT4_SIZE = 0x800000
     TVCUS_EXT4_SIZE  = 0x1000000
     TVDB_EXT4_SIZE  = 0x800000

      注:如果修改mstar 的supernova 分区的大小,需要在supernova 的 customized.mk 和 BoardConfig.mk 中同时修改大小。

    BOARD_TVSERVICEIMAGE_PARTITION_SIZE     := 0x9D000000
    BOARD_TVCONFIGIMAGE_PARTITION_SIZE      := 0x01000000
    BOARD_TVDATABASEIMAGE_PARTITION_SIZE    := 0x00800000
    BOARD_TVCUSTOMERIMAGE_PARTITION_SIZE    := 0x01000000
    BOARD_TVCERTIFICATEIMAGE_PARTITION_SIZE := 0x00800000
    BOARD_CM4IMAGE_PARTITION_SIZE           := 0x00080000
  • 相关阅读:
    C#学习:异步函数_异步流
    C#异步函数_编写异步函数
    C#学习:异步模式_Task.WhenAny和Task.WhenAll
    C#学习:集合 枚举
    Nginx:通过jdk自制https证书并配置到nginx中
    Boot++:SpringBoot2.x配置HTTPS访问
    git clone一个指定文件或者目录
    Hugo推荐主题
    瓦尔基水冷软件下载地址
    LeetCode 第 298 场周赛
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/13042663.html
Copyright © 2020-2023  润新知