Linux arm64异常简介和系统调用过程

news2024/10/5 12:58:43

文章目录

  • 一、异常简介
    • 1.1 Exception levels
    • 1.2 异常类型
  • 二、系统调用简介
    • 2.1 SVC指令
    • 2.2 VBAR
    • 2.3 系统调用保存现场
    • 2.4 系统调用返回
  • 三、Linux 内核分析
  • 参考资料

一、异常简介

在ARM64体系架构中,异常是处理器在执行指令时可能遇到的不寻常情况或事件。这些异常可以是由软件或硬件引发的。ARM64体系架构定义了一套异常模型,用于处理和响应这些异常情况。

1.1 Exception levels

Armv8-A体系结构定义了一组异常级别,EL0到EL3,其中:

● 如果ELn是异常级别,则n的值增加表示软件执行权限增加。
● 在EL0执行称为无特权执行。EL0为非特权模块,应用层。
● 在EL1执行称为特权特权执行。EL1为特权模块,操作系统内核层。
● EL2提供对虚拟化的支持。
● EL3支持在两种安全状态(安全状态和非安全状态)之间切换。

EL0 Applications.
EL1 OS kernel and associated functions that are typically described as privileged.
EL2 Hypervisor.
EL3 Secure monitor.

一个armv8系统实现可能不包括所有的Exception级别。所有实现都必须包括EL0和EL1。EL2和EL3是可选的。

从上面可看到armv8最大支持EL0~EL3四个exception level,EL0的execution privilege最低,EL3的execution privilege最高。当发生异常的时候,系统的exception会迁移到更高的exception level或者维持不变,但是绝不会降低。此外,不会有任何的异常会去到EL0。

1.2 异常类型

在Linux ARM64架构中,同步异常和异步异常与处理器的异常处理机制和中断控制器有关。

(1)同步异常(Synchronous Exceptions):
在ARM64架构中,同步异常与当前指令的执行直接相关,它们在指令执行期间同步地引发。常见的同步异常包括:

●未定义指令异常:当尝试执行在ARM64架构中未定义的指令时,会引发该异常。包括在不适当的异常级别执行指令、禁用的指令、以及未被分配的指令位模式。

●非法执行状态异常:当PSTATE.IL(非法执行状态)设置为1时,尝试执行指令会引发该异常。

●堆栈指针(SP)未对齐异常:当堆栈指针未按照对齐要求进行对齐时,会触发该异常。

●程序计数器(PC)未对齐异常:当尝试执行具有错误对齐的指令时,会引发该异常。

●引发异常的指令:特定指令(如SVC、HVC或SMC)可能触发异常。

●被捕获指令异常:当尝试执行被定义为在较高异常级别被捕获的指令时,会引发该异常。

●内存相关异常:由内存地址转换系统引发的异常,包括与指令执行或内存访问相关的指令异常和数据异常。

●数据地址未对齐异常:当尝试使用错误对齐的地址访问内存时,会触发该异常。

●调试异常:与调试相关的各种异常,例如断点指令异常、断点异常、观测点异常、向量捕获异常和软件单步异常。

●被捕获的浮点异常(如果支持):在支持浮点异常捕获的实现中,当发生被捕获的IEEE浮点异常时,会引发该异常。

对于同步异常,Linux内核会根据异常类型执行相应的异常处理程序,例如调用适当的异常处理函数、进行错误处理或发送信号给相关进程。

(2)异步异常(Asynchronous Exceptions):
在ARM64架构中,异步异常是与当前指令执行无直接关联的异常,它们以异步的方式引发。常见的异步异常包括:

在Armv8-A架构中,被带入AArch64状态的异步异常也被称为中断。中断分为两种类型:
物理中断(Physical interrupts):这些是从处理器外部发送给处理器的信号。它们包括:

SError:系统错误中断。
IRQ:普通中断请求。
FIQ:快速中断请求。

虚拟中断(Virtual interrupts):软件在EL2执行时可以启用和挂起的中断。虚拟中断从EL0或EL1传递到EL1。
虚拟中断的名称与物理中断对应:

vSError:虚拟系统错误中断。
vIRQ:虚拟普通中断请求。
vFIQ:虚拟快速中断请求。

