4.1用户空间RTOSAPI

4.1 用户空间RTOS API

4.1.1 用户空间RTOS API列表

本章对Xenomai 3编写,描述应用程序的构建与运行方式。文中"应用程序"特指基于Xenomai 3库的用户空间程序。

Xenomai 3通过将实时核心Cobalt与Linux内核并行运行,形成双内核架构。该实时扩展层内建于Linux内核,专门处理时间敏感型任务如中断处理和实时线程调度。Cobalt核心的执行优先级始终高于原生内核。

Xenomai 3提供的所有RTOS API如下表所示:

API 名称描述
POSIXXenomai 3实现了POSIX接口,便于移植与POSIX接口兼容的程序。
Alchemy‌此为在 Xenomai 2.x Native API 基础上的实现,和 Xenomai 2 有大量的重叠,有一些过渡库,具体情况可以参考 libtrank ,兼容Xenomai 2.x生态。
pSOS‌pSOS™ 为Wind River Systems, Inc.的注册商标,原为Integrated System, Inc. 开发,后被兼并,从Vxworks 5.5 开始,主要特点已经被融入Vxworks,支持嵌入式实时操作系统功能。
VxWorks‌VxWorks™ 为Wind River Systems, Inc.的注册商标,提供工业级实时操作系统服务。

Xenomai 3提供的上述RTOS API都具备实时能力。通过严格的优先级隔离机制,确保实时任务响应时间达到微秒级精度。

4.1.2 用户空间RTOS API框架

在这里插入图片描述

1. 蓝色部分Cobalt core

如图中蓝色部分所示,Cobalt core是Xenomai3中实时内核的名字,运行在内核空间。Cobalt core的代码实现在kernel/cobalt目录。

Cobalt是金属元素钴的英文名称,它的元素符号是Co,刚好与co-kernel相同,有点意思吧!

金属元素钴(Cobalt)的本色是带有光泽的银白色。然而,当钴用于各种应用中时,它可以呈现出不同的颜色,这取决于它的化合物和使用的形式。例如,在陶瓷和玻璃工业中,钴化合物用来制造出标志性的深蓝色,即所谓的钴蓝

大家注意过吗,Xenoami官网的主题色就是蓝色的。

2. 红色部分libcobalt

如图中红色部分所示,Xenomai3在用户空间定义了libcobalt库,通过系统调用与内核空间的Cobalt core沟通。libcobalt库代码实现在lib/cobalt目录。

特别注意一下旁边括号里面的文字备注:POSIX subset + extensions

  • POSIX subset表明Xenomai 3实现了POSIX的若干子集,包括:

    • POSIX 1003.1 (系统应用编程接口, Base Definitions)
    • POSIX 1003.1b (实时扩展, Real-time Extensions)
    • POSIX 1003.1c(线程接口)
    • POSIX 1003.1g (套接字和网络)
    • POSIX 1003.1q (消息队列)
  • extensions代表某些接口不属于 POSIX 标准,但对于编程来说必不可少:

    • _np 后缀的函数例如pthread_setname_np
    • GNU _chk 函数,例如__printf_chk
    • 标准 C 库中的函数(如 printffwrite 等)虽然在 POSIX 系统中可用,但它们属于 ISO C 标准,而非 POSIX 标准。

总而言之,libcobalt为用户空间应用程序提供了POSIX real-time API。在Xenomai体系中,用户空间RTOS API也被称为skin,所以POSIX real-time API一般都简称为POSIX skin

3. 橙色部分copperplate interface

Xenomai 3在libcobalt库中,没有把所有的RTOS API都挨个实现一遍,原生仅仅提供了POSIX skin。在libcobalt库的基础上,实现了一个接口转换层即copperplate interface,可以把其它RTOS API(也称为skin)转换为对POSIX skin的调用,从而在用户层提供其它non-POSIX real-time API

接口转换层copperplate interface代码实现在lib/copperplate目录。默认情况下,copperplate interface总是会自动初始化(Auto-initialization),保证其它接口可以正常工作。

单词copperplate的本意是铜版印刷体,是一种优美圆润的英文书法字体,这个名字非常的无厘头。但是单词copper是金属铜的意思,与接口转换层非常贴切。铜元素是过渡元素,这个过渡二字是不是非常符合copperplate interface的定位?

观察一下图中copperplate interface的背景色,是红色与黄色混合之后的红橙色。纯铜是柔软的金属,表面刚切开时为红橙色,与背景色一致,是不是恍然大悟?

接口转换层copperplate interface在图中起到了承上启下的作用。向上承接的是红色的libcobalt,向下开启的是黄色的non-POSIX real-time API,包括Alchemy‌VxWorks‌pSOS‌ RTOS API接口。

4. 黄色部分non-POSIX real-time API

