07、linux进程管理

一、进程介绍

1、进程概念

1)正在执行的程序
2)正在计算机上执行的程序实例
3)能分配处理器并由处理器执行的实体
进程的两个基本元素是程序代码和代码相关联的数据集。进程是一种动态描述,但并不代表所有的进程都在运
行。这就可以引入‘进程状态’。
进程在内存中因策会略或调度需求,会处于各种状态

2、linux下的进程状态

static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

# R- -可执行状态(运行状态)
只有在运行状态的进程才有可能在CPU上运行,注意是可能,并不意味着进程一定在运行中。同一时刻可能有多个进程处在可执行状态,这些进程的PCB(进程控制块)被放入对应CPU的可执行队列中。然后进程调度器从各个可执行队列中分别选择一个进程在CPU上运行。
另外如果计算机只有一个处理器,那么一次最多只有一个进程处于这种状态。

# S- -可中断睡眠状态(sleeping)
处在这个状态意味着进程在等待事件完成。这些进程的PCB(task_struct结构)被放入对应时间的等待队中。然后等待的事件发生时,对应的进程将被唤醒。

# D- -不可中断睡眠(disk sleep)
在这个状态的进程通常会等待IO的结束。
这个状态与sleeping状态相似,处于睡眠状态,但是此刻进程是不可中断的,意思是不响应异步信号。
另外你会发现处在D状态的进程kill -9竟然也杀不死。这就相当于我们怎么也叫不醒一个装睡的人。

# T- -暂停状态
给进程发送一个SIGSTOP信号,进程就会响应信号进入T状态,除非该进程正处在D状态。
再通过发送SIGCONT信号让进程继续运行。
kill -SIGSTOP
kill -SIGCONT

# Z- -僵死状态
僵死状态是一个比较特殊的状态。进程在退出的过程中,处于TASK_DEAD状态。
在这个退出过程中,进程占有的所有资源将被回收,除了task_struct结构(以及少数资源)以外。于是进
程就只剩下task_struct这么个空壳,故称为僵尸。

# X- -死亡状态或退出状态(dead)
死亡状态是内核运⾏ kernel/exit.c ⾥的 do_exit() 函数返回的状态。这个状态只是⼀个返回状态,
你不会在任务列表⾥看到这个状态

3、进程状态切换

进程在运行中不断的改变运行状态;
1)就绪状态
当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
2)执行(Running)状态
当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态
3) 阻塞(Blocked)状态
正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

# 就绪–>执行
处在就绪状态的进程,当调度器为其分配了处理机后,就变成了执行状态。
# 执行–>就绪
执行状态的进程在其执行过程中,时间片跑完了不得不让出处理机,于是从执行变成就绪状态。
# 执行–>阻塞
正在执行的进程等待某种事件而无法继续执行时,便从执行状态变成阻塞状态。
# 阻塞–>就绪
处在阻塞状态的进程,如果等待的时间发生,则从阻塞状态转变成就绪状态。
image-20201127160120811

二、查看进程

ps aux 是常用组合,查看进程用户、PID、占用CPU百分比、占用内存百分比、状态、执行的命令等

-a  	# 显示一个终端的所有进程
-u 		# 选择有效的用户id或者是用户名
-x 		# 显示没有控制终端的进程,同时显示各个命令的具体路径。

示例:

[root@localhost ~]# ps aux | head -5
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.6  54400  6644 ?        Ss   08:26   0:07 /usr/lib/systemd/systemd --system --deserialize 21
root          2  0.0  0.0      0     0 ?        S    08:26   0:00 [kthreadd]
root          3  0.0  0.0      0     0 ?        S    08:26   0:00 [ksoftirqd/0]
root          7  0.0  0.0      0     0 ?        S    08:26   0:00 [migration/0]
  • 查看结果显示
USER :	运行进程的用户
PID  : 	进程ID
%CPU :  CPU占用率
%MEM :  内存占用率
VSZ  :  占用虚拟内存,单位:kb(killobytes)
		VSZ是指已分配的线性空间大小,这个大小通常并不等于程序实际用到的内存大小,产生这个的可能性很多
		比如内存映射,共享的动态库,或者向系统申请了更多的堆,都会扩展线性空间大小。
