orangpione利用usb共享網(wǎng)絡(luò)(RNDIS)實(shí)現(xiàn)tftp加載內(nèi)核掛載到NFS根文件系統(tǒng)

https://www.mobileread.com/forums/showthread.php?p=3283986

目錄結(jié)構(gòu)說明

一、環(huán)境說明

1、環(huán)境介紹

2、RNDIS介紹

3、網(wǎng)絡(luò)環(huán)境配置

4、編譯腳本說明

二、uboot的RNDIS測試

1、配置編譯uboot的RNDIS功能

2、測試uboot的RNDIS網(wǎng)絡(luò)是否正常

三、kernel的RNDIS測試

1、配置編譯kernel的RNDIS功能

2、測試kernel的RNDIS網(wǎng)絡(luò)是否正常

3、測試kernel的RNDIS網(wǎng)絡(luò)的nfs功能是否正常

四、綜合測試RNDIS網(wǎng)絡(luò)

1、通過uboot手動(dòng)測試tftp加載kernel啟動(dòng)

2、通過uboot手動(dòng)測試tftp加載kernel掛載nfs啟動(dòng)

3、把測試啟動(dòng)的nfs命令轉(zhuǎn)換成boot.scr啟動(dòng)腳本

一、環(huán)境說明

1、環(huán)境介紹

?? 首先這里我們需要安裝一些基礎(chǔ)的編譯環(huán)境,安裝tftp服務(wù)器,安裝nfs服務(wù)器等,這里我們可以參考文章《用buildroot編譯整個(gè)系統(tǒng),用qemu仿真vexpressa9》中的環(huán)境準(zhǔn)備章節(jié),自行安裝相關(guān)服務(wù),在這里不展開。

2、RNDIS介紹

?? RNDIS是指Remote NDIS,基于USB實(shí)現(xiàn)RNDIS實(shí)際上就是TCP/IP over USB,就是在USB設(shè)備上跑TCP/IP,讓USB設(shè)備看上去像一塊網(wǎng)卡。簡單的來說,就是通過USB模擬了一個(gè)網(wǎng)卡,這樣我們可以通過這個(gè)網(wǎng)卡實(shí)現(xiàn)和虛擬機(jī)的聯(lián)機(jī),以及正常的網(wǎng)絡(luò)訪問。相關(guān)內(nèi)容可以參考網(wǎng)站https://zhidao.baidu.com/question/1930394656632188907.html

3、網(wǎng)絡(luò)環(huán)境配置

?? 1、這里我們實(shí)現(xiàn)的網(wǎng)絡(luò)環(huán)境配置如下圖所示。在win10主機(jī)上虛擬一個(gè)網(wǎng)橋,win10主機(jī)和Ubuntu虛擬機(jī)通過這個(gè)網(wǎng)橋連接到無線網(wǎng)絡(luò),訪問外網(wǎng)。同時(shí)orangepione開發(fā)板則通過USB實(shí)現(xiàn)與win10主機(jī)的RNDIS網(wǎng)絡(luò)共享。通過主機(jī)訪問外網(wǎng)。

網(wǎng)絡(luò)環(huán)境配置

?? 2、通過win10的hyperv創(chuàng)建虛擬網(wǎng)橋,把虛擬機(jī)的網(wǎng)絡(luò)和主機(jī)的網(wǎng)絡(luò)通過網(wǎng)橋橋接起來。在hyperv管理器上面找的虛擬交換機(jī)管理器,并點(diǎn)擊新建虛擬交換機(jī)網(wǎng)絡(luò),這里名字隨意就好,我這里的名字叫做hyper-net,相關(guān)配置如下圖所示,這里要選擇一個(gè)可以上外網(wǎng)的網(wǎng)卡進(jìn)行橋接
hyperv交換機(jī)

