[嵌入式系统-65]:RT-Thread-组件:FinSH控制台, 用户与RT Thread OS实时命令行交互工具

目录

FinSH 控制台

1. FinSH 简介

2. FinSH 内置命令 - 内核代码自身提供的命令

显示线程状态

显示信号量状态

显示事件状态

显示互斥量状态

显示邮箱状态

显示消息队列状态

显示内存池状态

显示定时器状态

显示设备状态

显示动态内存状态

3. 自定义 FinSH 命令 - 用户新增加的命令

自定义 msh 命令

自定义命令重命名

4. FinSH 功能配置

5. FinSH 应用示例

5.1 不带参数的 msh 命令示例

5.2 带参数的 msh 命令示例

6. FinSH 移植


FinSH 控制台

在计算机发展的早期,图形系统出现之前,没有鼠标,甚至没有键盘。那时候人们如何与计算机交互呢?最早期的计算机使用打孔的纸条向计算机输入命令,编写程序。后来随着计算机的不断发展,显示器、键盘成为计算机的标准配置,但此时的操作系统还不支持图形界面计算机先驱们开发了一种软件,它接受用户输入的命令,解释之后,传递给操作系统,并将操作系统执行的结果返回给用户。这个程序像一层外壳包裹在操作系统的外面,所以它被称为 shell。

嵌入式设备通常需要将开发板与 PC 机连接起来通讯,常见连接方式包括:串口、USB、以太网、Wi-Fi 等。一个灵活的 shell 也应该支持在多种连接方式上工作。有了 shell,就像在开发者和计算机之间架起了一座沟通的桥梁,开发者能很方便的获取系统的运行情况,并通过命令控制系统的运行。特别是在调试阶段有了 shell,开发者除了能更快的定位到问题之外,也能利用 shell 调用测试函数,改变测试函数的参数,减少代码的烧录次数,缩短项目的开发时间。

FinSH 是 RT-Thread 的命令行组件(shell),正是基于上面这些考虑而诞生的,FinSH 的发音为 [ˈfɪnʃ]。读完本章,我们会对 FinSH 的工作方式以及如何导出自己的命令到 FinSH 有更加深入的了解。

1. FinSH 简介

FinSH 是 RT-Thread 的命令行组件,提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,硬件拓扑结构如下图所示:

FinSH 硬件连接图

用户在控制终端输入命令,控制终端通过串口、USB、网络等方式将命令传给目标设备里的 FinSHFinSH 会读取设备输入命令,解析并自动扫描内部函数表,寻找对应函数名执行函数后输出回应,回应通过原路返回,将结果显示在控制终端上。因此,FinSH可以执行/调用任何函数!!!

当使用串口连接设备与控制终端时,FinSH 命令的执行流程,如下图所示:

FinSH 命令执行流程图

FinSH 支持权限验证功能,系统在启动后会进行权限验证,只有权限验证通过,才会开启 FinSH 功能,提升系统输入的安全性。

备注:

FinSH本身是一个内核组件的线程,该线程会解析命令,并把命令解析成特定的函数调用。

msh />list_thread
thread   cpu pri  status      sp     stack size max used left tick  error
-------- --- ---  ------- ---------- ----------  ------  ---------- ---
tshell     0  20  running 0x00000188 0x00001000    18%   0x00000005 000
aio      N/A  16  suspend 0x0000008c 0x00000800    07%   0x0000000a 000
sys_work N/A  23  suspend 0x0000008c 0x00000800    55%   0x0000000a 000
mmcsd_de N/A  22  suspend 0x000000b8 0x00000400    46%   0x00000014 000
tcpip    N/A  10  suspend 0x000000f4 0x00000400    93%   0x00000011 000
etx      N/A  12  suspend 0x000000b4 0x00000400    23%   0x00000010 000
erx      N/A  12  suspend 0x000000b8 0x00000400    66%   0x00000010 000
tidle1   N/A  31  ready   0x00000048 0x00000400    07%   0x00000020 000
tidle0   N/A  31  ready   0x00000064 0x00000400    21%   0x0000001b 000
timer    N/A   4  suspend 0x00000080 0x00000400    21%   0x0000000a 000
msh />

