fork后父子进程共享资源

fork父子进程共享 fork之后,子进程会拷贝父进程的数据空间、堆和栈空间(实际上是采用写时复制技术),二者共享代码段。 所以在子进程中修改全局变量(局部变量,分配在堆上的内存同样也是)后,父进程的相同的全局变量不会改变。 阅读详情

fork后父子进程共享资源

Unix环境高级编程中8.3节中说,“子进程是父进程的副本。例如,子进程获得父进程数据空间、堆和栈的副本。注意,这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间部分。父进程和子进程共享正文段。”

书中还预留了例子说明子进程对变量所做的改变并不影响父进程中该变量的值。

/**
 * fork.c
 * 探讨父子进程共享变量问题
 **/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int globvar = 6;        /* external variable in initialized data */
char buf[] = "a write to stdout\n";

int 
main(void)
{
    int var;    /* automatic variable on the stach */
    pid_t pid;

    var = 88;
    if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
    {
        perror("write error");
        exit(1);
    }
    printf("before fork\n");    /* we don't flush stdout */

    if ((pid = fork()) < 0)
    {
        perror("fork error");
        exit(1);
    } else if (pid == 0) {    /* child */
        globvar++;          /* modify variables */
        var++;
    } else {
        sleep(2);           /* parent */
    }

    printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
    exit(0);
}

编译和运行程序,如下:

/myblog/source/fork# gcc fork.c -o fork
/myblog/source/fork# ./fork
a write to stdout
before fork
pid = 12071, glob = 7, var = 89
pid = 12070, glob = 6, var = 88

如上,可以看出,fork后子进程只是获得了父进程的副本,所有变量的变更都只在各自进程中有效。

实际上,fork后子进程和父进程共享的资源还包括:

  • 打开的文件
  • 实际用户ID、实际组ID、有效用户ID、有效组ID
  • 添加组ID
  • 进程组ID
  • 会话期ID
  • 控制终端
  • 设置-用户-ID标志和设置-组-ID标志
  • 当前工作目录
  • 根目录
  • 文件方式创建屏蔽字
  • 信号屏蔽和排列
  • 对任一打开文件描述符的在执行时关闭标志
  • 环境
  • 连接的共享存储段(共享内存)
  • 资源限制

父子进程之间的区别是:

  • fork的返回值
  • 进程ID
  • 不同的父进程ID
  • 子进程的tms_utime,tms_stime,tms-cutime以及tms_ustime设置为0
  • 父进程设置的锁,子进程不继承
  • 子进程的未决告警被清除
  • 子进程的未决信号集设置为空集
参考文献

[1] Unix环境高级编程(第3版)

[2] http://blog.youkuaiyun.com/u012138828/article/details/39031823

Linux 多进程通信开发(一):fork 进程 这会是一系列文章,文章的目的是让自己的知识固话和文档化,以备自己不时的复习,同时也希望能够给予初学者一些帮助。 进程是操作系统中一个很重要的概念,几乎每一种应用都是单独跑在一个进程当中。 我们编译生成的程序一般放在磁盘上,需要运行的时候内核会创建一个进程空间,分配内存,然后分配 ID 号码,再将程序的代码段存放在一个地方,程序中定义的静态变量和全局变量存放在一个地方,动态分配的内存划定在进程的堆,... 阅读详情

相关推荐

Unity Addressable资源缓存路径自定义指南:告别C盘爆满烦恼

本文详细介绍了如何自定义Unity Addressable系统的资源缓存路径,解决其默认存储在C盘导致的磁盘空间不足问题。通过配置CacheInitializationSettings并编写编辑器脚本,开发者可以将缓存迁移至项目目录,实现资源的集中管理,提升团队协作效率与开发环境一致性。

pytorch8learner的博客 475

多进程编程,资源共享——fork

fork后父子进程共享资源子进程是父进程的副本。例如,子进程获得父进程数据空间、堆和栈的副本。注意,这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间部分。父进程和子进程共享正文段。子进程对变量所做的改变并不影响父进程中该变量的值。fork后子进程只是获得了父进程的副本,所有变量的变更都只在各自进程中有效。fork后子进程和父进程共享的资源还包括打开的文件实际用户ID、实际组ID、有效用户...

Just code it! 1349

echarts的坐标轴处理算法

参考原文:https://www.cnblogs.com/vicky-li/p/11653415.html。2、可用于双轴的情况,指定splitNumber,保证左右两边的线没有交叉显示的情况。1、设置echarts显示的最大最小值,让数据显示比较有起伏。处理echarts的一些问题。

HYeeee的博客 801

fork()----父子进程共享

fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进

程序狗的成长之路 9213

WSL2迁移后用户名不见了?一招教你快速恢复Ubuntu22.04默认用户