?? 3、在編譯好后,在開發(fā)板上電并進(jìn)行網(wǎng)絡(luò)通信的時(shí)候會(huì)在設(shè)備管理器出現(xiàn)RNDIS相管的提示信息,如果沒有驅(qū)動(dòng),則按照https://www.mobileread.com/forums/showthread.php?p=3283986網(wǎng)址上的驅(qū)動(dòng)方式對RNDIS進(jìn)行驅(qū)動(dòng),先下載kindle_rndis.inf_amd64-v1.0.0.1.zip并解壓,再執(zhí)行第5個(gè)cmd腳本注冊驅(qū)動(dòng)簽名,然后再設(shè)備管理器更新驅(qū)動(dòng)管理程序,選擇下載的驅(qū)動(dòng)目錄進(jìn)行驅(qū)動(dòng),如果驅(qū)動(dòng)成功,則在設(shè)備管理器會(huì)顯示下面的驅(qū)動(dòng)
RNDIS驅(qū)動(dòng)

??4、設(shè)置和主機(jī)的網(wǎng)絡(luò)共享,在驅(qū)動(dòng)成功后,需要在更改適配器選項(xiàng)界面,設(shè)置共享配置,這里選擇共享的是之前hyperv橋接的網(wǎng)卡,這里建議把hyperv橋接網(wǎng)卡的ip設(shè)置為靜態(tài)ip,后面共享的網(wǎng)卡需要通過該網(wǎng)卡的ip進(jìn)行dns解析,配置如下圖所示
這里如果配置不成功,后面會(huì)不能正常通訊
共享網(wǎng)絡(luò)配置

4、編譯腳本說明

這里我們和還是使用文章《用buildroot編譯整個(gè)系統(tǒng),用qemu仿真vexpressa9》提到的buildroot環(huán)境進(jìn)行開發(fā)。但是我們這里稍微改變了一下在orangepione目錄下的腳本build.sh,腳本的主要功能是編譯,和拷貝文件到tftp目錄,以及修改生成boot.scr文件,可能需要根據(jù)實(shí)際的情況進(jìn)行相關(guān)的調(diào)整

#! /bin/bash
NPWD=`realpath .`
echo $NPWD
if [ $1_x == cp_x ];then
        cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/zImage ~/tftp
        cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/dts/sun8i-h3-orangepi-one.dtb ~/tftp
elif [ $1_x == env_x ];then
        /home/vencol/code/buildroot/host/bin/mkimage -C none -A arm -T script -d $NPWD/boot.cmd $NPWD/boot.scr
        cp $NPWD/boot.scr $NPWD/rootfs/images/boot.scr
else
        cd $NPWD/../buildroot
        mkdir -p $NPWD/rootfs
        make O=$NPWD/rootfs ARCH=arm $1
fi

二、uboot的RNDIS測試

1、配置編譯uboot的RNDIS功能

  1. 在orangepi目錄執(zhí)行./build.sh uboot-menuconfig會(huì)彈出uboot的menuconfig的配置界面,我們的配置選項(xiàng)如下 Device Drivers --->USB support --->

EHCI HCD (USB 2.0) support --->CONFIG_USB_EHCI_HCD
Support for generic EHCI USB controller--->CONFIG_USB_EHCI_GENERIC
MUSB gadget mode support--->CONFIG_USB_MUSB_GADGET
Enable sunxi OTG / DRC USB controller--->CONFIG_USB_MUSB_SUNXI
Disable MUSB bulk split/combine--->CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
Disable DMA (always use PIO)--->CONFIG_USB_MUSB_PIO_ONLY
USB Gadget Support--->CONFIG_USB_GADGET

(0x0525) Vendor ID of the USB device--->CONFIG_USB_GADGET_VENDOR_NUM
(0xA4A2) Product ID of the USB device--->CONFIG_USB_GADGET_PRODUCT_NUM
USB Ethernet Gadget--->CONFIG_USB_ETHER
USB Ethernet Gadget Model (RNDIS Protocol)--->CONFIG_USB_ETH_RNDIS
(de:ad:be:ef:00:01) USB Gadget Ethernet device mac address--->CONFIG_USBNET_DEVADDR
(de:ad:be:ef:00:00) USB Gadget Ethernet host mac address--->CONFIG_USBNET_HOST_ADDR

  1. 配置完成后,使用腳本命令./build.sh -j4進(jìn)行uboot編譯,如無意外,則可以正常編譯通過,通過orangpi相關(guān)燒錄指引,把sdcard.img燒錄到sd卡中
  2. 燒錄完成后,插入sd卡。連接調(diào)試串口,并啟動(dòng)orangepi,在uboot3s后輸入空格停下啟動(dòng)信息,如下圖所示


    stop uboot