RSS: 	占用实际内存,单位:kb(killobytes)
		RSZ是Resident Set Size,常驻内存大小,即进程实际占用的物理内存大小
TTY: 	进程运行的终端


STAT: 	进程状态 	man ps (/STATE)
R 		运行
S 		可中断睡眠 Sleep,即在睡眠的过程中可以接收信号唤醒=》执行的IO操作可以得到硬件设备的响应
D 		不可中断睡眠,即在睡眠的过程中不可以接收信号唤醒=》执行的IO操作得不到硬件设备的响应
T 		停止的进程
Z 		僵尸进程
X 		死掉的进程(几乎看不见,因为死了就立即回收了)
< 		标注了<小于号代表优先级较高的进程
N 		N代表优先级较低的进程
s 		包含子进程
+ 		+表示是前台的进程组
l 		小写字母l,代表以线程的方式运行,即多线程
| 		管道符号代表多进程
START: 	 进程的启动时间
TIME: 	进程占用CPU的总时间
COMMAND: 进程文件,进程名
          带[]号的代表内核态进程
          不带[]号的代表用户态进程
  • linux进程有两种睡眠状态
# 1、Interruptible Sleep(可中断睡眠,在ps命令中显示“S”)
处在这种睡眠状态的进程是可以通过给它发送signal来唤醒的,比如发HUP信号给nginx的master进程可以让nginx重新加载配置文件而不需要重新启动nginx进程;

# 2、Uninterruptible Sleep(不可中断睡眠,在ps命令中显示“D”)
处在这种状态的进程不接受外来的任何signal,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是“kill”、“kill -9”、“kill -15”还是按 Ctrl+C 、Ctrl+Z 都无济于,因为它们压根儿就不受这些信号的支配。
# 解释
进程为什么会被置于D状态呢?处于uninterruptible sleep状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如NFS挂载的远程文件系统已经不可访问了。
正是因为得不到IO的响应,进程才进入了uninterruptible sleep状态,所以要想使进程从uninterruptible sleep状态恢复,就得使进程等待的IO恢复,比如如果是因为从远程挂载的NFS卷不可访问导致进程进入uninterruptible sleep状态的,那么可以通过恢复该NFS卷的连接来使进程的IO请求得到满足,除此之外,要想干掉处在D状态进程就只能重启整个Linux系统了(恐怖的D状态)。
看到有人说如果要想杀掉D状态的进程,通常可以去杀掉它的父进程(通常是shell,我理解的这种情况是在shell下直接运行的该进程,之后该进 程转入了D状态),于是我就照做了,之后就出现了上面的状态:他们父进程被杀掉了,但是他们的父进程PID都变成了1,也就是init进程,这下可如何是好?此时我这些D状态的进程已经影响到其他一些进程的运行,而已经无法访问的NFS卷又在段时间内无法恢复,那么,只好重新启动了。

# 强调
D与Z状态的进程都无法用kill -9杀死

示例:

# 1、在窗口1执行命令
[root@localhost ~]# vim a.txt

# 2、在窗口2查看vim的运行状态为:S+
[root@localhost ~]# ps aux | grep [v]im
root      79400  0.0  0.5 149576  5116 pts/2    S+   17:48   0:00 vim a.txt

# 3、在窗口1执行:ctrl+z,将进程放置到后台
[root@localhost ~]# vim a.txt

[1]+  已停止               vim a.txt

# 4、在窗口2查看vim的运行状态为:T
[root@localhost ~]# ps aux | grep [v]im
root      79543  0.0  0.5 149620  5180 pts/2    T    17:51   0:00 vim a.txt

示例2:查看S+、R+、D+

# 1、在窗口1执行命令
[root@localhost ~]# tar cvzf test.tar.gz /etc/ /usr/ /var/ /usr/

# 2、在窗口2查看tar的状态:S+、R+、D+
[root@localhost ~]# while true;do ps aux |grep [t]ar;sleep 0.3;clear;done
  • 查看进程树
[root@localhost ~]# yum install psmisc -y		# 安装pstree
[root@localhost ~]# pstree
[root@localhost ~]# pstree 104239
bash───bash───bash───bash───pstree
  • 查看ppid
