fl2440最小系统移植

本文详细介绍了如何在Fl2440开发板上进行Linux系统的移植工作,通过使用u-boot实现系统的重新启动。内容涉及Linux内核配置、根文件系统的构建等关键步骤。
摘要由CSDN通过智能技术生成
文章为作者原创,转载请附明原地址:https://mp.csdn.net/postedit/78514501

 Linux系统在执行一条命令时,默认会到/bin、/sbin、/usr/bin、/usr/sbin这些路径下找,如果找不到则提示 command not found ,当然我们也可以
通过 PATH环境变量 告诉系统其它命令存放的路径。现在根文件系统树下这些路径里并没有Linux系统相关命令。
 
[shun@localhost ~]$ cd ~/fl2440/
[shun@localhost fl2440]$ ls
3rdparty  bootloader  crosstool  driver  images  linux  program
[shun@localhost fl2440]$ cd 3rdparty/ 
[shun@localhost 3rdparty]$ tar -xjf busybox-1.27.1.tar.bz2
[shun@localhost 3rdparty]$ cd busybox-1.27.1
[shun@localhost busybox-1.27.1]$ ls
applets                 coreutils    loginutils              README
applets_sh              debianutils  mailutils               runit
arch                    docs         Makefile                scripts
archival                e2fsprogs    Makefile.custom         selinux
AUTHORS                 editors      Makefile.flags          shell
busybox                 examples     Makefile.help           sysklogd
busybox.links           findutils    make_single_applets.sh  testsuite
busybox_unstripped      include      miscutils               TODO
busybox_unstripped.map  init         modutils                TODO_unicode
busybox_unstripped.out  INSTALL      networking              util-linux
Config.in               libbb        printutils
configs                 libpwdgrp    procps
console-tools           LICENSE      qemu_multiarch_testing
[shun@localhost busybox-1.27.1]$ make menuconfig           #然后进行相应的设置

1、编译并安装busybox:
[shun@localhost busybox-1.27.1]$ make &&  make install

切换到根文件系统树路径下,创建符号链接指向busybox程序:
[shun@localhost busybox-1.27.1]$ cd ../../linux/rootfs/
[shun@localhost rootfs]$ ls
apps  bin  data  dev  etc  info  lib  linuxrc  mnt  proc  root  sbin  sys  tmp  usr  var
[shun@localhost rootfs]$ ln -s bin/b
base64   busybox  
[shun@localhost rootfs]$ ln -s bin/busybox init
[shun@localhost ro otfs]$ ls
apps  bin  data  dev  etc  info  init  lib  linuxrc  mnt  proc  root  sbin  sys  tmp  usr  var

列出根文件系统目录树下的Linux命令,这些命令其实都是符号链接到busybox:
[shun@localhost busybox-1.27.1]$ ls ../../linux/rootfs/bin/
ash      cttyhack       fatattr   iostat    lzop        nice           rpm           su
base64   date           fdflush   ipcalc    mkdir       pidof          run-parts     sync
busybox  dd             fgrep     kbd_mode  mknod       ping           scriptreplay  tar
cat      df             fsync     kill      mktemp      ping6          sed           touch
chattr   dmesg          getopt    link      more        pipe_progress  setarch       true
chgrp    dnsdomainname  grep      linux32   mount       printenv       setpriv       umount
chmod    dumpkmap       gunzip    linux64   mountpoint  ps             setserial     uname
chown    echo           gzip      ln        mpstat      pwd            sh            usleep
conspy   ed             hostname  login     mt          rev            sleep         vi
cp       egrep          hush      ls        mv          rm             stat          watch
cpio     false          ionice    lsattr    netstat     rmdir          stty          zcat
[shun@localhost busybox-1.27.1]$

2、创建/dev路径下的设备节点

  Linux下所有的东西都是文件,其中设备也是当作文件来处理。/dev路径下存放所有的Linux的设备文件,我们需要使用root权限执行mknod命令在这
里创建系统启动必须的设备文件节点,其他的设备节点将有mdev动态创建。