本文针对WSL2迁移后Ubuntu 22.04默认用户名丢失的常见问题,提供了详细的诊断与修复方案。通过分析迁移底层逻辑,指导用户使用`ubuntu2204.exe config --default-user`命令或配置`/etc/wsl.conf`文件快速恢复用户身份,并涵盖权限修复、冲突解决及自动化迁移脚本等进阶内容,确保子系统迁移后环境完整可用。

web39explorer的博客 558

【STK】手把手教你利用STK进行弹道导弹和运载火箭发射仿真的相关方法全过程解析

写这个系列主要是这几年做了一些弹道导弹和运载火箭发射的相关仿真项目,stk软件由于其专业性在国内比较小众,相关的教程和书籍、经验贴都不是很多,因此新手在进行开发中容易遇到较多困难,把自己的一些经验体会写下来,一方面供自己总结回顾,另一方面也希望对大家有所帮助。这个系列计划分几篇文章写完,每章的内容结构相似,都分为①如何确定发射场位置和发射轨迹、②导入导弹和运载火箭模型、③设计模型分段动作、④飞行参数分析和相关应用这四个部分,每篇文章争取完整描述1-2个实际项目的操作过程。

weixin_44184852的博客 5988

二、父子进程的关系

一、如何在进程中创建一个新的进程(fork函数) 1、pid_t fork(void); (1)fork函数与别的函数有所不同,它调用一次,返回两次。在新创建出来的进程中返回一次(返回值为 0),在原来的进程中返回一次(返回值为新进程的pid)。 (2)fork函数调用完成以后,两个进程都从fork之后开始执行。 (3)fork函数复制出新的进程后,两个进程成为独立的个体,互相不影响,各自执行。并...

凌凌小博客 2729

18、偏微分方程数值计算:粘性不可压缩流与电磁学的有限元方法

本文系统介绍了偏微分方程数值计算在粘性不可压缩流与电磁学中的应用,重点探讨了稳态与非稳态Navier-Stokes问题的混合有限元方法及求解技术,包括弱形式构建、半离散与时间离散格式、牛顿迭代法等。同时,详细阐述了电磁学中Maxwell方程的有限元与时域有限差分法(FDTD)求解方法,涵盖时间谐波与时域波方程、边界条件处理、稳定性分析与误差估计。结合MATLAB代码示例和实际案例,展示了速度场、压力、电场与磁场的数值模拟过程,并通过流程图与表格对比了两类问题的方法原理、应用场景与收敛性特性。最后展望了多物理

lemon的博客 89

父子进程管道通信(附简单样例)

0x00思路 为了给TinyHTTPd源码分析打下基础,先写一个简单父子进程管道通信的样例 1,先定义,并绑定read,write函数和缓冲区,创建pipe管道数组(下标0对于读段,1对应写端,这是强制规定的) 2.父进程fork后,父子进程各有一套1中的变量,且代码执行是同步的,只不过储存空间不在一起,然后对父子进程的管道进行操作使之可以通信 0x01函数 write #include <unistd.h> ssize_t write(int fd, const void *bu

CheAyuki13的博客 2250

RK3588,V4l2 读取Gmsl相机, Rga yuv422转换rgb (dma), 实现零拷贝

RK3588, 使用V4l2 读取 gmsl 相机,获得yuv422格式图像, 使用 rga 转换 rgb 图像。减少cpu占用率. 内存管理方式采用 dma,实现零拷贝.

J。 1262

爬虫瑞数5案例:联通

瑞数动态安全 Botgate(机器人防火墙)以“动态安全”技术为核心,通过动态封装、动态验证、动态混淆、动态令牌等技术对服务器网页底层代码持续动态变换,增加服务器行为的“不可预测性”,实现了从用户端到服务器端的全方位“主动防护”,为各类 Web、HTML5 提供强大的安全保护。

老衲爱洗头的博客 4470

父子进程共享的资源

先来看一个题目: 当父进程调用fork()创建子进程之后,下列哪些变量在子进程中修改之后,父进程里也会相应地作出改动? A.全局变量 B.局部变量 C.静态变量 D.文件指针 答案为D,解释如下: fork()子进程和父进程共享的资源: 打开的文件 实际用户ID、实际组ID、有效用户ID、有效组ID 添加组ID 进程组ID 对话期ID 控制终端。  设置-用户-ID标志

u012138828的专栏 6946

网络安全系列-四十三:使用Suricata分析恶意流量pcap文件

本文基于[网络安全系列-三十六:使用Suricata IDS分析pcap文件]和 [网络安全系列-四十二: Suricata之rulesets的激活、更新及动态加载]的基础上,使用suricata针对包含恶意流量的pcap文件进行分析,触发事件告警,并对suricata输出的日志进行逐个分析,让你掌握针对恶意流量的分析步骤,及怎么查看suricata输出的日志。