2、測試uboot的RNDIS網(wǎng)絡(luò)是否正常

  1. 在uboot停止的頁面輸入下面的內(nèi)容
usb start
setenv ethact usb_ether
setenv ipaddr 192.168.137.2
setenv netmask 255.255.255.0
setenv gatewayip 192.168.137.1
saveenv
ping 192.168.1.111
  1. 這里ping的ip是虛擬機(jī)的ip地址,需要查看uboot是否可以和虛擬機(jī)通訊,如果出現(xiàn)下圖類似情況ip is alive則通訊成功


    ping

三、kernel的RNDIS測試

1、配置編譯kernel的RNDIS功能

  1. 在orangepi目錄執(zhí)行./build.sh linux-menuconfig會(huì)彈出kernel的menuconfig的配置界面,我們的配置選項(xiàng)如下
    RNDIS選項(xiàng)的配置 (這里一開始我們先配置為模塊,調(diào)用g_ether.ko,調(diào)試通過后再編譯進(jìn)內(nèi)核)Device Drivers --->USB support --->
Support for Host-side USB--->CONFIG_USB
Enable USB persist by default--->CONFIG_USB_DEFAULT_PERSIST
EHCI HCD (USB 2.0) support--->CONFIG_USB_EHCI_HCD
Improved Transaction Translator scheduling--->CONFIG_USB_EHCI_TT_NEWSCHED
Generic EHCI driver for a platform device--->CONFIG_USB_EHCI_HCD_PLATFORM
OHCI HCD (USB 1.1) support--->CONFIG_USB_OHCI_HCD
Generic OHCI driver for a platform device--->CONFIG_USB_OHCI_HCD_PLATFORM
Inventra Highspeed Dual Role Controller--->CONFIG_USB_MUSB_HDRC
MUSB Mode Selection (Gadget only mode)--->CONFIG_USB_MUSB_GADGET
Allwinner (sunxi)--->USB_MUSB_SUNXI
USB Gadget Support--->CONFIG_USB_GADGET
USB Gadget precomposed configurations--->
Ethernet Gadget (with CDC Ethernet support)--->CONFIG_USB_ETH
RNDIS support--->CONFIG_USB_ETH_RNDIS

NFS網(wǎng)絡(luò)選項(xiàng)的配置 Networking support --->Networking options --->

TCP/IP networking--->CONFIG_INET
IP: kernel level autoconfiguration--->CONFIG_IP_PNP
IP: DHCP support--->CONFIG_IP_PNP_DHCP
IP: BOOTP support--->CONFIG_IP_PNP_BOOTP

NFS文件系統(tǒng)選項(xiàng)的配置 File systems --->Network File Systems --->