[shun@localhost ~]$ cd fl2440/linux/rootfs/
[shun@localhost rootfs]$ ls
apps  bin  data  dev  etc  info  init  lib  linuxrc  mnt  proc  root  sbin  sys  tmp  usr  var
[shun@localhost rootfs]$ sudo mknod -m666 dev/null c 1 3
[shun@localhost rootfs]$ sudo mknod -m666 dev/console c 5 1
[shun@localhost rootfs]$ sudo mknod -m666 dev/ttyS0 c 4 64
[shun@localhost rootfs]$ ls -l dev/
total 0
crw-rw-rw-. 1 root root 5,  1 Nov  6 21:03 console
crw-rw-rw-. 1 root root 1,  3 Nov  6 21:03 null
crw-rw-rw-. 1 root root 4, 64 Nov  6 21:04 ttyS0
[shun@localhost rootfs]$
[shun@localhost rootfs]$

3、创建/var路径下的文件

[shun@localhost rootfs]$ ln -s /tmp var/log
[shun@localhost rootfs]$ ln -s /tmp var/run
[shun@localhost rootfs]$ ln -s /tmp var/tmp
[shun@localhost rootfs]$ ls -l var/
total 0
lrwxrwxrwx. 1 shun shun 4 Nov  6 21:08 lock -> /tmp
lrwxrwxrwx. 1 shun shun 4 Nov  6 21:08 log -> /tmp
lrwxrwxrwx. 1 shun shun 4 Nov  6 21:08 run -> /tmp
lrwxrwxrwx. 1 shun shun 4 Nov  6 21:09 tmp -> /tmp
[shun@localhost rootfs]$

4、创建/etc路径下文件 
   1)创建/etc/inittab 文件
Linux内核自举启动完成之后,最后将创建init进程并执行根文件系统中的/init或/initrc程序,该程序解析并执行/etc/inittab配置文件,在此文件中配置
了init进程在系统启动要启动哪些应用程序。

[shun@localhost rootfs]$ vim etc/inittab

# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id == tty to run on, or empty for /dev/console.
#       If specified, then /dev/$id device must exist
# runlevels == ignored, busybox doesn't support it
# action == one of sysinit, respawn, askfirst, wait, and once
# process == program to run
# Startup the system
# mount all the file systems specified in /etc/fstab
::sysinit:/bin/mount -a
# Use mdev to auto generate device nod and auto mount SD card and USB storage
::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
::sysinit:/sbin/mdev -s
#make shm, pts support
::sysinit:/bin/mkdir -p /dev/pts
::sysinit:/bin/mkdir -p /dev/shm
::sysinit:/bin/mount -t devpts devpts /dev/pts
#Set hostname
null::sysinit:/bin/hostname -F /etc/hostname
#Enable console logon
null::respawn:/sbin/getty -L ttyS0 115200 vt100
# now run any rc scripts, which used to start other application
null::wait:/etc/init.d/rcS
# system daemon
null::respawn:/sbin/syslogd -n
null::respawn:/sbin/klogd -n
# Stuff to do before rebooting
null::shutdown:/bin/killall klogd
null::shutdown:/bin/killall syslogd
null::shutdown:/bin/umount -a -r
"etc/inittab" [New] 30L, 1132C written

2)创建/etc/fstab 文件

Linux下的mount -a命令将自动挂载/etc/fstab文件中指定的所有需要系统自动挂载的文件。在/etc/inittab中会使用该命令在上电时自动挂载相应的文件
系统,这里面主要是挂载一些伪文件系统,这些伪文件系统主要是导出Linux内核运行的相关信息,如比较重要的tmpfs、sysfs、proc文件系统等。

[shun@localhost rootfs]$ vim etc/fstab

# /etc/fstab: static file system information.
#
# <file system> <mount pt> <type> <options> <dump> <pass>
/dev/root / ext2 rw,noauto 0 1
proc /proc proc defaults 0 0
usbfs /proc/bus/usb usbfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
ramfs /tmp ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0

3)创建hostname文件
/etc/hostname 文件指定主机名,/etc/inittab文件中通过 hostname -F /etc/hostname 命令设置主机名

[shun@localhost rootfs]$ vim etc/hostname
LiuShunFL2440
~
"etc/hostname" [New] 1L, 14C written

4)创建系统启动文件脚本
系统所有的启动脚本我们都将放在/etc/init.d路径下,接下来我们将创建这些系统启动脚本:

启动脚本一、 /etc/init. d/rcS
/etc/inittab 脚本会使用命令 /etc/init.d/rcS 启动所有其它的应用程序,下面创建 etc/rcS 脚本,该 脚本将执行 /etc/init.d/ 下所有文件名以 S开头且后面紧
跟至少包括2个字符 的文件
[shun@localhost rootfs]$ cd etc/init.d/
[shun@localhost init.d]$ ls
[shun@localhost init.d]$ vim rcS