penriver的博客 2888

HUST OS 4.6 Windows和Linux进程同步机制【自学笔记】

4.6 windows|Linux进程同步机制 4.6.1 临界区机制(CRITICAL_SECTION) 等待函数WaitForXXXobject;(XXX:Multiple|Single) 等待目标对象变成有信号的状态就返回 当多个线程同时在临界区就绪的时候,需要对临界区进行一个互斥的访问. P(S) //进入临界区 V(S) //退出临界区 互斥量 Handle 信号量 Sema...

Irish_Moonshine的博客 433

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Liunx操作-Record14—父子进程中的相同与不同

父子进程中的相同与不同

恋蛩音的博客 502

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

linux进程fork——写时复制

fork到底复制了父进程的哪些资源? 我们来看一个例子 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/wait.h> int main() { pid_t pid; int num = 5; int status; pid = fork(); switch(pid) { case -1: perror("create porcess is

modi000的博客 529

fork,写时复制(copy-on-write),vfork

fork,写时复制(copy-on-write),vfork fork,写时复制(copy-on-write),vforkaqueforkvfork写时复制 进程创建 进程创建分为三种情况 1.共享 父进程与子进程共享数据段、堆栈段、代码段,也就是说子进程对数据进行的改变会直接影响父进程。 2.写时复制(Copy-On-Wr...

weixin_30788239的博客 287

fork函数

 在linux中,只有一个函数可以创建子进程:fork。 #include  #include  pid_t fork(void);       由f o r k创建的新进程被称为子进程( child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程I D。将子进程I D返回给父进程的理由是:因为一个进程的子进程

jeff_2009的专栏 467

linux下的fork

平时经常在linux做开发 经常会用到fork来启动个子进程 所有的书都说了子进程会继承父进程的资源 但没哪本书说了所有main程序中的代码父子进程都会执行 这可能会对刚接触到子进程编译的新手来说有点困惑

szkarry的专栏 649

【Linux】进程管理

利用 fork 系统调用编写多进程程序,分别设置全局和局部变量检测父子进程共享资源的情况。

2201_75406816的博客 363

Linux fork()/vfork()的区别

这里写目录标题fork函数介绍利用fork()创建父子进程vfork函数介绍利用vfork()创建父子进程fork()和vfork()的主要区别 fork函数介绍 在Linux系统内,创建子进程的方法是使用系统调用fork()函数。fork()函数是Linux系统内一个非常重要的函数,它与我们之前学过的函数有一个显著的区别:fork()函数调用一次却会得到两个返回值。 所需头文件: #include<sys/types.h> #include<unistd.h> 函数原型:pid_

TABE_的博客 523

fork是linux函数吗,linux fork()函数

概述最近在看进程间的通信,看到了fork()函数,虽然以前用过,这次经过思考加深了理解。现总结如下:1.函数本身(1)头文件#include#include(2)函数原型pid_t fork( void);(pid_t 是一个宏定义,其实质是int 被定义在#include中)返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1(3)函数说明一个现有进程可以...

weixin_39658900的博客 127

头歌Linux——Linux系统的进程控制 练习二 2023-04-06

Linux系统的进程控制 头歌Linux——Linux系统的进程控制 练习二 2023-04-06

weixin_66547608的博客 3546

C Fork 函数

Fork 函数:#include pid_t fork(void);由fork 创建的新进程被称为子进程。fork 函数被调用一次,但是返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的ID。将子进程的ID 返回给父进程的理由是:一个进程可以有多个子进程,并且没有函数是一个进程获得其子进程的进程ID。fork 在子进程中返回0的理由是:一个进程只能有一个父

Alf的专栏 2617

父子进程之间的关系

摘要:本文详解介绍fork()函数的基本使用,以及父子进程之间的关系.子进程对变量的改变不会影响到父进程、子进程对父进程文件流缓冲区的处理和子进程对父进程打开的文件描述符的处理. 创建进程 1.fork()函数 函数定义:     #include     pid_t fork(void); 返回值:如果返回值大于零,表明处于父进程上下文环境中,返回值是子进程的ID.如果返回值是零,

疯子小鱼 3679

Linux生成子进程函数fork()

#include &amp;amp;amp;lt;sys/types.h&amp;amp;amp;gt; #include &amp;amp;amp;lt;stdio.h&amp;amp;amp;gt; #include &amp;amp;amp;lt;unistd.h&amp;amp;amp;gt; #include &amp;amp;amp;lt;stdlib.h&amp;amp;amp;gt; #include &amp;amp;

Erick Lv的笔记 416
上一篇: 僵尸进程
下一篇: 多线程共享资源
薛离子
博客等级 码龄17年 21粉丝 146原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值