[root@localhost ~]# ps -ef| head -5
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 08:26 ?        00:00:08 /usr/lib/systemd/systemd --system --deserialize 21
root          2      0  0 08:26 ?        00:00:00 [kthreadd]
root          3      2  0 08:26 ?        00:00:00 [ksoftirqd/0]
root          7      2  0 08:26 ?        00:00:00 [migration/0]
  • 动态查看
# 一 基本用法
[root@localhost ~]# top
[root@localhost ~]# top -d 1 # 1秒刷新一次
[root@localhost ~]# top -d 1 -p 进程的pid
[root@localhost ~]# top -d 1 -p `pgrep nginx | head -1`
[root@localhost ~]# top -d 1 -p `pgrep sshd | head -1`,33 # 查看sshd以及pid为33的进程
[root@localhost ~]# top -d 1 -u nginx # 查看指定用户进程
[root@localhost ~]# top -b -n 2 > top.txt # 将2次top信息写入到文件

# 二 显示信息解释
第一部分:系统整体统计信息
    up左边的代表当前的时间
    up右边代表运行了多长时间
    load average: 0.86, 0.56, 0.78 CPU 1分钟,5分钟,15分钟平均负载
    us 用户态进程占用cpu时间的百分比
    sys 内核态进程占用cpu时间的百分比
    ni 代表优先被调度的进程占cpu时间的百分比
    id cpu空闲的百分比
    wa cpu等待io的百分比
    hi 硬件中断,处理硬件中断所占用CPU的时间
    si 软件中断,处理软件中断所占用CPU的时间
    st 被偷走的cpu

    linux中断:https://www.cnblogs.com/linhaifeng/articles/13916102.html
   
第二部分:进程信息
top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义
====================================================
VIRT:virtual memory usage 虚拟内存
1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量

RES:resident memory usage 常驻内存
1、进程当前使用的内存大小,但不包括swap out(当某进程向OS请求内存发现不足时,OS会把内存中暂时不用的数据交换出去,放在SWAP分区中,这个过程称为SWAP OUT。当某进程又需要这些数据且OS发现还有空闲物理内存时,又会把SWAP分区中的数据交换回物理内存中,这个过程称为SWAP IN)
2、包含其他进程的共享
3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
4、关于库占用内存的情况,它只统计加载的库文件所占内存大小

SHR:shared memory 共享内存
1、除了自身进程的共享内存,也包括其他进程的共享内存
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小
3、计算某个进程所占的物理内存大小公式:RES – SHR
4、swap out后,它将会降下来,因为内存充裕了,大家就没必要合租内存了

DATA
1、数据占用的内存。如果top没有显示,按f键、然后用空格选中DATA项目、然后按q则可以显示出来。
2、真正的该程序要求的数据空间,是真正在运行中要使用的。

# 三 top 运行中可以通过 top 的内部命令对进程的显示方式进行控制。内部命令如下:
命令
M 		按内存的使用排序
P 		按CPU使用排序
N 		以PID的大小排序
R 		对排序进行反转
f 		自定义显示字段
1 		显示所有CPU的负载
s 		改变画面更新频率
h|?		帮助
< 		向前
> 		向后
z 		彩色

# 四:调整进程的优先级:
1、r 调整进程的优先级(Nice Level)
优先级的数值为-20~19,其中数值越小优先级越高,数值越大优先级越低,-20的优先级最高,19的优先级最低。
需要注意的是普通用户只能在0~19之间调整应用程序的优先权值,只有超级用户有权调整更高的优先权值(从-20~19)。

2、k 给进程发送信号 1,2(^C),9,15,18,19(^Z)

# 五:更多内部命令
l – 关闭或开启第一部分第一行 top 信息的表示
t – 关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示
m – 关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示
N – 以 PID 的大小的顺序排列表示进程列表
P – 以 CPU 占用率大小的顺序排列进程列表
M – 以内存占用率大小的顺序排列进程列表
h – 显示帮助
n – 设置在进程列表所显示进程的数量
q – 退出 top