#!/bin/sh
# Copyright (C) 2012 LingYun I.o.T Studio < iot-yun.com >
# Start all scripts in /etc/init.d, executing them in numerical order.
for i in /etc/init.d/S??* ; do
    $i
done
~
"rcS" [New] 6L, 182C written
[shun@localhost init.d]$
需要给该脚本执行的权限才能执行:

[shun@localhost init.d]$ chmod a+x rcS

启动脚本二、 /etc/init. d/S1 0_network
假设我们希望 系统启动时自动设置网卡的IP地址 ,则可以创建一个 文件名以S开头且后面紧跟至少包括2个字符的启动脚本 ,并给执行权限。

[shun@localhost init.d]$ vim S10_network

#!/bin/sh
fconfig eth0 192.168.1.250 netmask 255.255.255.0 up
[shun@localhost init.d]$ chmod a+x S10_network

启动脚本三、 /etc/init. d/S9 9_rcsApp
今后我们很多应用程序将会存放在/apps分区下,有时我们希望这些应用程序的启动脚本也存放在该分区下以便于管理。这时我们可以 参考rcS脚本的实现
机制,让它也执行在/apps/etc下的所有启动脚本
[shun@localhost init.d]$ vim S99_rcsApp
#!/bin/sh
# Copyright (C) 2012 LingYun I.o.T Studio < iot-yun.com >
# Start all scripts in /apps/etc/init.d, executing them in numerical order.
for i in /apps/etc/init.d/S??* ; do
$i
done
[shun@localhost init.d]$ chmod a+x S99_rcsApp
[shun@localhost init.d]$ ls
rcS  S10_network  S99_rcsApp

5)创建shell的配置文件
在Linux服务器上,我们可以通过修改 ~/.bash_profile ~/.bashrc 文件来修改Shell的配置文件,如修改 PATH、LD_LIBRARY_PATH 环境变量等,也
可以在里面定义命令别名。 在嵌入式环境下,我们这些Shell的配置保存在 /etc/profile 文件中。这时我们可以创建该文件配置嵌入式环境busybox里的
shell( ash )。
[shun@localhost init.d]$ cd ..
[shun@localhost etc]$ ls
fstab  hostname  init.d  inittab
[shun@localhost etc]$ vim profile
# Busybox Shell(ash) configure file
export PATH=/bin:sbin:/usr/bin:/usr/sbin:/apps/bin:/apps/tools
export PS1='\w >: '
export USER=`id -un`
export LOGNAME=$USER
export HOSTNAME=`/bin/hostname`
export HISTSIZE=500
export HISTFILESIZE=500
export PAGER='/bin/more'
export EDITOR='/bin/vi'
export INPUTRC=/etc/inputrc
export LD_LIBRARY_PATH=/lib:/usr/lib:/apps/lib
export network_cfg_dir=/apps/etc/network
### Some alias command
alias vim='vi'
alias ll='ls -l'
alias l.='ls -d .*'
alias df='df -h'
~
6) 创建Linux登录帐号文件

Linux系统中的登录帐号信息保存在/etc/group、/etc/passwd和/etc/shadow文件中。
/etc/group文件保存了用户组信息;
/etc/passwd文件保存了用户信息;
/etc/shadow文件保存来相应用户的密码;
下面我们需要在根文件系统中创建这些系统帐号文件,在这里我们只创建root帐号,其他帐号的过程类似。当然也可以在系统启动后以root帐号权限来添

     /et c/group文件:

[shun@localhost etc]$ vim group
root:x:0:root
该文件的格式为:
groupname :password: gid :members
第一个字段为用户组名称;
第二个字段为用户组密码,当为x时密码是映射到/etc/gshadow中的,是非逆的;
第三个字段为GID,及组号,为正整数或0,0被付于了root用户组;系统通常会预留一些较靠前的GID给系统虚拟用户之用,每个系统预留的GID都
不同,一般普通用户的GID从500开始;
第四个字段为用户列表,每个用户间用逗号分隔;
    
     /et c/passwd文件

[shun@localhost etc]$ vim passwd
root:x:0:0:root:/:/bin/sh

