openssl 客户端程序移植到arm平台 OK6410上运行

openssl三方库交叉编译 项目需要将openssl三方库编译成在arm板子上能跑的AArch64格式,踩了一些坑,做个笔记一来方便以后忘记查阅,二是希望能帮助其他小伙伴能少走些弯路。提示:以下是本篇文章正文内容,下面案例可供参考openssl交叉编译配置总体还是比较简单的三方库,配置好交叉编译工具的环境变量和config文件一路畅通无阻,希望本篇内容对你有些帮助。 阅读详情

     openssl  客户端程序如何移植到arm平台上运行?

     在我的项目中拥有一个服务器程序file_server和一个客户端程序file_client,它们实现了通过安全套接字层传输文件的功能。原本两个程序都在pc上运行,现在要把客户端程序移植到arm平台上。

     原来makefile中生成客户端程序的规则是这样的:

     gcc file_client.c -o file_client -lssl -lpthread

     如果想移植到arm平台是不是直接将 gcc 改为 arm-linux-gcc就可以了呢?回答是不行的,原因在于-lssl连接的库libssl.a或 libssl.so原本是在x86的环境下编译生成的,所以直接arm-linux-gcc file_client.c -o file_client -lssl -lpthread 会提示搜索到的库格式不对。

     因此应该重新编译openssl,步骤如下:

     1.config:

        #config no-asm (忽略x86汇编部分)

     2.改Makefile

        1) CC= gcc 改成 CC = arm-linux-gcc;

        2) 删除 CFLAG= 中的 “-march=pentium”;(如果有的话)  

        3) AR=ar $(ARFLAGS) r 改为 AR=arm-linux-ar $(ARFLAGS) r;

        4) ARD=ar $(ARFLAGS) d 改为 ARD=arm-linux-ar $(ARFLAGS) d;

        5)RANLIB= /usr/bin/ranlib 改为 RANLIB= arm-linux-ranlib;

     3.编译

        #make


     编译完成后会产生libssl.a 和libcrypto.a 两个归档文件,将这两个文件copy到客户端代码目录下,直接和源文件进行编译:

     arm-linux-gcc file_client.c -o file_client libcryto.a libssl.a  -lpthread

    

     这时会出现:error:openssl/ssl.h: No such file or directory的错误,这显然是因为我们的arm-linux-gcc编译器没有把x86环境下的/usr/include作为标准头文件搜索目录的缘故。(原来在pc机上装x86的openssl时,将openssl的头文件install到这个目录)

     我们可以加上一个选项: -I/usr/include

 

     这时按照:

     arm-linux-gcc file_client.c -o file_client libcryto.a libssl.a  -lpthread -I/usr/include

     进行编译,又会冒出一大堆的:undefined refrence to ' '  错误。符号未定义?可以头文件都包含进来了啊?仔细分析另一种可能的原因是库的使用,准确的说是库的编译顺序,libssl.a用到很多符号,而这些符号只在libcryto.a定义或申明 ,那么libcrypto.a 应该出现在libssl.a 的后面 。

 

     arm-linux-gcc file_client.c -o file_client libssl.a  libcryto.a -lpthread -I/usr/include

     这时还会提示:undefined refrence to ' dlopen' ,再将 libdl.a(用于加载动态库方法的库)包含进去即可。

     最终编译命令:

 

     arm-linux-gcc file_client.c -o file_client libssl.a  libcryto.a -lpthread -I/usr/include  -ldl -static

 

     将生成的可执行程序 file_client 拷贝到开发板,chmod 777 file_client 修改权限,在pc上运行服务器程序,在开发板上运行客户端程序即可,下面给出我的程序在OK6410上的运行效果图:

1.运行客户端程序:

2.使用cd home切换客户端目录:

3.下载服务器上的文件serv.cpp

4.下载完成

5.屏幕刷新后,可见客户端home目录下多出的文件serv.cpp

 

 

 

opus编译库到arm上面用 一、可以到https://opus-codec.org/下载源码 进入到目录 % ./configure CFLAGS="-Os" --enable-fixed-point --enable-intrinsics --host=arm-linux // configure后面的参数是指定优化选项,和编译器 % make % sudo make install二、可以用git下载源码 % 阅读详情

相关推荐

openssl移植的arm开发板全过程

1.交叉编译参考了:http://hi.baidu.com/lihuanhai1943/blog/item/00ef57fa9ee3d1d6b58f31d0.html我的makefile修改完如下:#CC=gccCC=armv6zk-none-linux-gnueabi-gccC

梦想的蓝天草原--未来的时间自由人--哈哈哈哈 6535

编译-openssl交叉编译问题

openssl交叉编译问题

ty的专栏 1万+

OpenSSL库在WIN32平台和ARM平台下的编译