non-POSIX real-time API,包括Alchemy‌VxWorks‌pSOS‌ RTOS API接口。这些接口在Xenomai3中并不是原生实现的,而是通过接口转换层copperplate interface模拟实现的!

这些RTOS API接口,也可以称为不同的skin,例如Alchemy‌ skinVxWorks skinpSOS skin。它们的代码实现在lib/alchemy目录,lib/vxwork目录和lib/psos目录。

特别关注一下Alchemy‌ skin,它兼容Xenomai2/native接口。

5. 白色部分Applications

Applications顾名思义就是用户空间应用程序。对于应用程序而言,有很多种skin可以选择。

如果应用程序是从其它RTOS迁移到Xenomai 3,那么自然而然要选择相匹配的skin

如果是新开发一个应用程序,那么建议使用POSIX skin,可以避免使用转换层copperplate interface,减少复杂度。

在编译和链接阶段,具体要怎么对接不同的skin呢?xeno-config横空出世!

xeno-config是一个辅助脚本,可以为使用Xenomai库的应用程序提供正确的编译和链接标志。通过这个工具,开发者可以轻松获取所需的编译器选项和链接器参数,确保应用程序能够正确地集成到Xenomai环境中。

4.1.3 使用xeno-config获取编译和链接参数

在之前的章节中,xenomai-v3.2.4编译后,通过make install临时安装到了/root/xenomai/xenomai-v3.2.4-install目录。xeno-config脚本位于usr/xenomai/bin/xeno-config

xeno-config脚本通过标准化编译参数的方式,简化了 Xenomai 实时应用程序的构建过程,确保开发者可以专注于业务逻辑而无需手动维护复杂的编译环境配置。

对于不同的skinxeno-config可以通过传递特定的参数来调整输出的编译和链接标志,包含路径、宏定义等。

注意,如果是交叉编译环境,在执行xeno-config脚本时,需让环境变量DESTDIR指向xenomai的临时安装目录。

其基本用法如下参考xeno-config --help

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --help

Usage xeno-config OPTIONS
Options :
        --help
        --v,--verbose
        --version
        --cc
        --ccld
        --arch
        --prefix
        --[skin=]posix|vxworks|psos|alchemy|rtdm|smokey|cobalt
        --auto-init|auto-init-solib|no-auto-init
        --mode-check|no-mode-check
        --cflags
        --ldflags
        --lib*-dir|libdir|user-libdir
        --core
        --info
        --compat

虽然xeno-config还可以用于获取其它信息,但是本章仅聚焦在如何获取不同skin的编译和链接参数,主要涉及--skin--cflags--ldflags--compat

  • –[skin=]posix, alchemy, rtdm, psos, vxworks, smokey, cobalt:选择要为其打印信息的API/skin。skin=前缀是可选的,可以省略,例如--posix等同于--skin=posix,选择POSIX skin。
  • –cflags:输出编译基于所选Xenomai API/skin的应用程序所需的C编译器命令行选项(CFLAGS)。
  • –ldflags:输出链接基于所选Xenomai API/skin的应用程序所需的C编译器命令行选项(LDFLAGS)。
  • –compat:此开关影响Alchemy和POSIX API,为所选的API/skin启用Xenomai 2.x兼容模式。
1. POSIX skin编译与链接参数

下面展示如何通过--skin=posix获取POSIX skin编译与链接参数。注意,--skin=rtdm与传递--skin=posix严格等效。

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=posix --cflags
-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -D__COBALT_WRAP__

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=posix --ldflags
-Wl,--no-as-needed -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/cobalt.wrappers -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers  /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

POSIX skin必须解决一个问题:

基于POSIX API编写的应用程序源码中,会使用类似于pthread_create这样的标准接口。在构建应用程序二进制可执行文件时,会同时链接libcobaltlibpthread库。为了如何保证pthread_create链接到libcobalt库呢?

Xenomai使用了一个非常巧妙的方法,关键点在于链接参数:

-Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/cobalt.wrappers

其中,lib/cobalt/cobalt.wrappers文件的部分内容截取如下:

--wrap pthread_attr_init
--wrap pthread_create
--wrap pthread_setschedparam
--wrap pthread_getschedparam
--wrap pthread_setschedprio
--wrap pthread_yield
...snip...

--wrap是一种用于链接器(linker)的技术,通常在 GCC 编译环境中使用。它允许你重新定义或者扩展已有的函数功能,而不需要修改原始代码。当你使用 --wrap symbol 选项时,链接器遇到对原始 symbol 的调用时,它实际上会引用 __wrap_symbol 函数。

pthread_create为例,在链接的过程中,会隐式地链接libcoablt库定义的__wrap_pthread_create函数。