FinSH 支持自动补全、查看历史命令等功能,通过键盘上的按键可以很方便的使用这些功能,FinSH 支持的按键如下表所示:

按键功能描述
Tab 键当没有输入任何字符时按下 Tab 键将会打印当前系统支持的所有命令。若已经输入部分字符时按下 Tab 键,将会查找匹配的命令,也会按照文件系统的当前目录下的文件名进行补全,并可以继续输入,多次补全
↑↓键上下翻阅最近输入的历史命令
退格键删除符
←→键向左或向右移动标

FinSH 支持命令行模式,此模式又称为 msh(module shell),msh 模式下,FinSH 与传统 shell(dos/bash)执行方式一致,例如,可以通过 cd / 命令将目录切换至根目录。

msh 通过解析,将输入字符分解成以空格区分开的命令和参数。其命令执行格式如下所示:

command [arg1] [arg2] [...]

其中 command 既可以是 RT-Thread 内置的命令,也可以是可执行的文件。

2. FinSH 内置命令 - 内核代码自身提供的命令

在 RT-Thread 中默认内置了一些 FinSH 命令,在 FinSH 中输入 help 后回车或者直接按下 Tab 键,就可以打印当前系统支持的所有命令。

msh 模式下,按下 Tab 键后可以列出当前支持的所有命令。默认命令的数量不是固定的,RT-Thread 的各个组件会向 FinSH 输出一些命令。例如,当打开 DFS 组件时,就会把 ls,cp,cd 等命令加到 FinSH 中,方便开发者调试。

以下为按下 Tab 键后打印出来的当前支持的所有显示 RT-Thread 内核状态信息的命令,左边是命令名称,右边是关于命令的描述:

msh />
RT-Thread shell commands:
pin              - pin [option]
reboot           - Reboot System
help             - RT-Thread shell help.
ps               - List threads in the system.
free             - Show the memory usage in the system
clear            - clear the terminal screen
version          - show RT-Thread version information
list             - list objects


msh />list
Usage: list [options]
[options]:
    thread     - list threads
    timer      - list timers
    sem        - list semaphores
    mutex      - list mutexs
    event      - list events
    mailbox    - list mailboxs
    msgqueue   - list message queues
    memheap    - list memory heaps
    mempool    - list memory pools
    device     - list devices
    fd         - list file descriptors
msh />
复制错误复制成功

这里列出输入常用命令后返回的字段信息,方便开发者理解返回的信息内容。

显示线程状态

使用 ps 或者 list thread 命令来列出系统中的所有线程信息,包括线程优先级、状态、栈的最大使用量等。

msh />list thread
thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
tshell    20  running 0x00000160 0x00001000    15%   0x00000003 OK
aio      128  suspend 0x00000084 0x00000800    06%   0x0000000a OK
sys work  23  suspend 0x00000084 0x00000800    06%   0x0000000a OK
tidle0   255  ready   0x0000005c 0x00001000    04%   0x00000016 OK
timer      4  suspend 0x00000078 0x00000400    11%   0x00000009 OK复制错误复制成功

list thread 返回字段的描述:

字段描述
thread线程的名称
pri线程的优先级
status线程当前的状态
sp线程当前的栈位置
stack size线程的栈大小
max used线程历史中使用的最大栈位置
left tick线程剩余的运行节拍数
error线程的错误码

显示信号量状态

使用 list sem 命令来显示系统中所有信号量信息,包括信号量的名称、信号量的值和等待这个信号量的线程数目。

msh />list sem
semaphor v   suspend thread
-------- --- --------------
shrx     000 0
sem_sd0  001 0
psem     001 0
pmq      001 0
wqueue   000 0
sd_ack   000 0
wqueue   000 0复制错误复制成功