文件的格式为:
username :password: uid :gid: fullname :homedir: shell
第一个字段为登录用户名
第二个字段为密码,这里设置为 x 表示密码被映射到 /etc/shadow 文件中
第三个字段为用户ID(UID)
第四个字段为用户所属组ID(GID)
第五个字段为用户名全称
第六个字段为用户根目录
第七个字段为用户所用shell的类型
Unix系统最初是用明文保存密码的,后来由于安全的考虑,采用crypt()算法加密密码并存放在/etc/passwd文件。现在,由于计算机处理能力的提高,使
密码破解变得越来越容易。/etc/passwd文件是所有合法用户都可访问的,大家都可互相看到密码的加密字符串,这给系统带来很大的安全威胁。现代的
Unix系统使用影子密码系统,它把密码从/etc/passwd文件中分离出来,真正的密码保存在/etc/shadow文件中,shadow文件只能由超级用户访问。这样
入侵者就不能获得加密密码串,用于破解。使用shadow密码文件后,/etc/passwd文件中所有帐户的password域的内容为"x",如果password域的内容
为"*",则该帐号被停用。

    /et c/shadow文件
etc/shadow文件保存了相应帐号的密文,这个文件内容不能直接创建。如果我们想在嵌入式Linux系统中设置root的登录密码为123456,则我们先在自
己的Linux服务器或虚拟机上修改root密码为123456,然后再将Linux服务器或虚拟机上的/etc/shadow文件里root帐号的密码密文部分拷贝出来,创建根
文件系统树里的etc/shadow时将密文部分用这个密文替换。这个过程做完后记得将自己的Linux服务器或虚拟机的root密码还原回去。
[shun@localhost ~]$ sudo passwd root
Changing password for user root.
New password:
BAD PASSWORD: it is too simplistic/systematic
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.
[shun@localhost ~]$ sudo cat /etc/sh
shadow   shadow-  shells   
[shun@localhost ~]$ sudo cat /etc/shadow | grep root
root:$1$Aq7.S.aR$Yw1wTVOPLW8YpGbDrkTX80:17478:0:99999:7:::

再把root密码改回去
[shun@localhost ~]$ sudo passwd root
Changing password for user root.
New password:
BAD PASSWORD: it is based on a dictionary word
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.

现在我们创建根文件系统树下的/etc/shadow文件, 参考下文内容只将上面root帐号的加密密文部分( $6$Gc****lUkrTw1 )拷贝过来,其它部分保持不变:


[shun@localhost ~]$ cd fl2440/linux/rootfs/etc/
[shun@localhost etc]$ vim shadow
root:$1$Aq7.S.aR$Yw1wTVOPLW8YpGbDrkTX80:17478:0:99999:7:::

该文件的格式为:
username :password: last_change :min_change: max_change :warm: failed_expire :expiration: reserved
第一字段:用户名(也被称为登录名),在/etc/shadow中,用户名和/etc/passwd 是相同的,这样就把passwd 和shadow中用的用户记录联系在
一起;这个字段是非空的;
第二字段:密码加密后的密文,这个字段是非空的;
第三字段:上次修改密码的时间;这个时间是从1970年01月01日算起到最近一次修改口令的时间间隔(天数);
第四字段:两次修改密码间隔最少的天数;如果这个字段的值为空,帐号永久可用;
第五字段:两次修改密码间隔最多的天数;如果这个字段的值为空,帐号永久可用;
第六字段:提前多少天警告用户密码将过期;如果这个字段的值为空,帐号永久可用;
第七字段:在密码过期之后多少天禁用此用户;如果这个字段的值为空,帐号永久可用;
第八字段:用户过期日期;此字段指定了用户作废的天数(从1970年的1月1日开始的天数),如果这个字段的值为空,帐号永久可用;
第九字段:保留字段,目前为空,以备将来发展之用;

7)创建linux其他文件
    /et c/resolv.conf文件
该文件用来设置Linux系统的DNS服务器,DNS服务器用来将域名转换成IP地址。
[shun@localhost etc]$ vim hosts
127.0.0.1  localhost

    /et c/TZ文件
/etc/TZ 文件 配置了系统的时区
[shun@localhost etc]$ vim TZ
MST7MDT

    /et c/issue文件
/etc/issue 文件里存放 在console上登录系统时提示的警告信息
[shun@localhost etc]$ vim issue
Copyright (C) 2012 LingYun I.o.T Studio< iot-yun.com >
Default Logon Username: root Password: 123456

至此Linux根文 件系统树所需要的基本文件都已经有了,接下来我们可以使用Linux内核启动这个根文件系统。