NFS client support--->CONFIG_NFS_FS
NFS client support for NFS version 2--->CONFIG_NFS_V2
NFS client support for NFS version 3--->CONFIG_NFS_V3
NFS client support for the NFSv3 ACL protocol extension--->CONFIG_NFS_V3_ACL
NFS client support for NFS version 4--->CONFIG_NFS_V4
Root file system on NFS--->CONFIG_ROOT_NFS
  1. 通過源碼修改kernel的ubs0網(wǎng)卡地址,因?yàn)槿绻恍薷牡刂?,每次重啟都?huì)產(chǎn)生一個(gè)隨機(jī)的網(wǎng)卡地址,那么win10這邊識(shí)別的就不是前面設(shè)置的共享網(wǎng)卡了,這里我們需要把網(wǎng)卡設(shè)置成和uboot的網(wǎng)卡地址一樣,這里我么需要修改的文件是,kernel源碼下面的u_ether.c文件的gether_setup_name_default函數(shù)添加usb網(wǎng)卡的判斷,當(dāng)識(shí)別到usb網(wǎng)卡的時(shí)候,設(shè)置其默認(rèn)的host地址為de:ad:be:ef:00:00,dev地址為de:ad:be:ef:00:01
 837     snprintf(net->name, sizeof(net->name), "%s%%d", netname);
 838
 839     if(memcmp(netname, "usb", 3) == 0)
 840     {
 841         eth_random_addr(dev->dev_mac);
 842         pr_warn("using usb my random %s ethernet address\n", "self");
 843         eth_random_addr(dev->host_mac);
 844         pr_warn("using usb my %s ethernet address\n", "host");
 845         dev->host_mac[0] = 222;
 846         dev->host_mac[1] = 173;
 847         dev->host_mac[2] = 190;
 848         dev->host_mac[3] = 239;
 849         dev->host_mac[4] = 0;
 850         dev->host_mac[5] = 0;
 851
 852         dev->dev_mac[0] = 222;
 853         dev->dev_mac[1] = 173;
 854         dev->dev_mac[2] = 190;
 855         dev->dev_mac[3] = 239;
 856         dev->dev_mac[4] = 0;
 857         dev->dev_mac[5] = 1;
 858     }
 859     else
 860     {
 861         eth_random_addr(dev->dev_mac);
 862         pr_warn("using random %s ethernet address\n", "self");
 863         eth_random_addr(dev->host_mac);
 864         pr_warn("using random %s ethernet address\n", "host");
 865     }
  1. 配置修改完成后,使用腳本命令./build.sh -j4進(jìn)行uboot編譯,如無意外,則可以正常編譯通過,通過orangpi相關(guān)燒錄指引,把sdcard.img燒錄到sd卡中

2、測試kernel的RNDIS網(wǎng)絡(luò)是否正常

  1. 重新上電后,等等其加載mmc的根文件系統(tǒng),加載成功后登陸系統(tǒng),通過命令modprobe g_ether加載模塊驅(qū)動(dòng),如果加載成功,會(huì)出現(xiàn)類似的信息
[    1.526195] usb0: HOST MAC de:ad:be:ef:00:00
[    1.530505] usb0: MAC de:ad:be:ef:00:01
[    1.534355] using usb my random self ethernet address
[    1.539399] using usb my host ethernet address
[    1.543905] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
[    1.550519] g_ether gadget: g_ether ready
  1. 通過ifconfig -a查看是否存在usb0網(wǎng)卡,如果存在usb0網(wǎng)卡,說明網(wǎng)卡正常驅(qū)動(dòng)
  2. 啟動(dòng)usb0網(wǎng)卡且對其進(jìn)行配置ifconfig usb0 up && ifconfig usb0 192.168.137.2 netmask 255.255.255.0
  3. 配置默認(rèn)網(wǎng)關(guān)route add default gw 192.168.137.1
  4. 測試是否可以ping通虛擬機(jī)ping 192.168.1.111,如果正常ping通說明網(wǎng)絡(luò)成功通訊
  5. 通過命令/etc/network/nfs_check創(chuàng)建網(wǎng)卡啟動(dòng)時(shí)對nfs的檢查文件
#!/bin/sh

# This allows NFS booting to work while also being able to configure
# the network interface via DHCP when not NFS booting.  Otherwise, a
# NFS booted system will likely hang during DHCP configuration.

# Attempting to configure the network interface used for NFS will
# initially bring that network down.  Since the root filesystem is
# accessed over this network, the system hangs.

# This script is run by ifup and will attempt to detect if a NFS root
# mount uses the interface to be configured (IFACE), and if so does
# not configure it.  This should allow the same build to be disk/flash
# booted or NFS booted.

nfsip=`sed -n '/^[^ ]*:.* \/ nfs.*[ ,]addr=\([0-9.]\+\).*/s//\1/p' /proc/mounts`
if [ -n "$nfsip" ] && ip route get to "$nfsip" | grep -q "dev $IFACE"; then
        echo Skipping $IFACE, used for NFS from $nfsip
        exit 1
fi
  1. 通過命令vi /etc/network/interfaces添加usb0網(wǎng)卡開機(jī)自動(dòng)掛載