list sem 返回字段的描述:

字段描述
semaphore信号量的名称
v信号量当前的值
suspend thread等待这个信号量的线程数目

显示事件状态

使用 list event 命令来显示系统中所有的事件信息,包括事件名称、事件的值和等待这个事件的线程数目。

msh />list event
event      set    suspend thread
-----  ---------- --------------复制错误复制成功

list event 返回字段的描述:

字段描述
event事件集的名称
set事件集中当前发生的事件
suspend thread在这个事件集中等待事件的线程数目

显示互斥量状态

使用 list mutex 命令来显示系统中所有的互斥量信息,包括互斥量名称、互斥量的所有者和所有者在互斥量上持有的嵌套次数等。

msh />list mutex
mutex      owner  hold suspend thread priority
-------- -------- ---- -------------- --------
fat0     (NULL)   0000 0              255
sd_bus_l (NULL)   0000 0              255
fdlock   (NULL)   0000 0              255
fslock   (NULL)   0000 0              255
dfs_mgr  (NULL)   0000 0              255
heap     (NULL)   0000 0              255复制错误复制成功

list mutex 返回字段的描述:

字段描述
mutxe互斥量的名称
owner当前持有互斥量的线程
hold持有者在这个互斥量上嵌套持有的次数
suspend thread等待这个互斥量的线程数目
priority持有线程的优先级

显示邮箱状态

使用 list mailbox 命令显示系统中所有的邮箱信息,包括邮箱名称、邮箱中邮件的数目和邮箱能容纳邮件的最大数目等。

msh />list mailbox
mailbox  entry size suspend thread
-------- ----  ---- --------------
mmcsdhot 0001  0004 0
mmcsdmb  0000  0004 1:mmcsd_de复制错误复制成功

list mailbox 返回字段的描述:

字段描述
mailbox邮箱的名称
entry邮箱中包含的邮件数目
size邮箱能够容纳的最大邮件数目
suspend thread等待这个邮箱的线程数目

显示消息队列状态

使用 list msgqueue 命令来显示系统中所有的消息队列信息,包括消息队列的名称、包含的消息数目和等待这个消息队列的线程数目。

msh />list msgqueue
msgqueue entry suspend thread
-------- ----  --------------复制错误复制成功

list msgqueue 返回字段的描述:

字段描述
msgqueue消息队列的名称
entry消息队列当前包含的消息数目
suspend thread等待这个消息队列的线程数目

显示内存池状态

使用 list mempool 命令来显示系统中所有的内存池信息,包括内存池的名称、内存池的大小和最大使用的内存大小等。

msh />list mempool
mempool block total free suspend thread
------- ----  ----  ---- --------------
signal  0012  0032  0032 0复制错误复制成功

list mempool 返回字段的描述:

字段描述
mempool内存池名称
block内存块大小
total总内存块
free空闲内存块
suspend thread等待这个内存池的线程数目

显示定时器状态

使用 list timer 命令来显示系统中所有的定时器信息,包括定时器的名称、是否是周期性定时器和定时器超时的节拍数等。

msh />list timer
timer     periodic   timeout    activated     mode
-------- ---------- ---------- ----------- ---------
tshell   0x00000000 0x00000000 deactivated one shot
aio      0x00000000 0x00000000 deactivated one shot
mmcsd_de 0x00000001 0x0000000d deactivated one shot
sys work 0x00000000 0x00000000 deactivated one shot
tidle0   0x00000000 0x00000000 deactivated one shot
timer    0x00000000 0x00000000 deactivated one shot
current tick:0x00017c0d复制错误复制成功

list timer 返回字段的描述:

字段描述
timer定时器的名称
periodic定时器是否是周期性的
timeout定时器超时时的节拍数
activated定时器的状态,activated 表示活动的,deactivated 表示不活动的
mode定时器类型,one shot 表示单次定时,periodic 表示周期定时

current tick 表示当前系统的 tick 数。

显示设备状态