对于异步异常,ARM64架构中的处理方式通常是由中断控制器来管理和处理。中断控制器会根据中断优先级和配置,将异步事件传递给处理器,并触发相应的中断处理程序。

二、系统调用简介

2.1 SVC指令

系统调用属于异常的同步软件异常。

系统调用是通过执行SVC、HVC或SMC指令触发的,这里我们指讨论SVC指令:
默认情况下,执行SVC指令会生成一个Supervisor Call,这是一个针对EL1的同步异常。这为在EL0执行的软件提供了一种调用在EL1执行的操作系统或其他软件的机制。

在ARM64体系架构中EL0是用户空间,EL1是内核空间。

SVC指令提供了在不同执行级别(EL)之间进行通信和交互的机制。通过执行SVC指令,EL0中的用户空间程序可以请求EL1中运行的操作系统或其他软件执行特权操作。

SVC Generate exception targeting Exception level 1
Supervisor Call causes an exception to be taken to EL1.

2.2 VBAR

当处理器处于使用AArch64执行状态时,当处理器执行到一个异常级别(Exception level)引发异常时,执行将被强制转移到异常向量(exception vector)所指示的地址上。异常向量表(vector table)位于该异常级别的内存中,占据一系列以字对齐的地址。

在ARMv8-A体系结构中,每个异常级别都有一个关联的向量基地址寄存器(Vector Base Address Register,VBAR),它定义了该异常级别对应的异常基地址。向量基地址决定了异常向量表在特定异常级别下的起始地址。当异常发生时,处理器使用与当前异常级别相关联的VBAR寄存器来查找相应的向量表,并跳转到该表中对应的异常向量。

通过为每个异常级别使用独立的向量表和VBAR寄存器,ARMv8-A体系结构在不同特权级别下的异常处理中提供了灵活性和定制性。该机制能够高效处理异常和中断,确保在不同情况下的适当处理和恢复。

处理器在用户空间EL0执行系统调用时,即执行svc指令,发生了异常,处理器跳转和执行相关的异常处理指令。异常相关的处理指令存储在一个表中,即异常向量表。对于ARM64体系架构,EL1对应一个异常向量表,其地址存放在向量基址寄存器(VBAR_EL1, Vector Base Address Register )中。

对于AArch64状态的异常,the vector table提供以下信息:
以下是关于异常的一些信息
(1)异常类型:

— Synchronous exception.
— SError.
— IRQ.
— FIQ

(2)异常级别和相关信息:
异常发生的异常级别:指示异常发生的特权级别,例如EL0(用户级别)、EL1(操作系统级别)等。
正在使用的堆栈指针:用于跟踪异常处理期间的堆栈操作。
寄存器文件的状态:指示异常发生时寄存器文件中各个寄存器的值和状态。
在这里插入图片描述
说明:
(1)这个表有四个异常条目,每个异常条目有四种异常类型:同步异常(Synchronous exception),IRQ,FIQ和SError。
(2)每一个异常入口占用0x80 bytes空间,每一个异常入口可以放置多32条指令。ARMv8指令集支持64位指令集,但每一条指令的位宽是32位,而不是64位。

0x80(128) / 4 = 32 

四个异常条目:
(1)如果发生异常并不会导致exception level切换,并且使用的栈指针是SP_EL0,对应着第一个异常条目。
(2)如果发生异常并不会导致exception level切换,并且使用的栈指针是SP_EL1/2/3,对应着第二个异常条目。
(3)如果发生异常会导致exception level切换,并且比目的exception level低一级的exception level运行在AARCH64模式,对应着第三个异常条目。
(4)如果发生异常会导致exception level切换,并且比目的exception level低一级的exception level运行在AARCH32模式,对应着第四个异常条目。

对于AARCH64模式异常指令svc,处理器会导致exception level切换,异常等级从EL0切换到EL1,对应着第三个异常条目:如果发生异常会导致exception level切换,并且比目的exception level低一级的exception level运行在AARCH64模式,那么使用第三个异常条目。

Lower Exception level, where the implemented level immediately lower than the target level is using AArch64.b

对于异常指令svc属于同步异常(Synchronous exception),因此svc异常处理器会跳转到 VBAR_EL1 + 0x400 地址处的异常向量中。