如果不使用这个方法,那么势必要修改应用程序原始代码,显示地调用__wrap_pthread_create函数。这种方式的缺点非常明显,破坏了应用程序的可移植性,带来了额外的开发与维护成本。如果因为不可抗拒的原因,必须选择显示地调用__wrap_pthread_create函数,那么使用--skin=cobalt来获取编译和链接参数。

如何理解--skin=cobalt

所有带有__wrap_前缀的函数,都有一个__cobalt_前缀的别名,这些函数在Xenomai中也可以被称为Cobalt API。例如,__wrap_pthread_create函数在libcoablt库中还有一个别名__cobalt_pthread_create

2. VxWorks skin编译与链接参数

下面展示如何通过--skin=vxworks获取VxWorks skin编译与链接参数。

cd /root/xenomai/xenomai-v3.2.4-install

告诉编译器,skin是vxworks,如何找到头文件和必要的宏定义,还有兼容性选项(如 -D_REENTRANT 线程可重入,保证多线程运行安全)

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=vxworks --cflags

输出

-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/vxworks

告诉链接器,skin 是vxWorks时, 如何找到 Xenomai 程序所需要的链接库(libcobalt、libmodechk和libpthread等)和必须的链接参数。注意这里 libmodechk 是用来监控 in-band/out-of-band 运行模式切换。

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=vxworks --ldflags

输出

-Wl,--no-as-needed -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers -lvxworks -lcopperplate /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

POSIX skin的基础上,有两个显著的变化:

  • 链接时增加-lvxworks,确保链接VxWorks skin。以下是按include/vxworks/下头文件进行VxWorks API 分类,每类仅列出部分代表性函数:

    • 任务管理taskSpawn, taskDelete, taskDelay;
    • 中断服务intConnect, intLock, intUnlock;
    • 消息队列msgQCreate, msgQSend, msgQReceive;
    • 信号量semBCreate, semMCreate, semTake, semGive;
    • 其他
  • 链接时增加-lcopperplate

    • libcopperplate库实现了一个接口转换层copperplate interface,可以把VxWorks skin转换为对POSIX skin的调用。
    • xeno-config脚本默认启用接口转换层copperplate interface的自动初始化功能。
3. pSOS skin编译与链接参数

下面展示如何通过--skin=psos获取pSOS skin编译与链接参数。

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=psos --cflags
-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/psos

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=psos --ldflags
-Wl,--no-as-needed -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers -lpsos -lcopperplate /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

POSIX skin的基础上,有两个显著的变化:

  • 链接时增加-lpsos,确保链接pSOS skin。以下是按include/psos/psos.h的 pSOS API 分类,每类仅列出部分代表性函数:

    • 任务管理t_create, t_delete, t_start, t_suspend, t_resume, t_setpri
    • 信号量管理sm_create, sm_delete, sm_p, sm_v
    • 消息队列管理q_create, q_send, q_receive, q_delete
    • 变长消息队列管理q_vcreate, q_vsend, q_vreceive
    • 事件管理ev_send, ev_receive
    • 内存分区管理pt_create, pt_getbuf, pt_retbuf, pt_delete
    • 区域管理(动态内存)rn_create, rn_getseg, rn_retseg, rn_delete
    • 定时器管理tm_evafter, tm_evwhen, tm_wkafter, tm_cancel
    • 对象查找与标识t_ident, sm_ident, q_ident, pt_ident, rn_ident
    • 优先级转换函数psos_task_normalize_priority, psos_task_denormalize_priority
  • 链接时增加-lcopperplate

    • libcopperplate库实现了一个接口转换层copperplate interface,可以把pSOS skin转换为对POSIX skin的调用。
    • xeno-config脚本默认启用接口转换层copperplate interface的自动初始化功能。
4. Alchemy skin编译与链接参数

下面展示如何通过--skin=alchemy获取Alchemy skin编译与链接参数。

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=alchemy --cflags
-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/alchemy

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=alchemy --ldflags
-Wl,--no-as-needed -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers -lalchemy -lcopperplate /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