使用 list device 命令来显示系统中所有的设备信息,包括设备名称、设备类型和设备被打开次数。

msh />list device
device           type         ref count
-------- -------------------- ----------
sd       Block Device         1
rtc      RTC                  0
zero     Miscellaneous Device 0
shm      Unknown              0
uart1    Character Device     0
uart0    Character Device     2复制错误复制成功

list device 返回字段的描述:

字段描述
device设备的名称
type设备的类型
ref count设备被打开次数

显示动态内存状态

使用 free 命令来显示系统中所有的内存信息。

msh />free
total    : 66606976
used     : 17792
maximum  : 20000
available: 66589184复制错误复制成功

free 返回字段的描述:

字段描述
total memory内存总大小
used memory已使用的内存大小
maximum allocated memory最大分配内存
available可用内存大小

3. 自定义 FinSH 命令 - 用户新增加的命令

除了 FinSH 自带的命令,FinSH 还也提供了多个宏接口来导出自定义命令,导出的命令可以直接在 FinSH 中执行。

自定义 msh 命令

自定义的 msh 命令,可以在 msh 模式下被运行,将一个命令导出到 msh 模式可以使用如下宏接口:

MSH_CMD_EXPORT(name, desc);

参数描述
name要导出的命令
desc导出命令的描述

这个命令可以导出有参数的命令,也可以导出无参数的命令。导出无参数命令时,函数的入参为 void,示例如下:

void hello(void)
{
    rt_kprintf("hello RT-Thread!\n");
}

MSH_CMD_EXPORT(hello , say hello to RT-Thread);复制错误复制成功

导出有参数的命令时,函数的入参为 int argc 和 char**argv。argc 表示参数的个数,argv 表示命令行参数字符串指针数组指针。导出有参数命令示例如下:

static void atcmd(int argc, char**argv)
{
    ……
}

MSH_CMD_EXPORT(atcmd, atcmd sample: atcmd <server|client>);复制错误复制成功

自定义命令重命名

FinSH 的函数名字长度有一定限制,它由 finsh.h 中的宏定义 FINSH_NAME_MAX 控制,默认是 16 字节,这意味着 FinSH 命令长度不会超过 16 字节。这里有个潜在的问题:当一个函数名长度超过 FINSH_NAME_MAX 时,使用 FINSH_FUNCTION_EXPORT 导出这个函数到命令表中后,在 FinSH 符号表中看到完整的函数名,但是完整输入执行会出现 null node 错误。这是因为虽然显示了完整的函数名,但是实际上 FinSH 中却保存了前 16 字节作为命令,过多的输入会导致无法正确找到命令,这时就可以使用 FINSH_FUNCTION_EXPORT_ALIAS 来对导出的命令进行重命名。

FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc);

参数描述
name要导出的命令
alias导出到 FinSH 时显示的名字
desc导出命令的描述

在重命名的命令名字前加 __cmd_ 就可以将命令导出到 msh 模式,否则,命令会被导出到 C-Style 模式。以下示例定义了一个 hello 函数,并将它重命名为 ho 后导出成 C-Style 模式下的命令。

void hello(void)
{
    rt_kprintf("hello RT-Thread!\n");
}

FINSH_FUNCTION_EXPORT_ALIAS(hello , ho, say hello to RT-Thread);复制错误复制成功

4. FinSH 功能配置

FinSH 功能可以裁剪,宏配置选项在 rtconfig.h 文件中定义,具体配置项如下表所示。

宏定义取值类型描述默认值
#define RT_USING_FINSH使能 FinSH开启
#define FINSH_THREAD_NAME字符串FinSH 线程的名字"tshell"
#define FINSH_USING_HISTORY打开历史回溯功能开启
#define FINSH_HISTORY_LINES整数型能回溯的历史命令行数5
#define FINSH_USING_SYMTAB可以在 FinSH 中使用符号表开启
#define FINSH_USING_DESCRIPTION给每个 FinSH 的符号添加一段描述开启
#define FINSH_USING_MSH使能 msh 模式开启
#define FINSH_ARG_MAX整数型最大输入参数数量10
#define FINSH_USING_AUTH使能权限验证关闭
#define FINSH_DEFAULT_PASSWORD字符串权限验证密码关闭