auto usb0
iface usb0 inet static
pre-up /etc/network/nfs_check
address 192.168.137.2
netmask 255.255.255.0
gateway 192.168.137.1
#dns-nameservers 8.8.8.8 192.168.137.1 211.136.20.203
  1. 通過命令vi /etc/resolv.conf配置dns服務(wù)器,注意resolv.conf文件不能是鏈接文件
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 192.168.137.1

3、測試kernel的RNDIS網(wǎng)絡(luò)的nfs功能是否正常

  1. 在虛擬機(jī)服務(wù)器端開啟nfs服務(wù)
  2. 在虛擬機(jī)通過命令ln -s nfsroot nfs創(chuàng)建nfs文件的的軟連接,nfsroot是實(shí)際的根文件系統(tǒng)目錄,而后面的nfs是創(chuàng)建的軟連接目錄
  3. 在虛擬機(jī)通過命令sudo vi /etc/exports修改文件內(nèi)容,添加類似的內(nèi)容/home/vencol/code/nfs *(insecure,rw,sync,no_root_squash,no_subtree_check)
  4. 在虛擬機(jī)通過命令sudo /etc/init.d/nfs-kernel-server restart重啟nfs服務(wù)
  5. 在開發(fā)創(chuàng)建nfsdir目錄,并且通過命令mount -t nfs -o nolock 192.168.1.111:/home/vencol/code/nfs nfsdir,如果掛載成功通過ls nfsdir則可以看到nfs根文件系統(tǒng)的內(nèi)容。

四、綜合測試RNDIS網(wǎng)絡(luò)

1、通過uboot手動(dòng)測試tftp加載kernel啟動(dòng)

  1. 由于前面我們使用了saveenv命令來保存uboot的環(huán)境參數(shù),所以這里我們只要沒有重新燒錄,都可以不用再次設(shè)置,如果需要設(shè)置,請參考【測試uboot的RNDIS網(wǎng)絡(luò)是否正常】章節(jié)內(nèi)容
  2. 我們在虛擬機(jī)上通過執(zhí)行./build.sh cp命令把zImage和sun8i-h3-orangepi-one.dtb設(shè)備樹文件拷貝到我們的tftp服務(wù)器目錄下。
  3. 我們在開發(fā)板上設(shè)置bootargs參數(shù)為setenv bootargs "console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait"并且通過saveenv保存該參數(shù)
  4. 在開發(fā)板上,使用tftp 0x42000000 zImage加載zimage到內(nèi)存,通過tftp 0x43000000 sun8i-h3-orangepi-one.dtb加載設(shè)備樹到內(nèi)存
  5. 在開發(fā)板上,通過bootz 0x42000000 - 0x43000000啟動(dòng)內(nèi)核,如無意外,可以成功進(jìn)入登錄界面,但是這時(shí)加載的是mmc根文件系統(tǒng),下面我們開始加載nfs文件系統(tǒng)

2、通過uboot手動(dòng)測試tftp加載kernel掛載nfs啟動(dòng)

  1. 在前面已經(jīng)可以正常加載mmc根文件系統(tǒng)的前提下,進(jìn)行nfs文件系統(tǒng)的加載
  2. 在uboot界面停下,由于前面保存了相關(guān)的環(huán)境變量,這里我們直接進(jìn)行bootargs參數(shù)的修改,通過命令修改bootargs參數(shù)為,setenv bootargs root=/dev/nfs rw rootpath=/home/vencol/code/nfs nfsroot=192.168.1.111:/home/vencol/code/nfs,nolock ip=192.168.137.2:192.168.1.111:192.168.137.1:255.255.255.0 console=ttyS0,115200 nfsvers=2這里的rootpath是虛擬機(jī)上nfs根文件的地址,而ip則是根據(jù)我們的實(shí)際情況設(shè)置,由于這里虛擬機(jī)和開發(fā)板不在同一網(wǎng)段,所以需要填寫網(wǎng)關(guān)和掩碼信息
  3. 在開發(fā)板上,使用tftp 0x42000000 zImage加載zimage到內(nèi)存,通過tftp 0x43000000 sun8i-h3-orangepi-one.dtb加載設(shè)備樹到內(nèi)存
  4. 在開發(fā)板上,通過bootz 0x42000000 - 0x43000000啟動(dòng)內(nèi)核,如無意外,可以成功進(jìn)入登錄界面,但是這時(shí)加載的是mmc根文件系統(tǒng),下面我們開始加載nfs文件系統(tǒng)
  5. 出現(xiàn)問題排查