2.3 系统调用保存现场

当系统调用从用户态到内核态的时候,首先要做的第一件事情,就是将用户态运行过程中的 CPU 上下文保存起来,其实主要就是保存在这个结构的寄存器变量里。这样当从内核系统调用返回的时候,才能让进程在刚才的地方接着运行下去。

应用层程序执行svc系统调用指令时,会将用户态此时所有通用寄存器的状态保存起来,以便从系统调用返回时恢复状态。将进程用户态此时所有通用寄存器的状态保存在该进程的内核栈中的pt_regs栈框中。

在内核栈的最高地址端,存放的是另一个结构 pt_regs,这个结构体保存着进程从应用层进入到内核层时,用户态寄存器的状态。
struct pt_regs结构体:

/*
 * This struct defines the way the registers are stored on the stack during an
 * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
 * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
 */
struct pt_regs {
	union {
		struct user_pt_regs user_regs;
		struct {
			u64 regs[31];
			u64 sp;
			u64 pc;
			u64 pstate;
		};
	};
	u64 orig_x0;
#ifdef __AARCH64EB__
	u32 unused2;
	s32 syscallno;
#else
	s32 syscallno;
	u32 unused2;
#endif

	u64 orig_addr_limit;
	/* Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. */
	u64 pmr_save;
	u64 stackframe[2];
};

如下图所示:
在这里插入图片描述
关于进程内核栈请参考:Linux 进程管理之内核栈和struct pt_regs

2.4 系统调用返回

当操作系统的异常处理(这里只描述svc异常)完成后,执行一条ERET指令就可以从异常返回。寄存器ELR_ELx存放svc指令异常返回的地址,发生系统调用svc指令时,系统肯定是在用户空间的地址,将svc指令的下一条指令的地址保存在寄存器ELR_ELx中,当系统调用返回时,即执行ERET指令时,返回svc异常指令现场,从寄存器ELR_ELx取出svc指令的下一条指令的地址,执行该指令。执行ERET指令时会从寄存器ELR_ELx恢复PC指针。

三、Linux 内核分析

(1)汇编入口:

// linux-5.4.18/arch/arm64/kernel/entry.S

/*
 * Exception vectors.
 */
	.pushsection ".entry.text", "ax"

	.align	11
ENTRY(vectors)
	kernel_ventry	1, sync_invalid			// Synchronous EL1t
	kernel_ventry	1, irq_invalid			// IRQ EL1t
	kernel_ventry	1, fiq_invalid			// FIQ EL1t
	kernel_ventry	1, error_invalid		// Error EL1t

	kernel_ventry	1, sync				// Synchronous EL1h
	kernel_ventry	1, irq				// IRQ EL1h
	kernel_ventry	1, fiq_invalid			// FIQ EL1h
	kernel_ventry	1, error			// Error EL1h

	kernel_ventry	0, sync				// Synchronous 64-bit EL0
	kernel_ventry	0, irq				// IRQ 64-bit EL0
	kernel_ventry	0, fiq_invalid			// FIQ 64-bit EL0
	kernel_ventry	0, error			// Error 64-bit EL0

#ifdef CONFIG_COMPAT
	kernel_ventry	0, sync_compat, 32		// Synchronous 32-bit EL0
	kernel_ventry	0, irq_compat, 32		// IRQ 32-bit EL0
	kernel_ventry	0, fiq_invalid_compat, 32	// FIQ 32-bit EL0
	kernel_ventry	0, error_compat, 32		// Error 32-bit EL0
#else
	kernel_ventry	0, sync_invalid, 32		// Synchronous 32-bit EL0
	kernel_ventry	0, irq_invalid, 32		// IRQ 32-bit EL0
	kernel_ventry	0, fiq_invalid, 32		// FIQ 32-bit EL0
	kernel_ventry	0, error_invalid, 32		// Error 32-bit EL0
#endif
END(vectors)

Linux 内核使用vectors作为异常向量表,刚好和arm官方手册Vector Base Address Register (VBAR)的相对应。

前面说到对于同步异常指令svc,处理器会跳转到 VBAR_EL1 + 0x400 地址处的异常向量中。
VBAR_EL1 存放的是vectors的基地址。