msh />list_thread
thread   cpu pri  status      sp     stack size max used left tick  error
-------- --- ---  ------- ---------- ----------  ------  ---------- ---
tshell     0  20  running 0x00000188 0x00001000    18%   0x00000005 000
aio      N/A  16  suspend 0x0000008c 0x00000800    07%   0x0000000a 000
sys_work N/A  23  suspend 0x0000008c 0x00000800    55%   0x0000000a 000
mmcsd_de N/A  22  suspend 0x000000b8 0x00000400    46%   0x00000014 000
tcpip    N/A  10  suspend 0x000000f4 0x00000400    93%   0x00000011 000
etx      N/A  12  suspend 0x000000b4 0x00000400    23%   0x00000010 000
erx      N/A  12  suspend 0x000000b8 0x00000400    66%   0x00000010 000
tidle1   N/A  31  ready   0x00000048 0x00000400    07%   0x00000020 000
tidle0   N/A  31  ready   0x00000064 0x00000400    21%   0x0000001b 000
timer    N/A   4  suspend 0x00000080 0x00000400    21%   0x0000000a 000
msh />

在RT-Thread中,msh和FinSH都是命令行相关的组件,但它们的定位和功能有所不同

msh是RT-Thread的一个组件,它依赖于FinSH,并为其提供了在msh模式下运行自定义命令的功能。具体来说,msh利用FinSH提供的宏接口(如MSH_CMD_EXPORT)来导出自定义命令,这些命令可以直接在msh中执行。例如,你可以编写一个函数并使用MSH_CMD_EXPORT宏将其导出为msh命令,然后在msh命令行中输入该命令来触发这个函数。

另一方面,FinSH是RT-Thread的命令行组件,它提供了一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。FinSH支持多种通信方式(如串口、以太网、USB等)与PC机进行通信,并且提供了多个宏接口来导出自定义命令。

综上所述,msh和FinSH在RT-Thread中协同工作,共同为用户提供命令行交互的功能。msh依赖于FinSH的命令行接口来执行自定义命令,而FinSH则为msh提供了导出和执行这些命令的能力。

rtconfig.h 中的参考配置示例如下所示,可以根据实际功能需求情况进行配置。

/* 开启 FinSH */
#define RT_USING_FINSH

/* 将线程名称定义为 tshell */
#define FINSH_THREAD_NAME "tshell"

/* 开启历史命令 */
#define FINSH_USING_HISTORY
/* 记录 5 行历史命令 */
#define FINSH_HISTORY_LINES 5

/* 开启使用 Tab 键 */
#define FINSH_USING_SYMTAB
/* 开启描述功能 */
#define FINSH_USING_DESCRIPTION

/* 定义 FinSH 线程优先级为 20 */
#define FINSH_THREAD_PRIORITY 20
/* 定义 FinSH 线程的栈大小为 4KB */
#define FINSH_THREAD_STACK_SIZE 4096
/* 定义命令字符长度为 80 字节 */
#define FINSH_CMD_SIZE 80

/* 开启 msh 功能 */
#define FINSH_USING_MSH
/* 最大输入参数数量为 10 个 */
#define FINSH_ARG_MAX 10复制错误复制成功

5. FinSH 应用示例

5.1 不带参数的 msh 命令示例

本小节将演示如何将一个自定义的命令导出到 msh 中,示例代码如下所示,代码中创建了 hello 函数,然后通过 MSH_CMD_EXPORT 命令即可将 hello 函数导出到 FinSH 命令列表中。

#include <rtthread.h>

void hello(void)
{
    rt_kprintf("hello RT-Thread!\n");
}

MSH_CMD_EXPORT(hello , say hello to RT-Thread);复制错误复制成功