1.nfs服務(wù)器端的傳輸協(xié)議是否和開發(fā)版客戶端的協(xié)議一致,如果不一致,在bootargs添加nfsserver=2,這里2是nfs2的意思,對應(yīng)版本即可

  1. 查看nfs根文件系統(tǒng)中的/dev目錄是否存在,/dev/console和/dev/null,如果不存在通過下面命令創(chuàng)建
    sudo mknod console c 5 1 //創(chuàng)建console字符設(shè)備,
    sudo mknod null c 1 3 //創(chuàng)建null 字符設(shè)備,
    sudo chown 1000:1000 console null```
  2. 在源碼文件init/do_mounts.c的do_mount_root函數(shù)中調(diào)用的do_mount函數(shù)返回的錯(cuò)誤打印出來,查看錯(cuò)誤碼是什么,如果錯(cuò)誤碼為-93,那么就是服務(wù)器版本不對,這里有可能是下面4這點(diǎn)的問題。在服務(wù)器端用nfsstat -s查看版本,如果是其他錯(cuò)誤可以參考/var/log/syslog中nfs的輸出日志。
  3. 低版本uboot和高版本ubuntu搭配進(jìn)行開發(fā)時(shí),發(fā)現(xiàn)nfs不能使用.uboot默認(rèn)啟動(dòng)協(xié)議為2.而高版本的ubuntu17之后nfs就默認(rèn)支持3和4,因此需要ubuntu支持協(xié)議2。在文件/etc/default/nfs-kernel-server末尾添加RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog",然后重啟nfs服務(wù)。

3、把測試啟動(dòng)的nfs命令轉(zhuǎn)換成boot.scr啟動(dòng)腳本

  1. boot.scr是通過mkimage工具生成的,這里我們需要先拷貝buildroot中orangepione的boot.cmd文件到腳本目錄,在這個(gè)文件的基礎(chǔ)上進(jìn)行修改,其目錄在buildroot/board/orangepi/orangepi-one/boot.cmd
  2. 修改boot.cmd文件如下,其中rootdelay=3看具體情況使用
setenv fdt_high ffffffff
usb start
setenv ethact usb_ether
setenv ipaddr 192.168.137.2
setenv gatewayip 192.168.137.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.111
#setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
setenv bootargs root=/dev/nfs rw rootpath=/home/vencol/code/nfs nfsroot=192.168.1.111:/home/vencol/code/nfs,nolock ip=192.168.137.2:192.168.1.111:192.168.137.1:255.255.255.0 console=ttyS0,115200 nfsvers=2 rootdelay=3

tftp $kernel_addr_r zImage
tftp $fdt_addr_r sun8i-h3-orangepi-one.dtb
bootz $kernel_addr_r - $fdt_addr_r

#fatload mmc 0 $kernel_addr_r zImage
#fatload mmc 0 $fdt_addr_r sun8i-h3-orangepi-one.dtb
#bootz $kernel_addr_r - $fdt_addr_r
  1. 通過腳本命令./build.sh env生成boot.scr文件在當(dāng)前目錄中
  2. 把boot.scr文件拷貝到nfs目錄的root目錄下
  3. 在開發(fā)板已經(jīng)正常進(jìn)入mmc根文件系統(tǒng)的情況下,掛載nfs目錄到nfsdir目錄中
  4. 通過命令mount /dev/mmcblk0p1 /mnt/fat/掛載boot分區(qū)到/mnt/fat/
  5. 把nfs目錄的boot.scf拷貝到boot分區(qū)cp nfsdir/root/boot.scr /mnt/fat
  6. 確認(rèn)boot分區(qū)的boot.scr文件更新后,卸載boot分區(qū),并重啟umount /mnt/fat && reboot
    如無意外,則可以看到類似的掛nfs信息出現(xiàn)
    nfs

:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容