一个表项128字节,十六进制即 0x80。

偏移异常描述
Current Exception level with SP_EL0
0x00kernel_ventry 1, sync_invalid // Synchronous EL1t
0x80kernel_ventry 1, irq_invalid // IRQ EL1t
0x100kernel_ventry 1, fiq_invalid // FIQ EL1t
0x180kernel_ventry 1, error_invalid // Error EL1t
Current Exception level with SP_ELx, x>0
0x200kernel_ventry 1, sync // Synchronous EL1h
0x280kernel_ventry 1, irq // IRQ EL1h
0x300kernel_ventry 1, fiq_invalid // FIQ EL1h
0x380kernel_ventry 1, error // Error EL1h
Lower Exception level, where the implemented level immediately lower than the target level is using AArch64
0x400kernel_ventry 0, sync // Synchronous 64-bit EL0
0x480kernel_ventry 0, irq // IRQ 64-bit EL0
0x500kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
0x580kernel_ventry 0, error // Error 64-bit EL0
Lower Exception level, where the implemented level immediately lower than the target level is using AArch32
0x600kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
0x680kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
0x700kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
0x780kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0

vectors的基地址 + 0x400 =

kernel_ventry	0, sync				// Synchronous 64-bit EL0
// linux-5.4.18/arch/arm64/kernel/entry.S

/*
 * EL0 mode handlers.
 */
	.align	6
el0_sync:
	kernel_entry 0
	mrs	x25, esr_el1			// read the syndrome register
	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
	cmp	x24, #ESR_ELx_EC_SVC64		// SVC in 64-bit state
	b.eq	el0_svc
	cmp	x24, #ESR_ELx_EC_DABT_LOW	// data abort in EL0
	b.eq	el0_da
	cmp	x24, #ESR_ELx_EC_IABT_LOW	// instruction abort in EL0
	b.eq	el0_ia
	......

在el0_sync汇编函数中,首先通过kernel_entry保存异常现场。然后从esr_el1寄存器中读取异常类型(EC),当异常类型为ESR_ELx_EC_SVC64是,跳转到 el0_svc 汇编函数。

// linux-5.4.18/arch/arm64/kernel/entry.S

/*
 * SVC handler.
 */
	.align	6
el0_svc:
	gic_prio_kentry_setup tmp=x1
	mov	x0, sp
	bl	el0_svc_handler
	b	ret_to_user
ENDPROC(el0_svc)

el0_svc 汇编函数跳转到 el0_svc_handler 函数。

(2)C语言入口

// linux-5.4.18/arch/arm64/kernel/syscall.c

asmlinkage void el0_svc_handler(struct pt_regs *regs)
{
	el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table);
}
// linux-5.4.18/arch/arm64/include/asm/ptrace.h

/*
 * This struct defines the way the registers are stored on the stack during an
 * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
 * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
 */
struct pt_regs {
	union {
		struct user_pt_regs user_regs;
		struct {
			u64 regs[31];
			u64 sp;
			u64 pc;
			u64 pstate;
		};
	};
	u64 orig_x0;
	......
};
// linux-5.4.18/include/uapi/asm-generic/unistd.h

#define __NR_syscalls 436
// linux-5.4.18/arch/arm64/include/asm/syscall.h

typedef long (*syscall_fn_t)(const struct pt_regs *regs);

// linux-5.4.18/arch/arm64/kernel/sys.c

const syscall_fn_t sys_call_table[__NR_syscalls] = {
	[0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
#include <asm/unistd.h>
};
static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
			   const syscall_fn_t syscall_table[])
{

	regs->orig_x0 = regs->regs[0];
	regs->syscallno = scno;

	invoke_syscall(regs, scno, sc_nr, syscall_table);
	
}
static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
			   unsigned int sc_nr,
			   const syscall_fn_t syscall_table[])
{
	long ret;

	if (scno < sc_nr) {
		syscall_fn_t syscall_fn;
		syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];
		ret = __invoke_syscall(regs, syscall_fn);
	}
	
	regs->regs[0] = ret;
}
static long __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
{
	return syscall_fn(regs);
}

(3)流程简介

