filesystem capabilities support

本文探讨了能力基于的安全机制以及如何在系统中用文件系统能力替代传统的setuid权限,提供了两种不同领域的安全实践策略。
训练数据保存为deep_convnet_params.pkl,UI使用wxPython编写。卷积神经网络(CNN)是一种专门针对图像、视频等结构化数据设计的深度学习模型,在计算机视觉、语音识别、自然语言处理等多个领域有广泛应用。其核心设计理念源于对生物视觉系统的模拟,主要特点包括局部感知、权重共享、多层级抽象以及空间不变性。 **1. 局部感知与卷积操作** 卷积层是CNN的基本构建块,使用一组可学习的滤波器对输入图像进行扫描。每个滤波器在图像上滑动,以局部区域内的像素值与滤波器权重进行逐元素乘法后求和,生成输出值。这一过程能够捕获图像中的边缘、纹理等局部特征。 **2. 权重共享** 同一滤波器在整个输入图像上保持相同的权重。这显著减少了模型参数数量,增强了泛化能力,并体现了对图像平移不变性的内在假设。 **3. 池化操作** 池化层通常紧随卷积层之后,用于降低数据维度并引入空间不变性。常见方法有最大池化和平均池化,它们可以减少模型对微小位置变化的敏感度,同时保留重要特征。 **4. 多层级抽象** CNN通常包含多个卷积和池化层堆叠在一起。随着网络深度增加,每一层逐渐提取更复杂、更抽象的特征,从底层识别边缘、角点,到高层识别整个对象或场景,使得CNN能够从原始像素数据中自动学习到丰富的表示。 **5. 激活函数与正则化** CNN中使用非线性激活函数来引入非线性表达能力。为防止过拟合,常采用正则化技术,如L2正则化和Dropout,以增强模型的泛化性能。 **6. 应用场景** CNN在诸多领域展现出强大应用价值,包括图像分类、目标检测、语义分割、人脸识别、图像生成、医学影像分析以及自然语言处理等任务。 **7. 发展与演变** CNN的概念起源于20世纪80年代,其影响力在硬件加速和大规模数据集出现后真正显现。经典模型如LeNet-5用于手写数字识别,而AlexNet、VGG、GoogLeNet、ResNet等现代架构推动了CNN技术的快速发展。如今,CNN已成为深度学习图像处理领域的基石,并持续创新。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
# # Copyright (C) 2006-2013 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # include $(TOPDIR)/rules.mk PKG_NAME:=busybox ifeq ($(CONFIG_PACKAGE_BUSYBOX_VERSION),"1.36.1") PKG_VERSION:=1.36.1 PKG_MD5SUM:=0fc591bc9f4e365dfd9ade0014f32561 else PKG_VERSION:=1.19.4 PKG_MD5SUM:=9c0cae5a0379228e7b55e5b29528df8e endif PKG_RELEASE:=6 PKG_FLAGS:=essential PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=http://www.busybox.net/downloads \ http://distfiles.gentoo.org/distfiles/ PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc PKG_BUILD_PARALLEL:=1 include $(INCLUDE_DIR)/package.mk ifeq ($(DUMP),) STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | md5s) endif ifeq ($(CONFIG_PACKAGE_lp5523ctrl),y) LP5523_SUPPORT="y" endif ifeq ($(CONFIG_PACKAGE_wireless-schedule),y) WIRELESS_SCHEDULE_SUPPORT="y" endif ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) BB_MAKE_VERBOSE := V=1 else BB_MAKE_VERBOSE := endif init-y := init-$(CONFIG_BUSYBOX_CONFIG_HTTPD) += httpd init-$(CONFIG_BUSYBOX_CONFIG_CROND) += cron init-$(CONFIG_BUSYBOX_CONFIG_TELNETD) += telnet define Package/busybox SECTION:=TP-LINK CATEGORY:=TP-LINK iplatform apps MAINTAINER:=Nicolas Thill <nico@openwrt.org> TITLE:=Core utilities for embedded Linux URL:=http://busybox.net/ DEPENDS:=+BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc +common +PACKAGE_$(PKG_NAME)_UGLY_LOG:liblog MENU:=1 endef define Package/busybox/description The Swiss Army Knife of embedded Linux. It slices, it dices, it makes Julian Fries. endef define Package/busybox/config ifeq ($(CONFIG_PACKAGE_BUSYBOX_VERSION),"1.36.1") source "$(SOURCE)/Config_1_36_1.in" else source "$(SOURCE)/Config.in" endif config PACKAGE_$(PKG_NAME)_UGLY_LOG bool "Enable ugly log" default y endef define Build/Configure rm -f $(PKG_BUILD_DIR)/.configured* grep 'CONFIG_BUSYBOX_' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_\\(.*\\),\\1\\2,g" > $(PKG_BUILD_DIR)/.config yes '' | $(MAKE) -C $(PKG_BUILD_DIR) \ CC="$(TARGET_CC)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ KBUILD_HAVE_NLS=no \ ARCH="$(ARCH)" \ $(BB_MAKE_VERBOSE) \ oldconfig endef ifdef CONFIG_GCC_VERSION_LLVM TARGET_CFLAGS += -fnested-functions endif LDLIBS:=m crypt TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include export LDFLAGS=$(TARGET_LDFLAGS) ifdef CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC LDLIBS += rpc endif ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)_UGLY_LOG),) TARGET_CFLAGS += -DCONFIG_UGLY_LOG=1 LDLIBS += log endif define Build/Prepare mkdir -p $(PKG_BUILD_DIR) ifeq ($(CONFIG_PACKAGE_BUSYBOX_VERSION),"1.36.1") $(CP) ./src_1_36_1/* $(PKG_BUILD_DIR) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR),) else $(CP) ./src/* $(PKG_BUILD_DIR) endif endef ifdef CONFIG_LINUX_KERNEL_INCLUDE_PATH TARGET_CFLAGS += -I$(LINUX_DIR)/../$(CONFIG_LINUX_KERNEL_INCLUDE_PATH) endif define Build/Compile +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ CC="$(TARGET_CC)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ KBUILD_HAVE_NLS=no \ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \ ARCH="$(ARCH)" \ SKIP_STRIP=y \ LDLIBS="$(LDLIBS)" \ $(BB_MAKE_VERBOSE) \ LP5523_SUPPORT="$(LP5523_SUPPORT)" \ WIRELESS_SCHEDULE_SUPPORT="$(WIRELESS_SCHEDULE_SUPPORT)" \ BUSYBOX_DHCP_OPTION66="$(CONFIG_BUSYBOX_DHCP_OPTION66)" \ BUSYBOX_DHCP_OPTION43="$(CONFIG_BUSYBOX_DHCP_OPTION43)" \ all rm -rf $(PKG_INSTALL_DIR) $(FIND) $(PKG_BUILD_DIR) -lname "*busybox" -exec rm \{\} \; $(MAKE) -C $(PKG_BUILD_DIR) \ CC="$(TARGET_CC)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \ ARCH="$(ARCH)" \ CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \ LDLIBS="$(LDLIBS)" \ $(BB_MAKE_VERBOSE) \ LP5523_SUPPORT="$(LP5523_SUPPORT)" \ WIRELESS_SCHEDULE_SUPPORT="$(WIRELESS_SCHEDULE_SUPPORT)" \ BUSYBOX_DHCP_OPTION66="$(CONFIG_BUSYBOX_DHCP_OPTION66)" \ BUSYBOX_DHCP_OPTION43="$(CONFIG_BUSYBOX_DHCP_OPTION43)" \ install endef define Package/busybox/install $(INSTALL_DIR) $(1)/etc/init.d $(CP) $(PKG_INSTALL_DIR)/* $(1)/ $(INSTALL_DIR) $(1)/etc/crontabs touch $(1)/etc/crontabs/root for tmp in $(init-y); do \ $(INSTALL_BIN) ./filesystem/$$$$tmp $(1)/etc/init.d/$$$$tmp; \ done -rm -rf $(1)/lib64 endef $(eval $(call BuildPackage,busybox))此Makefile编译正常,对比下面这个Makefile出现编译卡住的问题# SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2006-2021 OpenWrt.org include $(TOPDIR)/rules.mk PKG_NAME:=busybox PKG_VERSION:=1.35.0 PKG_RELEASE:=1 PKG_FLAGS:=essential PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://www.busybox.net/downloads \ http://sources.buildroot.net PKG_HASH:=faeeb244c35a348a334f4a59e44626ee870fb07b6884d68c10ae8bc19f83a694 PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_PAM:libpam PKG_BUILD_PARALLEL:=1 PKG_CHECK_FORMAT_SECURITY:=0 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=LICENSE archival/libarchive/bz/LICENSE PKG_CPE_ID:=cpe:/a:busybox:busybox BUSYBOX_SYM=$(if $(CONFIG_BUSYBOX_CUSTOM),CONFIG,DEFAULT) BUSYBOX_IF_ENABLED=$(if $(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_$(1)),$(2)) ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SUID),) PKG_FILE_MODES:=/bin/busybox:root:root:4755 endif include $(TOPDIR)/platform/include/local-development.mk include $(INCLUDE_DIR)/package.mk ifeq ($(DUMP),) STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | $(MKHASH) md5) endif # All files provided by busybox will serve as fallback alternatives by opkg. # There should be no need to enumerate ALTERNATIVES entries here define Package/busybox/Default SECTION:=base CATEGORY:=Base system MAINTAINER:=Felix Fietkau <nbd@nbd.name> TITLE:=Core utilities for embedded Linux URL:=http://busybox.net/ DEPENDS:=+BUSYBOX_CONFIG_PAM:libpam +BUSYBOX_CONFIG_NTPD:jsonfilter USERID:=ntp=123:ntp=123 endef define Package/busybox $(call Package/busybox/Default) CONFLICTS:=busybox-selinux VARIANT:=default endef define Package/busybox-selinux $(call Package/busybox/Default) TITLE += with SELinux support DEPENDS += +libselinux VARIANT:=selinux PROVIDES:=busybox endef define Package/busybox/description The Swiss Army Knife of embedded Linux. It slices, it dices, it makes Julian Fries. endef define Package/busybox/config source "$(SOURCE)/Config.in" endef ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOG)$(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOGD_CFG),) define Package/busybox/conffiles/syslog /etc/syslog.conf endef endif ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_CROND),) define Package/busybox/conffiles/crond /etc/crontabs/ endef endif define Package/busybox/conffiles $(Package/busybox/conffiles/syslog) $(Package/busybox/conffiles/crond) endef Package/busybox-selinux/conffiles = $(Package/busybox/conffiles) ifndef CONFIG_USE_MUSL LDLIBS:=m crypt endif LDLIBS += $(call BUSYBOX_IF_ENABLED,PAM,pam pam_misc pthread) ifeq ($(CONFIG_USE_GLIBC),y) LDLIBS += $(call BUSYBOX_IF_ENABLED,NSLOOKUP,resolv) endif ifeq ($(BUILD_VARIANT),selinux) LDLIBS += selinux sepol endif TARGET_CFLAGS += -flto TARGET_LDFLAGS += -flto=jobserver -fuse-linker-plugin MAKE_VARS := MAKE_FLAGS += \ EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ EXTRA_LDFLAGS="$(TARGET_LDFLAGS)" \ LDLIBS="$(LDLIBS)" \ LD="$(TARGET_CC)" \ SKIP_STRIP=y ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) MAKE_FLAGS += V=1 endif define Build/Configure rm -f $(PKG_BUILD_DIR)/.config touch $(PKG_BUILD_DIR)/.config ifeq ($(DEVICE_TYPE),nas) echo "CONFIG_HDPARM=y" >> $(PKG_BUILD_DIR)/.config endif ifeq ($(BUILD_VARIANT),selinux) cat $(TOPDIR)/$(SOURCE)/selinux.config >> $(PKG_BUILD_DIR)/.config endif grep 'CONFIG_BUSYBOX_$(BUSYBOX_SYM)' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_$(BUSYBOX_SYM)_\\(.*\\),\\1CONFIG_\\2,g" >> $(PKG_BUILD_DIR)/.config yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig endef define Build/Compile $(call Build/Compile/Default, \ CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \ all install \ ) endef define Package/busybox/install $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_DIR) $(1)/usr/sbin $(CP) $(PKG_INSTALL_DIR)/* $(1)/ ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOG)$(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_SYSLOGD_CFG),) touch $(1)/etc/syslog.conf endif ifneq ($(CONFIG_BUSYBOX_CONFIG_SYSLOGD),) $(INSTALL_BIN) ./files/syslogd.init $(1)/etc/init.d/syslogd ifeq ($(CONFIG_BUSYBOX_CONFIG_LOGREAD)$(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_FEATURE_IPC_SYSLOG),) $(INSTALL_BIN) ./files/logread $(1)/sbin endif endif ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_CROND),) $(INSTALL_BIN) ./files/cron $(1)/etc/init.d/cron $(INSTALL_DIR) $(1)/etc/crontabs endif ifneq ($(CONFIG_BUSYBOX_$(BUSYBOX_SYM)_NTPD),) $(INSTALL_BIN) ./files/sysntpd $(1)/etc/init.d/sysntpd $(INSTALL_BIN) ./files/ntpd-hotplug $(1)/usr/sbin/ntpd-hotplug $(INSTALL_DIR) $(1)/etc/capabilities $(1)/usr/share/acl.d $(INSTALL_DATA) ./files/ntpd.capabilities $(1)/etc/capabilities/ntpd.json $(INSTALL_DATA) ./files/ntpd_acl.json $(1)/usr/share/acl.d/ntpd.json endif -rm -rf $(1)/lib64 endef Package/busybox-selinux/install = $(Package/busybox/install) $(eval $(call BuildPackage,busybox)) $(eval $(call BuildPackage,busybox-selinux))
11-24
<think> 我们分析两个Makefile的主要差异,特别是导致编译卡住(循环打印配置选项)的部分。 第一个Makefile(正常): Build/Configure 部分: 它从顶层目录的.config中提取CONFIG_BUSYBOX_开头的配置项,并去掉前缀,生成busybox的.config。 然后使用`yes '' | make oldconfig`,这样对于新选项会使用默认值(空输入表示接受默认)。 第二个Makefile(卡住): Build/Configure 部分: 它先创建空的.config,然后根据设备类型(nas)添加一个配置项,如果是selinux变体则追加selinux.config。 然后从顶层目录的.config中提取CONFIG_BUSYBOX_$(BUSYBOX_SYM)($(BUSYBOX_SYM)可能是CONFIG或DEFAULT)的配置项,并去掉前缀(例如CONFIG_BUSYBOX_CONFIG_XXX变成CONFIG_XXX)追加到.config。 然后运行`yes 'n' | make oldconfig`,这意味着对于所有新选项都回答'n'(即不启用)。 问题分析: 在第二个Makefile中,使用`yes 'n'`来回答所有新选项。但是,在编译过程中,如果遇到一个需要选择(比如多选一)的选项,而该选项在.config中并没有被设置,那么`oldconfig`会进入交互式选择。而`yes 'n'`只是不断输入'n',但有些选项不是Y/N的问题,比如“What kind of applet links to install”是一个数字选择(1-4)。输入'n'对于数字选择是无效的,因此会不断提示,造成死循环。 具体到问题中的循环打印: 在BusyBox的配置中,有一个选项是“What kind of applet links to install”,它是一个choice,有4个选项,要求输入1-4。而`yes 'n'`会一直输入'n',这个选项无法被正确设置,因此会不断重复提示,造成死循环。 解决方案: 我们需要确保在非交互式编译时,对于choice类型的选项,我们也要提供默认值(或者确保在.config中已经设置)。在第一个Makefile中,它使用`yes ''`,这样对于choice选项,它会自动选择默认值(通常是第一个选项)。而第二个Makefile使用`yes 'n'`,对于choice选项无效。 修改建议: 将第二个Makefile中的`yes 'n'`改为`yes ''`,这样对于所有新选项都会使用默认值(包括choice选项)。或者,我们可以像第一个Makefile那样,在生成.config的时候,确保所有必要的选项都已经设置(特别是choice选项)。 具体修改: 找到第二个Makefile(卡住的那个)的Build/Configure部分,将: yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig 改为: yes '' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig 这样,对于所有新出现的配置选项,都会自动选择默认值,从而避免因为choice选项等待输入而卡住。 另外,我们也可以考虑在生成.config的时候,确保那个特定的choice选项已经被设置。例如,在生成.config之后,我们可以追加一行: echo "CONFIG_INSTALL_APPLET_SYMLINKS=y" >> $(PKG_BUILD_DIR)/.config 或者(根据需求选择一个) echo "CONFIG_INSTALL_APPLET_DONT=y" >> $(PKG_BUILD_DIR)/.config 但是,由于我们不知道用户具体需要哪个选项,所以使用默认值(即通过`yes ''`选择第一个)更为通用。 注意:第一个Makefile中也是使用`yes ''`。 因此,我们得出结论:第二个Makefile中的`yes 'n'`是导致循环卡住的原因,应改为`yes ''`。 此外,我们还需要注意,在第一个Makefile中,它使用的是: yes '' | $(MAKE) ... oldconfig 而第二个Makefile中,在运行oldconfig时还传递了$(MAKE_FLAGS)。这可能是另一个不同点,但通常$(MAKE_FLAGS)中可能包含一些变量定义,不会影响配置过程。 所以,我们只需要修改输入为`yes ''`即可。 如果修改后仍然有问题,可以检查是否还有其他choice选项没有被设置,但使用`yes ''`应该能解决。 总结:将第二个Makefile中的`yes 'n'`替换为`yes ''`。 </think>分析两个Makefile差异及解决编译卡住问题: ### 关键差异分析 | 功能点 | 正常Makefile (1.19.4/1.36.1) | 卡住Makefile (1.35.0) | |--------------------|-------------------------------------------|--------------------------------------------| | **配置生成方式** | `grep提取配置 → sed处理 → 直接注入` | `创建空配置 → 追加配置 → 交互式确认` | | **交互处理** | `yes '' \| make oldconfig` (自动确认) | `yes 'n' \| make oldconfig` (强制选否) | | **选项前缀** | 使用`CONFIG_BUSYBOX_`统一前缀 | 使用动态`BUSYBOX_SYM`变量前缀 | | **choice选项处理** | 通过预配置避免choice交互 | 未预置choice选项导致循环 | ### 问题根源定位 1. **交互式配置冲突**: `yes 'n'`强制对所有新选项选"No",但遇到**choice类型选项**(如applet链接方式)时: - `n`对数字选择项无效 - 配置系统陷入等待有效输入的循环 2. **选项前缀不一致**: `CONFIG_BUSYBOX_$(BUSYBOX_SYM)_XXX`动态前缀导致部分配置未正确提取 ### 解决方案 #### ✅ 修改配置生成逻辑 ```makefile # 替换原Build/Configure段 define Build/Configure rm -f $(PKG_BUILD_DIR)/.config # 统一提取所有BUSYBOX配置项(兼容动态前缀) grep 'CONFIG_BUSYBOX_' $(TOPDIR)/.config | \ sed -e "s/\(# \)\?CONFIG_BUSYBOX_.*_\(.*\)/\1CONFIG_\2/g" > $(PKG_BUILD_DIR)/.config # 预置choice选项默认值 echo "CONFIG_INSTALL_APPLET_SYMLINKS=y" >> $(PKG_BUILD_DIR)/.config # 非交互式确认(空输入接受默认) yes '' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig endef ``` #### ✅ 补充必要预配置 在配置提取后添加: ```makefile # 确保choice选项有默认值 $(if $(CONFIG_BUSYBOX_INSTALL_APPLET), \ echo "CONFIG_$(subst CONFIG_BUSYBOX_,,$(CONFIG_BUSYBOX_INSTALL_APPLET))=y" >> $(PKG_BUILD_DIR)/.config, \ echo "CONFIG_INSTALL_APPLET_SYMLINKS=y" >> $(PKG_BUILD_DIR)/.config \ ) ``` #### ✅ 修改交互策略 ```diff - yes 'n' | $(MAKE) ... oldconfig + yes '' | $(MAKE) ... oldconfig # 接受所有默认值 ``` ### 验证步骤 1. 清理历史配置: ```bash make package/busybox/clean rm -rf build_dir/target-*/busybox-* ``` 2. 预生成关键配置: ```bash echo "CONFIG_BUSYBOX_INSTALL_APPLET_SYMLINKS=y" >> .config ``` 3. 启动编译: ```bash make package/busybox/compile V=s ``` > 修改后原理: > 通过`yes ''`自动接受默认值 + 预置choice选项,避免交互阻塞,同时保持配置兼容性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值