系统运行起来后,在 FinSH 控制台按 tab 键可以看到导出的命令:

msh />
RT-Thread shell commands:
hello             - say hello to RT-Thread
version           - show RT-Thread version information
……复制错误复制成功

运行 hello 命令,运行结果如下所示:

msh />hello
hello RT_Thread!
msh />复制错误复制成功

5.2 带参数的 msh 命令示例

本小节将演示如何将一个带参数的自定义的命令导出到 FinSH 中, 示例代码如下所示,代码中创建了 atcmd() 函数,然后通过 MSH_CMD_EXPORT 命令即可将 atcmd() 函数导出到 msh 命令列表中。

#include <rtthread.h>

static void atcmd(int argc, char**argv)
{
    if (argc < 2)
    {
        rt_kprintf("Please input'atcmd <server|client>'\n");
        return;
    }

    if (!rt_strcmp(argv[1], "server"))
    {
        rt_kprintf("AT server!\n");
    }
    else if (!rt_strcmp(argv[1], "client"))
    {
        rt_kprintf("AT client!\n");
    }
    else
    {
        rt_kprintf("Please input'atcmd <server|client>'\n");
    }
}

MSH_CMD_EXPORT(atcmd, atcmd sample: atcmd <server|client>);复制错误复制成功

系统运行起来后,在 FinSH 控制台按 tab 键可以看到导出的命令:

msh />
RT-Thread shell commands:
hello             - say hello to RT-Thread
atcmd             - atcmd sample: atcmd <server|client>
version           - show RT-Thread version information
……复制错误复制成功

运行 atcmd 命令,运行结果如下所示:

msh />atcmd
Please input 'atcmd <server|client>'
msh />复制错误复制成功

运行 atcmd server 命令,运行结果如下所示:

msh />atcmd server
AT server!
msh />复制错误复制成功

运行 atcmd client 命令,运行结果如下所示:

msh />atcmd client
AT client!
msh />复制错误复制成功

6. FinSH 移植

FinSH 完全采用 ANSI C 编写,具备极好的移植性;

内存占用少,如果不使用前面章节中介绍的函数方式动态地向 FinSH 添加符号,FinSH 将不会动态申请内存。FinSH 源码位于 components/finsh 目录下。移植 FinSH 需要注意以下几个方面:

  • FinSH 线程:

每次的命令执行都是在 FinSH 线程(即 tshell 线程)的上下文中完成的

当定义 RT_USING_FINSH 宏时,就可以在初始化线程中调用 finsh_system_init() 初始化 FinSH 线程。

RT-Thread 1.2.0 之后的版本中可以不使用 finsh_set_device(const char* device_name) 函数去显式指定使用的设备,而是会自动调用 rt_console_get_device() 函数去使用 console 设备(RT-Thread 1.1.x 及以下版本中必须使用 finsh_set_device(const char* device_name) 指定 FinSH 使用的设备)。FinSH 线程在函数 finsh_system_init() 函数中被创建,它将一直等待 rx_sem 信号量。

  • FinSH 的输出:

FinSH 的输出依赖于系统的输出,在 RT-Thread 中依赖 rt_kprintf() 输出。在启动函数 rt_hw_board_init() 中, rt_console_set_device(const char* name) 函数设置了 FinSH 的打印输出设备。

  • FinSH 的输入:

FinSH 线程在获得了 rx_sem 信号量后,调用 rt_device_read() 函数从设备 (选用串口设备) 中获得一个字符然后处理。所以 FinSH 的移植需要 rt_device_read() 函数的实现。而 rx_sem 信号量的释放通过调用 rx_indicate() 函数以完成对 FinSH 线程的输入通知

通常的过程是,当串口接收中断发生时(即串口有输入),接受中断服务例程调用 rx_indicate() 函数通知 FinSH 线程有输入而后 FinSH 线程获取串口输入最后做相应的命令处理。如下图所示:

FinSH 命令执行流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/592293.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【5/01-5/03】 Arxiv安全类文章速览