5Linux内核使用initramfs文件系统启动

initramfs是Linus开发的一种基于内存的根文件系统,在编译Linux内核的时候, 它会直接把根文件系统树打包进内核的镜像文件中 (zImage),这也意味
着该 镜像文件同时包含了Linux内核和根文件系统 。因为根文件系统是内核打包进去的,所以 内核自己知道根文件系统的位置,这样u-boot也就不需要通过
bootargs参数告诉内核根文件系统的信息 ,此外也不需要额外烧录根文件系统镜像文件,如ubifs、yaffs2、jffs2等。在 今后做其他根文件系统的时候,请
务必在内核中禁用initramfs,否则Linux内核将优先使用initramfs启动了
因为initramfs是基于内存的根文件系统,所以 大家在开发板上对根文件系统里的任何文件的操作,包括创建、删除、修改在 重启后都会丢失 。因此 如果
想要更改根文件系统里的文件,必须修改根文件系统树,然后重新编译Linux内核并使用u-boot重新烧录。
Linux内核使用initramfs启动,只需要在 make menuconfig作 下面修改,然后重新编译即可。

[shun@localhost ~]$ cd fl2440/linux/linux-3.0
[shun@localhost linux-3.0]$ make menuconfig

..........

使用u-boot重新启动Linux系统:(这里的  Linux系统是指在开发板上跑的Linux)


[fl2440@lingyun]# tftp 30008000 linuxrom-s3c2440.bin
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
Using dm9000 device
TFTP from server 192.168.2.8; our IP address is 192.168.2.168
Filename 'linuxrom-s3c2440.bin'.
Load address: 0x30008000
Loading: T #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ###############################
done
Bytes transferred = 7133768 (6cda48 hex)
[fl2440@lingyun]# bootm 30008000
## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux Kernel
   Created:      2017-11-09  14:25:58 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    7133704 Bytes = 6.8 MiB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Linux version 3.0.0 ( shun@localhost.localdomain) (gcc version 4.4.6 (crosstool-NG 1.16.0) ) #4 Thu Nov 9 22:25:28 CST 2017
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=tty0 console=ttyS0,115200 men=64M rw loglevel=7
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 48856k/48856k available, 16680k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xffc00000 - 0xffe00000   (   2 MB)
    vmalloc : 0xc4800000 - 0xf6000000   ( 792 MB)
    lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc0b59000   (11588 kB)
      .text : 0xc0b59000 - 0xc0f5f028   (4121 kB)
      .data : 0xc0f60000 - 0xc0f86040   ( 153 kB)
       .bss : 0xc0f86064 - 0xc0fadffc   ( 160 kB)
NR_IRQS:85
irq: clearing pending ext status 00080800
irq: clearing subpending status 00000003
irq: clearing subpending status 00000002
Console: colour dummy device 80x30
console [tty0] enabled
console [ttyS0] enabled
Calibrating delay loop... 201.52 BogoMIPS (lpj=503808)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
gpiochip_add: gpios 288..303 (GPIOK) failed to register
gpiochip_add: gpios 320..334 (GPIOL) failed to register
gpiochip_add: gpios 352..353 (GPIOM) failed to register
NET: Registered protocol family 16
S3C Power Management, Copyright 2004 Simtec Electronics
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C244X: Clock Support, DVS off
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
s3c-i2c s3c2440-i2c: slave address 0x10
s3c-i2c s3c2440-i2c: bus frequency set to 98 KHz
s3c-i2c s3c2440-i2c: i2c-0: S3C I2C adapter
Advanced Linux Sound Architecture Driver Version 1.0.24.
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered

............


NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
Freeing init memory: 11588K         找到根文件系统并且成功启动
usb 1-1: new full speed USB device number 2 using s3c2410-ohci
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device number 3 using s3c2410-ohci
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device number 4 using s3c2410-ohci
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device number 5 using s3c2410-ohci
usb 1-1: device not accepting address 5, error -62
hub 1-0:1.0: unable to enumerate USB device on port 1
opyright (C) 2012 LingYun I.o.T Studio< iot-yun.com >     /etc/issue 文件里的信息
Default Logon Username: root Password: 123456
LiuShunFL2440 login: root         /etc/hostname 里设置的主机名为LiuShunFL2440,登录用户名为root,密码为123456
Password:           输入密码后进入Linux命令模式
~ >:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值