OpenSSL是一个强大的安全套接字层密码库,包含各种主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供了丰富的应用程序供测试或其他目的使用。访问OpenSSL的官方网站[https://www.openssl.org/source/],下载1.1版本的源码包,并解压至合适的目录。通过以上步骤,可以在WIN32平台和ARM平台下成功编译OpenSSL库,并将其用于各自平台的安全通信和数据加密等需求。的错误,需要编辑Makefile文件,删除相关的。将生成的库文件和头文件安装到指定的目录。

哈哈星云 859

基于嵌入式linux的OpenSSL源码移植(基于arm64)

本文介绍在openssl的源码(注意:本文OpenSSL源码为V1.1.1t,是V1.x的最新版本。)移植流程,使用ubuntu系统的交叉编译器环境编译openssl的源码,生成可以在ARM64架构上运行的应用软件。

q544344318的博客 2423

opus编解码移植stm32f407

移植好的opus音频编码,测试编解码正常。采用freertos实时系统。

openssl 最新版 all Platform

openssl 最新版 全平台 .a 类库 i386 arm64 armv7 armv7s x86_64,全部支持 lib/libssl.a are: i386 armv7s armv7 x86_64 arm64 lib/libcrypto.a are: i386 armv7s armv7 x86_64 arm64

使用openssl的md5库

在linux机器上,有一个命令可以计算出文件的md5值,那就是md5sum,如果没有的话,就需要安装RPM包:coreutils。 现在我们使用openssl的库也可以方便的计算出文件的md5值。主要用到的函数是 int MD5_Init(MD5_CTX *c); int MD5_Update(MD5_CTX *c, const void *data, size_t len); int M

hepeng597的专栏 2万+

Stable Diffusion跑图总爆显存?别急着换显卡,试试这个PYTORCH_CUDA_ALLOC_CONF参数调优

本文深入解析了Stable Diffusion运行中常见的显存不足问题,特别是由显存碎片化导致的假性OOM现象。通过详细讲解PYTORCH_CUDA_ALLOC_CONF参数中的max_split_size_mb设置技巧,提供了一套完整的显存优化方案,帮助用户在无需升级硬件的情况下显著提升AI绘画的稳定性与效率。

weixin_42524100的博客 347

移植OpenSSL加密软件到ARM

1.执行解压命令tar xvzf ./opensll-1.0.0s.tar.gz,解压后进入文件夹. 2.mkdir _install 创建一个_install文件夹 3.执行命令  ./config no-asm shared --prefix=/home/S5-Pro/Spring_1/opensll-1.0.0s/_install/(此处填绝对路径) 4.修改Makefile 将c

5念since 2240

MIPI D-PHYv2.5笔记(11) -- 高速时钟传输(High-Speed Clock Transmission)

在High-Speed模式中,Clock Lane提供了一个低摆幅(low-swing)、差分DDR时钟信号,此信号从Master到Slave,用于为高速数据传输提供时钟信号。时钟信号关于Forward Direction中的Data Lane上的位切换序列(toggling bit sequence)有正交相位,并且在一次burst的第一个被传输的bit的中心点有一个上升沿。

vivo01的专栏 3021

微信小程序导航栏滑动一定距离后固定到顶部

接上一篇文章的内容,通常在一个页面中部会有一个导航栏查看不同的内容,这篇文章旨在实现在页面下滑的过程中导航栏自动固定到顶部以便我们阅读过程中的切换。 下滑一段距离后自动固定到顶部 首先,思考这个功能应该是怎么实现的: 在页面下滑的过程中,我们希望系统应当能识别下滑了多少距离,当原本的导航栏逐渐被遮住以后(遮住意味着下滑了特定距离),触发这个功能,执行另一种样式,将导航栏固定在页面顶端,同时如果我们将页面往上滑,系统能识别到原来的导航栏能露出来了(即距离顶端的高度小于一个特定的值),这时候又执行最初的样式

Oblivision_Geek的博客 4031

openssl移植arm开发板

openssl移植arm开发板一 准备openssl压缩包mini244开发板二 步骤step1 解压缩# tar zvcf openssl-1.0.0s.tar.gz# cd openssl-1.0.0sstep2 配置# mkdir _install# .config no-asm shared --prefix=/home/S4-DRIVER/project/part2/openssl-1....

yyq5033的博客 959

Halcon实战:基于图像清晰度自动筛选最佳对焦图片

本文详细介绍了如何使用Halcon实现基于图像清晰度的自动筛选最佳对焦图片技术。通过分析灰度值统计和标准差等核心指标,结合实战代码示例,帮助开发者高效处理工业检测中的对焦问题,提升自动化检测的准确性和效率。

weixin_27015733的博客 440

【物联网】ARM平台移植openssl-1.1.1详解

OpenSSL是一款开源的安全套接字层(SSL)和加密套接字层(TLS)库,它可以为互联网通信、邮件、文件传输和其他应用程序提供安全保护。它支持多种加密算法,包括对称和非对称加密,并且可以在各种操作系统和硬件平台上运行。OpenSSL由全球各地的开发者和组织共同维护和开发,是目前最流行的SSL和TLS库之一。命令行工具:openssl命令行工具可以用于生成证书、密钥、TLS连接和其他安全操作。库文件:openssl库文件包含了OpenSSL的主要功能,可以在程序中直接使用。

C/C++软件工程师、嵌入式软件工程师、物联网研发工程师、C/C++讲师、物联网讲师、嵌入式讲师、鸿蒙讲师---欢迎大家一起交流(私信添加博主微信) 2545

Unity3d实现红外热成像效果

1.将需要在红外图像中高亮的物体设置到图层PostProcessing。 2.新建一个相机CameraHighLight,设置其Culling Mask为PostProcessing,也就是在这个相机中只有PostProcessing图层的物体可见。 3.新建一个RenderTexture,命名为HightLightRt,将CameraHighLight的Target Texture设HightLightRt。 4.新建一个相机Camera2,这个相机用于显示其他物体。 接下来将CameraHigh

zouxin_88的专栏 8327

大华 DSS 数字监控系统 itcBulletin SQL 注入漏洞复现

大华 DSs 数字监控系统是大华开发的一款安防视频监控系统,拥有实时监视、云台操作、录像回放、报警处理、设备管理等功能。大华 DSS存在SQL注入漏洞,攻击者 pota/services/itcBuletin 路由发送特殊构造的数据包,利用报错注入获取数据库敏感信息。攻击者除了可以利用 SQL注入漏词获取数据库中的信息例如,管理员后台密码、站点的用户人人信息)之外,甚至在高权限的情况可向服务器中写入木马,进一步获取服务器系统权限poc验证是否存在漏洞如果你想查询用户名和密码。