序号		列名 		含义
a 		  PID 	    进程id
b 		  PPID   	父进程id
c 		  RUSER Real user name
d 		  UID 		进程所有者的用户id
e 		  USER 		进程所有者的用户名
f  	 	  GROUP 	进程所有者的组名
g 		  TTY 		启动进程的终端名。不是从终端启动的进程则显示为 ?
h 		  PR 		优先级
i 		  NI 		nice值。负值表示高优先级,正值表示低优先级
j 		  P 		最后使用的CPU,仅在多CPU环境下有意义
k 		  %CPU 		上次更新到现在的CPU时间占用百分比
l 		  TIME 		进程使用的CPU时间总计,单位秒
m 		  TIME+ 	进程使用的CPU时间总计,单位1/100秒
n 		  %MEM 		进程使用的物理内存百分比
o 		  VIRT 		进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
p 		  SWAP 		进程使用的虚拟内存中,被换出的大小,单位kb。
q 		  RES 		进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
r 		  CODE 		可执行代码占用的物理内存大小,单位kb
s 		  DATA 		可执行代码以外的部分(数据段+)占用的物理内存大小,单位kb
t 		  SHR 		共享内存大小,单位kb
u 		  nFLT 		页面错误次数
v 		  nDRT 		最后一次写入到现在,被修改过的页面数。
w 		  S 		进程状态。(D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程)
x 		  COMMAND    命令名/命令行
y 		  WCHAN 	若该进程在睡眠,则显示睡眠中的系统函数名
z 		  Flags 	任务标志,参考 sched.h
默认情况下仅显示比较重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列。可以通过下面的快捷键来更改显示内容。
通过 f 键可以选择显示的内容。按 f 键之后会显示列的列表,按 a-z 即可显示或隐藏对应的列,最后按回车键确定。
按 o 键可以改变列的显示顺序。按小写的 a-z 可以将相应的列向右移动,而大写的 A-Z 可以将相应的列向左移动。最后按回车键确定。
按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序。而大写的 R 键可以将当前的排序倒转

三、shell管理进程

1、优先级设置

可以在启动进程时用nice命令设置设置优先级

# 1、命令
nice [-n <优先级>] [--help] [--version] [执行指令]

# 2、选项介绍:
若 nice命令未指定优先级的调整值,则以缺省值10来调整程序运行优先级,既在当前程序运行优先级基础之
上增加10。
-n <优先级> 指定优先级;
--help 帮助信息;
--version 版本信息;

# 3、执行范例:让命令以新的优先级执行
[root@localhost ~]# $ nice -n 5 ls # nice -n -20 命令

# 4、ps -l 命令
其中的几个重要信息有:
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值

PRI即进程的优先级,此值越小进程的优先级别越高。而NI,也就是我们所要说的nice值(通过nice命令设置),其表示进程可被执行的优先级的修正数值。如前面所说,PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。
所以,nice命令设置的优先级不是程序最终的优先级,而只是优先级的修正数值。
renice命令允许用户修改一个正在运行的进程的优先权。

也可以对已运行的进程设置新的优先级

[root@localhost ~]# renice -20 11111

2、给进程发送信号

[root@localhost ~]# kill -l # 列出所有支持的信号
=====================解释==========================
# HUP(1): 1、挂起信号 2、往往可以让进程重新加载配置
本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。
登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都 属于这个 Session。当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。不过,可以捕获这个信号,比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录,wget也能继续下载。
此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。

# INT(2): 中断, 通常因为按下ctrl+c而产生的信号,用于通知前台进程组终止进程。

# QUIT(3): 退出,和SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。

# TSTP(20): 停止进行运行,通常因为按下ctrl+z而产生的信号

# KILL (9):强制杀死
用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。

# TERM(15):
终止,是不带参数时kill默认发送的信号,默认是杀死进程,与SIGKILL不同的是该信号可以被阻塞和处理。
通常用TERM信号来要求程序自己正常退出,如果进程终止不了,我们才会尝试SIGKILL。

# CONT(18) 被暂停的进程将继续恢复运行

# SIGSTOP(19) 暂停进程

# SIGCHLD
子进程结束时, 父进程会收到这个信号。
如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸 进程。这种情 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程 来接管)# 更多详见:man 7 signal

杀死所有:根据进程名杀所有

[root@localhost ~]# vim a.txt &
[4] 82137
[root@localhost ~]# vim a.txt &
[5] 82139