el0 svc
	-->el1 vectors
		-->kernel_ventry	0, sync				// Synchronous 64-bit EL0
			-->el0_sync
				-->el0_svc
					-->el0_svc_handler
						-->el0_svc_common
							-->invoke_syscall
								-->__invoke_syscall
									-->syscall_fn(regs)

从系统调用表中sys_call_table根据系统调用号取出对应的系统调用回调函数,然后去执行对应的系统调用回调函数。

参考资料

Linux 5.4.18
armv8手册

https://blog.csdn.net/luteresa/article/details/120263414
https://zhuanlan.zhihu.com/p/578252899
http://www.wowotech.net/238.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Mac软件]Adobe Media Encoder 2024 V24.0.2免激活版

软件说明 使用Media Encoder&#xff0c;您将能够处理和管理多媒体。插入、转码、创建代理版本&#xff0c;并几乎以任何可用的格式输出。在应用程序中以单一方式使用多媒体&#xff0c;包括Premiere Pro、After Effects和Audition。 紧密整合 与Adobe Premiere Pro、After …

Google play提高上包率——如何防止封号、拒审、下架?

Google Play是全球最大的移动应用商店之一&#xff0c;它是运行Android操作系统的设备的官方应用商店。它提供各种数字内容&#xff0c;包括应用程序&#xff08;应用&#xff09;、游戏、音乐、书籍等&#xff0c;包括免费和付费选项。这也为许多游戏/APP出海的企业或开发者提…

供暖系统如何实现数据远程采集?贝锐蒲公英高效实现智慧运维

山西某企业专注于暖通领域&#xff0c;坚持为城市集中供热行业和楼宇中央空调行业提供全面、专业的“智慧冷暖”解决方案。基于我国供热行业的管理现状&#xff0c;企业成功研发并推出了可将能源供应、管理与信息化、自动化相融合的ICS-DH供热节能管理系统。 但是&#xff0c;由…

集合贴4——QA机器人设计与优化

基础课21——知识库管理-CSDN博客文章浏览阅读342次&#xff0c;点赞6次&#xff0c;收藏2次。知识库中有什么信息内容&#xff0c;决定了智能客服机器人在回答时可以调用哪些信息内容&#xff0c;甚至可以更简单地理解为这是智能客服机器人的话术库。https://blog.csdn.net/22…

Java ClassNotFoundException异常解决指南

Java ClassNotFoundException异常解决指南 《Java ClassNotFoundException异常解决指南》摘要引言了解ClassNotFoundException异常的本质异常的起因表情小贴士 &#x1f61f; 异常的处理常见引发ClassNotFoundException的情况1. **类路径配置错误**2. **依赖关系错误**3. **动态…

Elasticsearch 作为 GenAI 缓存层

作者&#xff1a;JEFF VESTAL&#xff0c;BAHA AZARMI 探索如何将 Elasticsearch 集成为缓存层&#xff0c;通过降低 token 成本和响应时间来优化生成式 AI 性能&#xff0c;这已通过实际测试和实际实施进行了证明。 随着生成式人工智能 (GenAI) 不断革新从客户服务到数据分析…

云栖大会-简单易用的智能云网络

云布道师 10 月 31 日&#xff0c;杭州云栖大会&#xff0c;在阿里云网络技术分论坛&#xff0c;阿里云网络产品线负责人祝顺民带来《Leadership&#xff1a;简单易用的智能云网络——阿里云网络持续演进之路》的主题演讲&#xff0c;全面阐释阿里云飞天洛神云网络&#xff08;…

基于Python的pyAV读取H265(HEVC)编码的视频文件

1.问题出现 利用海康威视相机拍出来的视频是H265格式的&#xff0c;相比于常规的H264编码&#xff0c;压缩率更高&#xff0c;但因此如果直接用之前的方法读取&#xff0c;会出现无法读取的情况&#xff0c;如下。 可以看到&#xff0c;对于帧间没有改变的部分&#xf…

测试用例怎么样写?怎么搞懂方法和流程?

前言 作为一个测试新人&#xff0c;刚开始接触测试&#xff0c;对于怎么写测试用例很头疼&#xff0c;无法接触需求&#xff0c;只能根据站在用户的角度去做测试&#xff0c;但是这样情况会导致不能全方位的测试APP&#xff0c;这种情况就需要一份测试用例了&#xff0c;但是不…