知识星球 首先推荐一下我们的知识星球&#xff0c;以AI与安全结合作为主题&#xff0c;包括AI在安全上的应用和AI本身的安全&#xff1b; 加入星球你将获得&#xff1a; 【Ai4sec】&#xff1a;以数据驱动增强安全水位&#xff0c;涵盖内容包括&#xff1a;恶意软件分析&…

MATLAB中功率谱密度计算pwelch函数使用详解

MATLAB中功率谱密度计算pwelch函数使用详解 目录 前言 一、pwelch函数简介 二、pwelch函数参数说明 三、pxx pwelch(x)示例 四、[pxx,f]pwelch(x,window,noverlap,nfft,fs)示例 四、[pxx,f] pwelch(x,window,noverlap,nfft,fs,freqrange,spectrumtype)示例 五、多通道功…

# cmd 报错 “npm 不是内部或外部命令,也不是可运行的程序 或批处理文件”

cmd 报错 “npm 不是内部或外部命令,也不是可运行的程序 或批处理文件” 1、报错原因分析&#xff1a; Node.js 没有安装或安装不正确。 npm 的路径没有添加到系统环境变量中。 安装 Node.js 时选择了不包含 npm 的安装选项。 2、解决方法&#xff1a; 1&#xff09;在 cm…

【房屋】租房攻略,萌新第一次租房需要考虑的要素(通勤、地段、房源)

【房屋】租房攻略&#xff0c;萌新第一次租房需要考虑的要素&#xff08;通勤、地段、房源&#xff09; 文章目录 1、位置要好&#xff08;通勤近 vs 地段好&#xff09;2、户型要好&#xff08;朝向/楼层&#xff0c;独卫/家具&#xff0c;水电费&#xff09;3、价格要便宜4、…

Github 2024-05-03 Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-05-03统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9Kotlin项目1C++项目1libGDX: 跨平台Java游戏开发框架 创建周期:4284 天开发语言:Java, C++协议类型:Apache License 2.0Star数量:2…

DDD:根据maven的脚手架archetype生成ddd多模块项目目录结构

随着领域驱动的兴起&#xff0c;很多人都想学习如何进行ddd的项目开发&#xff0c;那ddd的项目结构是怎么样的&#xff1f;又是如何结合SpringBoot呢&#xff1f;那么针对这个问题&#xff0c;笔者使用maven的archetype封装一个相对通用的ddd的项目目录&#xff0c;方便一键生成…

函数模板 template

函数模板的定义和调用 注意&#xff1a; 在调用函数模板时&#xff0c;编译器会根据调用的函数的参数类型自动推导出T的类型。 优先选择普通函数 强制调用函数模板 函数模板不能对函数的参数自动强制类型转换 myPrintAll(10,b)//普通函数&#xff0c;因为普通函数将b强制转换成…

安装vscode基础配置,es6基础语法,

https://code.visualstudio.com/ es6 定义变量 const声明常量&#xff08;只读变量&#xff09; // 1、声明之后不允许改变 const PI “3.1415926” PI 3 // TypeError: Assignment to constant variable. // 2、一但声明必须初始化&#xff0c;否则会报错 const MY_AGE /…

极简单行阅读器:上班族的摸鱼神器

在忙碌的工作日中&#xff0c;我们经常需要寻找一些方式来放松自己&#xff0c;而阅读无疑是一种既能够放松心情&#xff0c;又能增长知识的方式。今天&#xff0c;我要向大家介绍一个名为“极简单行阅读器”的神器&#xff0c;它不仅能够满足你的阅读需求&#xff0c;还能让你…

时也命也!反派失败于错估了主角的实力——早读(逆天打工人爬取热门微信文章解读)

此子断不可留 引言Python 代码第一篇 洞见 人到中年最大的清醒&#xff1a;时也&#xff0c;运也&#xff0c;命也第二篇 人民日报要闻社会政策 结尾 自知之明是最难得的知识 真正的智慧来自于对自己能力和局限的深刻理解 引言 最近在看仙葫 然后昨天晚上刷了一下这个诛仙 发现…