[4]+  已停止               vim a.txt
[root@localhost ~]# vim a.txt &
[6] 82143

[5]+  已停止               vim a.txt
[root@localhost ~]# killall -9 vim
[1]   已杀死               vim a.txt
[4]   已杀死               vim a.txt
[5]-  已杀死               vim a.txt
[6]+  已杀死               vim a.txt
[root@localhost ~]# pkill -9 vim
[root@localhost ~]#

查看某个用户开启的进程

[root@localhost ~]# pgrep -l -u root

四、proc文件系统

[root@localhost ~]# du -sh /proc

cpu:/proc/cpuinfo

[root@localhost ~]# grep 'processor' /proc/cpuinfo
processor       : 0
[root@localhost ~]# grep 'physical id' /proc/cpuinfo
physical id     : 0
[root@localhost ~]# grep 'cpu cores' /proc/cpuinfo
cpu cores       : 1
[root@localhost ~]# cat /proc/cpuinfo

lm(64位)
vmx 支持虚拟化 Intel
svm 支持虚拟化 AMD
[root@localhost ~]# egrep --color 'lm|vmx|svm' /proc/cpuinfo
[root@localhost ~]# lscpu

内存:/proc/meminfo

# 查看内存
[root@egon ~]# less /proc/meminfo

[root@localhost ~]# free -wm
              total        used        free      shared     buffers       cache   available
Mem:            977         160          66          11           3         747         646
Swap:          2047           1        2046


# 需要注意的是
free表示的是当前完全没有被程序使用的内存;
而cache在有需要时,是可以被释放出来以供其它进程使用的(当然,并不是所有cache都可以释放,比如当前被用作ramfs的内存)。
而available才是真正表明系统目前可以提供给新启动的应用程序使用的内存。
/proc/meminfo从3.14内核版本开始提供MemAvailable的值;在2.6.27~3.14版本之间,是free程序自己计算available的值;早于2.6.27版本,available的值则同free一样。

# 释放内存示例:	
[root@localhost ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1001332      164132       68012       12240      769188      662032
Swap:       2097148        1060     2096088
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches
[root@localhost ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1001332      149816      791392       12240       60124      759016
Swap:       2097148        1060     2096088

内核启动参数: /proc/cmdline

[root@localhost ~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8
[root@localhost ~]# uptime
 18:41:16 up 10:14,  3 users,  load average: 0.00, 0.01, 0.05

卸载/proc后

# 下述命令都不可用
free -m
uptime
lscpu
toop

五、管理后台进程

[root@localhost ~]# sleep 5000 &         # 运行程序(时),让其在后台执行
[1] 83176
[root@localhost ~]# sleep 4000
^Z									  # ^z,将前台的程序挂起(暂停)到后台
[2]+  已停止               sleep 4000
[root@localhost ~]# jobs				# 中括号内的编号就是作业编号,%1代表作业1
[1]   运行中               sleep 5000 &
[2]+  已停止               sleep 4000

[root@localhost ~]# bg %2 				# 让作业2在后台运行
[2]+ sleep 4000 &
[root@localhost ~]# fg %1 				# 将作业1调回到前台
[root@localhost ~]# jobs
[2]+ 运行中 sleep 4000 &
[root@localhost ~]# kill %2

nohup

加在一个命令的最前面,表示不挂断的运行命令

六、管道

1、介绍

# 管道用于进程间通信
[root@localhost ~]# ps aux |grep "httpd"
[root@localhost ~]# yum list |grep nginx

详细地说,管道操作符号 "|" ,主要用来连接左右两个命令, 将左侧的命令的标准输出, 交给右侧命令的标准输入
PS: 无法传递标准错误输出至后者命令
格式: cmd1 | cmd2 [...|cmdn]

2、管道流程示意图

image-20201127175901034

3、管道应用示例

  • 统计当前/etc/passwd中用户使用的shell类型
[root@localhost ~]# awk -F: '{print $7}' /etc/passwd | sort | uniq -c
      2 /bin/bash
      1 /bin/sync
      1 /sbin/halt
     19 /sbin/nologin
      1 /sbin/shutdown
  • 统计网站的访问情况
[root@localhost ~]# netstat -an |grep :80 |awk -F":" '{print $8}'|sort |uniq -c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值