java学习part01

15-Java语言概述-单行注释和多行注释的使用_哔哩哔哩_bilibili 1.命令行 javac编译出class文件 然后java运行 2. java文件每个文件最多一个public类 3.java注释 单行注释 // 多行注释 文档注释 文档注释内容可以被JDK提供的工具javadoc所解析&#xff0c;生成一套以网页文…

SQLChat 的 RBAC 之旅

去年 ChatGPT 在科技圈大火&#xff0c;到今年彻底破圈。各个领域都有相应的一些产品&#xff0c;数据库领域集中在 AI SQL&#xff0c;自然语言转 SQL&#xff0c;或者利用自然语言来管理数据库等。今天我们来体验一下该领域的 SQLChat 这款 AI 数据库客户端。 今天我们预设一…

C++智能指针的使用:shared_ptr、weak_ptr、unique_ptr的使用,使用案例说明。

系列文章目录 本章内容&#xff1a; &#xff08;1&#xff09;shared_ptr、weak_ptr、unique_ptr的介绍 &#xff08;2&#xff09;单独使用share_ptr造成的内存泄漏 &#xff08;3&#xff09;shared_ptr和weak_ptr的配合使用 文章目录 系列文章目录前言一、shared_ptr、wea…

PHP编写采集药品官方数据的程序

在 PHP 中编写爬虫程序&#xff0c;首先我们需要引入一些必要的库&#xff0c;如 curl 和 file_get_contents。然后&#xff0c;我们需要设置爬虫ip信息&#xff0c;以便我们可以从指定的爬虫ip服务器上获取数据。 // 引入必要的库 require_once curl.php;// 设置爬虫ip信息 $p…

振南技术干货集:振南当年入门C语言和单片机的那些事儿(3)

注解目录 第一章《振南当年入门 C 语言和单片机的那些事儿》 1、注定堕入单片机 1.1 懵懂好奇的我 &#xff08;小时候好奇的性格经常让我屁股开花。初中开始对计算机产生兴趣&#xff0c;并一发不可收拾。&#xff09; 1.2 我的 C 语言学习经历 &#xff08;上大学后自学…

虚拟机网络没有有效的ip配置

虚拟机网络没有有效的ip配置&#xff1a; 原因猜测&#xff1a;或许是之前使用的操作系统把网络给占了。 解决方法&#xff1a;点击虚拟机的 遍历->网络编辑器->移除不要的网络&#xff0c;然后添加网络。&#xff08;下面的图就是我把虚拟网络全部移除&#xff0c;然后…

ke10javaweb停更

<jsp:getProperty property"isval" name "username"/> property来修改属性,name是类 所以如果调用tip在前面那么就是没有设置值 证明是先到java里面去运转

JNPF开发平台:加速企业数字化转型,提升业务效率

如今&#xff0c;随着信息化的深入发展&#xff0c;数字化转型已经成为企业生存和发展的关键。为了在竞争激烈的市场中保持领先地位&#xff0c;企业需要快速地适应变化&#xff0c;优化业务流程&#xff0c;并提供优质的用户体验。而在这其中&#xff0c;低代码开发平台JNPF是…

VulnHub Nullbyte

一、信息收集 1.nmap扫描 arp-scan -l扫描内网存活主机 ┌──(root&#x1f480;kali)-[~/桌面] └─# nmap -sS -A -p- 192.168.103.201/24 -sS 半扫描 -A 扫描详细信息 -p- 扫描全端口发现开放了80、111、777、50978端口 且发现777端口开放了ssh服务&#xff0c;说明他把…

SQL Server 2022 安装步骤——SQL Server设置身份验证教程

目录 前言: 安装详细步骤: 第一步: 第二步: 第三步: 第四步: SQL Server 连接的方式: Window验证: SQL Server验证: 两者之间区别: 总结: SQL Server身份验证登录配置教程:​ 第一步: 第二步: 第三步: 番外篇: 前言: 本文讲解&#xff0c;如何安装SQL Server安…

Android修行手册-POI操作Excel实现超链接并且变为蓝色

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…