Qt之信号与槽

槽的本质&#xff1a;对信号响应的函数。 信号函数和槽函数通常位于某个类中&#xff0c;和普通的成员函数相⽐&#xff0c;它们的特别之处在于&#xff1a; 信号函数⽤ signals 关键字修饰&#xff0c;槽函数⽤ public slots、protected slots 或者 private slots 修饰。sign…

前端基础学习html-->表单标签

目录 表单标签&#xff1a; 表单域&#xff1a; 表单控件(表单元素)&#xff1a; 提示信息: 表单标签&#xff1a; 表单标签顾名思义就是一种表格&#xff0c;用于收集用户信息 在html&#xff0c;一个完整的表单域是由表单域&#xff0c;表单控件(表单元素)和提示信息组…

揭秘Fabric交易流程:一文带你深入了解

随着区块链技术的日益普及&#xff0c;Hyperledger Fabric作为一种联盟链解决方案&#xff0c;受到了广泛关注。那么&#xff0c;Fabric的交易流程究竟是怎样的呢&#xff1f;本文将为您一一揭晓。 1. Fabric交易的参与方 客户端&#xff1a;交易流程的发起方&#xff0c;发起…

Java web第五次作业

1.在idea中配置好数据源 2、视频案例中只给出了查询所有结果的示例&#xff0c;请自己完成添加、删除、修改操作的代码。以下供参 考。 Delete("delete from emp where id#{id}") public void delete(Integer id); 测试代码 Test public void testDelete(){ empMa…

springboot 整合 knife4j-openapi3

适用于&#xff1a;项目已使用shiro安全认证框架&#xff0c;整合knife4j-openapi3 1.引入依赖 <!-- knife4j-openapi3 --> <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifa…

SpringBoot+Vue项目在线视频教育平台

一、前言介绍 本系统采用的数据库是Mysql&#xff0c;使用SpringBoot框架开发&#xff0c;运行环境使用Tomcat服务器&#xff0c;idea是本系统的开发平台。在设计过程中&#xff0c;充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面…

ThreeJS:常见几何体与基础材质入门

在前文《ThreeJS:Geometry与顶点|索引|面》中&#xff0c;我们了解了与Geometry几何体相关的基础概念&#xff0c;也尝试了如何通过BufferGeometry自定义几何体。 常见Geometry几何体 ThreeJS内部也提供了诸多封装好的几何体&#xff0c;常见的Geometry几何体如下图所示&#…

Delta lake with Java--利用spark sql操作数据1

今天要解决的问题是如何使用spark sql 建表&#xff0c;插入数据以及查询数据 1、建立一个类叫 DeltaLakeWithSparkSql1&#xff0c;具体代码如下&#xff0c;例子参考Delta Lake Up & Running第3章内容 import org.apache.spark.sql.SaveMode; import org.apache.spark.…

AGI要闻:斯坦福李飞飞首次创业,瞄准“空间智能”;OpenAI下周发布搜索产品挑战谷歌;新的开源 AI 眼镜来了|钛媒体AGI | 最新快讯

多方消息证实&#xff0c;OpenAI将会在北京时间5月10日&#xff08;周五&#xff09;凌晨2点公布搜索引擎新产品消息。 斯坦福大学首位红杉讲席教授 李飞飞 通用人工智能&#xff08;AGI&#xff09;领域又公布了一系列重磅消息。 5月4日凌晨&#xff0c;据路透社&#xff0c…

etcd源码流程---调试环境的搭建

etcd启动命令&#xff1a; name必须设置&#xff0c;否则会用default&#xff0c;集群内不同etcd实例的名字应该是唯一的&#xff0c;因为他会有一个map(name->ip)。如果initial-cluster-state设置为new&#xff0c;那么他会创建一个新的clusterid。需要在initial-cluster中…
最新文章