POSIX skin的基础上,有两个显著的变化:

  • 链接时增加-lalchemy,确保链接Alchemy skin。以下是按include/alchemy/下头文件进行Alchemy API 分类,每类仅列出部分代表性函数:

    • 任务管理 (task.h):rt_task_create(), rt_task_start(), rt_task_set_priority()
    • 信号量 (sem.h):rt_sem_create(), rt_sem_p(), rt_sem_v()
    • 互斥锁 (mutex.h):rt_mutex_create(), rt_mutex_acquire(), rt_mutex_release()
    • 事件机制 (event.h):rt_event_create(), rt_event_signal(), rt_event_wait()
    • 消息队列 (queue.h):rt_queue_create(), rt_queue_send(), rt_queue_receive()
    • 条件变量 (cond.h):rt_cond_create(), rt_cond_wait(), rt_cond_signal()
    • 内存管理 (heap.h):rt_heap_create(), rt_heap_alloc(), rt_heap_free()
    • 定时器 (timer.h/alarm.h):rt_timer_create(), rt_alarm_start(), rt_timer_sleep()
    • 管道通信 (pipe.h):rt_pipe_create(), rt_pipe_read(), rt_pipe_write()
    • 缓冲区管理 (buffer.h):rt_buffer_create(), rt_buffer_read(), rt_buffer_write()
  • 链接时增加-lcopperplate

    • libcopperplate库实现了一个接口转换层copperplate interface,可以把Alchemy skin转换为对POSIX skin的调用。
    • xeno-config脚本默认启用接口转换层copperplate interface的自动初始化功能。
5. --compat获取与Xenomai 2兼容的编译与链接参数

--compat参数影响Alchemy和POSIX API,为所选的API/skin启用Xenomai 2.x兼容模式。

Xenomai 2 skinXenomai 3 编译链接参数说明
Native–skin=alchemy --compat等同于 --skin=native
POSIX–skin=posix --compat

注意,xeno-config出于向后兼容的目的,接受 --skin=native--natvie

以兼容Xenomai 2的Native skin为例,获取其在Xenomai 3 的编译链接参数。

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=alchemy --compat --cflags
-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/trank -D__XENO_COMPAT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/alchemy

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=alchemy --compat --ldflags
-Wl,--no-as-needed -ltrank -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers -lalchemy -lcopperplate /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

主要变化是增加了-ltrank,引入了trank库。

trankTransition Kit的缩写。它包含了一系列的包装器和服务,帮助开发者更轻松地将使用Xenomai 2.x开发的应用程序迁移到Xenomai 3.x。这个工具包提供了源代码级别的兼容性,使得原本依赖于Xenomai 2.x的POSIX和原生API的应用程序能够在Xenomai 3.x环境中继续运行。

6. 特殊选项--skin=smokey

在Xenomai实时系统框架中,Smokey 是一个专门用于内核空间测试的子系统。通过xeno-config --skin=smokey可以获取测试专用编译和链接参数。

cd /root/xenomai/xenomai-v3.2.4-install

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=smokey --cflags
-I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/cobalt -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/include/smokey

DESTDIR=$(pwd) usr/xenomai/bin/xeno-config --skin=smokey --ldflags
-Wl,--no-as-needed -Wl,@/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/modechk.wrappers -lsmokey -lcopperplate /root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib/dynlist.ld -L/root/xenomai/xenomai-v3.2.4-install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

冒烟测试(Smoke Testing),有时候也称为“smokey”测试,是一种初步的软件测试方法,用于确认刚刚构建的软件版本是否稳定到足以进行进一步的详细测试。这个术语来源于硬件行业的做法,在新硬件组装完成后首次通电时,检查是否有部件因过热而冒烟的现象。

冒烟测试的通常覆盖了软件的主要模块和关键路径,通过自动化脚本执行,执行速度快。冒烟测试对于保证软件质量、减少修复成本以及加速开发周期具有重要作用。

内容概要:本文围绕SecureCRT自动化脚本开发在毕业设计中的应用,系统介绍了如何利用SecureCRT的脚本功能(支持Python、VBScript等)提升计算机、网络工程等相关专业毕业设计的效率与质量。文章从关键概念入手,阐明了SecureCRT脚本的核心对象(如crt、Screen、Session)及其在解决多设备调试、重复操作、跨场景验证等毕业设计常见痛点中的价值。通过三个典型应用场景——网络设备配置一致性验证、嵌入式系统稳定性测试、云平台CLI兼容性测试,展示了脚本的实际赋能效果,并以Python实现的交换机端口安全配置验证脚本为例,深入解析了会话管理、屏幕同步、输出解析、异常处理和结果导出等关键技术细节。最后展望了低代码化、AI辅助调试和云边协同等未来发展趋势。; 适合人群:计算机、网络工程、物联网、云计算等相关专业,具备一定编程基础(尤其是Python)的本科或研究生毕业生,以及需要进行设备自动化操作的科研人员; 使用场景及目标:①实现批量网络设备配置的自动验证与报告生成;②长时间自动化采集嵌入式系统串口数据;③批量执行云平台CLI命令并分析兼容性差异;目标是提升毕业设计的操作效率、增强实验可复现性与数据严谨性; 阅读建议:建议读者结合自身毕业设计课题,参考文中代码案例进行本地实践,重点关注异常处理机制与正则表达式的适配,并注意敏感信息(如密码)的加密管理,同时可探索将脚本与外部工具(如Excel、数据库)集成以增强结果分析能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值