holyxp的博客 4003

Openssl移植到ARM开发板

Openssl移植到ARM开发板openssl源码下载源码编译配置使用生成的库文件 openssl源码下载 openssl源码可以在官网下载:https://www.openssl.org/source/,如图所示,下载需要的版本。 下载源码的好处是编译时可以自己定义一些配置,否则也可以使用apt-get等命令安装。 源码编译配置 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标...

lingyuncao的博客 5185

wireshark提取视频数据之RTP包中提取H264和H265

本文主要描述从wireshark包数据中提取出H264和H265裸流数据方法,裸流通过RTP封包方式发送,从抓包中直接提取视频流数据,进而进行流媒体问题定位

技术控的笔记 17万+

编译并导入OpenSSL

编译并导入OpenSSL   1. 首先,需要运行脚本生成OpenSSL库,参考 https://github.com/x2on/OpenSSL-for-iPhone 示例     2. 运行脚本生成静态库 下一步我们会用到这两个文件夹中的内容   3. 新建一个文件夹叫 openssl ,然后将 OpenSSL-for-iPhone 项目中的 FSOpenSSL.h/...

weixin_33742618的博客 297

顶刊论文引言用AI怎么写?借助Gemini 3 Pro结合四段式写出逻辑清晰的Introduction

写研究目标时,先明确研究问题,直接回应前文提到的研究缺口,如 “This study aims to investigate whether X modulates Y via the Z pathway in human cells.”然后再提出你的研究假设,当理论依据清晰时,可以用如 “We hypothesized that inhibiting X would rescue Y deficiency in this model.”的句子点出研究目标。要求:1)明确陈述本研究拟解决的核心科学问题;

智能AI让学术科研更容易 180

深度学习工具包 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")

交叉编译 Openssl,然后移植到ARM板上

请移步:https://blog.youkuaiyun.com/lingyuncao/article/details/90667781

zgp2917的专栏 795

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

openssl之linux编译

编译前工作         解压源码,例如:openssl-OpenSSL_1_1_1-stable.zip到目录/home/workspace/openssl-OpenSSL_1_1_1-stable。         在父目录创建构建目...

hezhanran的博客 3347

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ARM平台移植openssl1.1.1g

1.openssl简介 在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。Netscape公司在推出第一个Web浏览器的同时,提出了SSL协议标准。其目标是保证两个应用间通信的保密性和可靠性,可在服务器端和用户端同时实现支持。已经成为Internet上保密通讯的工业标准。

qq_36973838的博客 3194

【交叉编译】ARM平台交叉编译|OpenSSL

由于是交叉编译,如不使用该选项,会出现汇编指令不识别的问题,因为openssl默认使用的汇编指令为X86平台下的指令,而一般的交叉编译器使用时ARM平台下的交叉编译器。注意:正在编译之前,需要Makefile中将-m64选项全部删除掉,因为aarch64-linux-gnu-gcc编译器不识别该选项。版权声明:本文为优快云博主「奔跑的码仔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。交叉编译器Compiler:aarch64-linux-gnu-gcc。

guanlizhongxintishi的博客 1484
上一篇: NFS无法挂载,出现错误:reason given by server: Permission denied的解决办法
下一篇: 线程条件变量详解
RICH_BABA
博客等级 码龄17年 51粉丝 17原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值