最新资讯

  • 【Linux】进程信号全攻略(二)

【Linux】进程信号全攻略(二)

2025-05-02 11:37:49 1 阅读

🌈 个人主页:Zfox_
🔥 系列专栏:Linux

目录

  • 一:🔥 再谈信号的捕捉
    • 🦋 关于信号捕捉的细节部分(sigaction函数)
  • 二:🔥 穿插话题 - 操作系统是怎么运⾏的
    • 🦋 硬件中断
    • 🦋 时钟中断
    • 🦋 OS 死循环
    • 🦋 小结
    • 🦋 如何理解系统调用
  • 三:🔥 缺⻚中断?内存碎⽚处理?除零野指针错误?
  • 四:🔥 如何理解内核态和⽤⼾态
  • 五:🔥 可重入函数
  • 六:🔥 使用信号对全局变量进行操作出现的问题(volatile)
  • 七:🔥 SIGCHLD信号
  • 八:🔥 共勉

一:🔥 再谈信号的捕捉

关于信号捕捉有三种方式:

signal(2, handler);       // 自定义捕捉
signal(2, SIG_IGN);       // 忽略一个信号
signal(2, SIG_DFL);       // 信号的默认处理动作

SIG_IGN 是一个特殊的宏,用于指示系统忽略该信号。

信号可能不会被立即处理,而是在合适的时候处理,那么合适的时候是什么时候呢?

  • 先给结论:从进程的内核态返回到用户态的时候,进行处理。

💦 简单来说,执行自己的代码,访问自己的数据,这就叫做用户态。

💦 当我们进入系统调用时,我们以操作系统的身份来执行时,此时就进入了内核态,操作系统把我们的底层工作做完,做完这些工作后返回到我们的调用处,继续执行下面的代码,但是操作系统,由内核态返回到用户态时,在返回的这个时候信号的检测和处理

这是因为管理信号的数据结构(也就是我们的三张表)都位于进程的控制块(PCB)内,而PCB属于内核数据。因此,信号的检测和处理必须在内核态下进行。

当进程从内核态返回用户态时,内核会检查是否有待处理的信号,并根据信号的处理方式(默认处理、忽略或自定义处理)进行相应的操作。但操作系统不能直接转过去执行用户提供的handler方法,这是出于对安全性的考虑。

如果信号的处理动作是⽤⼾⾃定义函数,在信号递达时就调⽤这个函数,这称为捕捉信号。

由于信号处理函数的代码是在⽤⼾空间的,处理过程⽐较复杂,举例如下:

  1. ⽤⼾程序注册了 SIGQUIT 信号的处理函数 sighandler
  2. 当前正在执⾏ main 函数, 这时发⽣中断或异常切换到内核态。
  3. 在中断处理完毕后要返回⽤⼾态的 main 函数之前检查到有信号 SIGQUIT 递达。
  4. 内核决定返回⽤⼾态后不是恢复 main 函数的上下⽂继续执⾏,⽽是执⾏ sighandler 函数, sighandler main 函数使⽤不同的堆栈空间,它们之间不存在调⽤和被调⽤的关系,是两个独⽴的控制流程。
  5. sighandler 函数返回后⾃动执⾏特殊的系统调⽤ sigreturn 再次进⼊内核态。
  6. 如果没有新的信号要递达,这次再返回⽤⼾态就是恢复 main 函数的上下⽂继续执⾏了

🦋 关于信号捕捉的细节部分(sigaction函数)

  • signum指定要设置或获取处理程序的信号编号。可以指定SIGKILL和SIGSTOP以外的所有信号。
  • act指向 sigaction 结构体的指针,用于指定新的信号处理方式。如果此参数非空,则根据此参数修改信号的处理动作。
  • oldact如果非空,则通过此参数传出该信号原来的处理动作。(如果你想恢复以前的方式,此参数就是保存之前的操作方式)

🦁 sigaction 结构体

struct sigaction {  
    void (*sa_handler)(int);     // 指向信号处理函数的指针,接收信号编号作为参数  
    void (*sa_sigaction)(int, siginfo_t *, void *);   // 另一个信号处理函数指针,支持更丰富的信号信息  
    sigset_t sa_mask;           // 设置在处理该信号时暂时屏蔽的信号集  
    int sa_flags;               // 指定信号处理的其他相关操作  
    void (*sa_restorer)(void);  // 已废弃,不用关心  
};

🎯 sigaction 函数和 signal 的明显区别:

如果你还想在处理 2 号信号(OS对2号自动屏蔽0),同时,对其它型号也进行屏蔽,你可以设置 sa_mask 变量。

  • 当前如果正在对 2 号信号进行处理,默认 2 号信号会被自动屏蔽,对2号信号处理完成的时候,会自动解除对 2 号信号的屏蔽。为什么?这是因为,操作系统不允许同一个信号被连续处理。
  • 如果 2 号信号处理完毕后,会自动解除对 2 号信号的屏蔽

下面是一段示例:

#include 
#include 
#include 

void PrintBlock()
{
    sigset_t set, oset;
    sigemptyset(&set);
    sigemptyset(&oset);

    sigprocmask(SIG_BLOCK, &set, &oset);
    std::cout << "block :";
    for(int signo = 31; signo > 0; signo--)
    {
        if(sigismember(&oset, signo))
        {
            std::cout << 1;
        }
        else 
        {
            std::cout << 0;
        }
    }
    std::cout << std::endl;
}

void PrintPending()
{
    sigset_t pending;
    ::sigpending(&pending);

    std::cout << "Pending :";
    for(int signo = 31; signo > 0; signo--)
    {
        if(sigismember(&pending, signo))
        {
            std::cout << 1;
        }
        else 
        {
            std::cout << 0;
        }
    }
    std::cout << std::endl;
}

void handler(int signo)
{
    static int cnt = 0;
    cnt++;
    while (true)
    {
        std::cout << "get a sig" << signo << ", cnt: " << cnt << std::endl;
        PrintBlock();
        ::sleep(1);
        break;
    }
}

int main()
{
    struct sigaction act, oact;
    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, 3);
    sigaddset(&act.sa_mask, 4);
    sigaddset(&act.sa_mask, 5);
    sigaddset(&act.sa_mask, 6);
    sigaddset(&act.sa_mask, 7);

    ::sigaction(2, &act, &oact);

    while (true)
    {
        // PrintBlock();
        PrintPending();
        ::pause();
    }

    return 0;
}

🌳 我对3,4,5,6,7号信号也同时做了屏蔽,此时发送2号信号,pending值也是由0置为1的。

二:🔥 穿插话题 - 操作系统是怎么运⾏的

🦋 硬件中断

• 中断向量表就是操作系统的⼀部分,启动就加载到内存中了
• 通过外部硬件中断,操作系统就不需要对外设进⾏任何周期性的检测或者轮询
• 由外部设备触发的,中断系统运⾏流程,叫做硬件中断

🦋 时钟中断

☁️ 定义:Linux 时钟中断是指在 Linux 操作系统中,系统定时器周期性地触发中断,这个中断被称为时钟中断。时钟中断源于硬件定时器,通常由计算机的主板芯片或处理器芯片提供,通过定时器计数器来实现定时中断功能。

功能:

  • 维护系统时间每当一个时钟中断发生时,内核会更新系统时间的计数值。这个计数值可以是自世界时间开始的毫秒数,也可以是自系统启动以来的滴答数(tick)。通过定时更新系统时间,系统可以保持时间的准确性,为用户提供可靠的时间信息。

  • 任务调度在多任务操作系统中,内核需要决定哪个进程将获得CPU的控制权。时钟中断提供了一个计时器,每当中断发生时,内核会检查当前运行的进程是否到达了它应该运行的时间片。如果一个进程的时间片用完了,内核就会重新选择下一个要运行的进程,并切换上下文,将控制权交给新的进程。这样保证了系统中进程的公平调度,提高了系统的整体性能。

  • 计算进程执行时间每当一个进程或线程被抢占,切换到另一个进程或线程时,时钟中断记录下了抢占发生的时间。通过记录不同进程和线程的执行时间,可以分析其调度情况,了解系统中进程的运行情况,为性能优化提供依据。

🦋 OS 死循环

💜 如果是这样,操作系统不就可以躺平了吗?对,操作系统⾃⼰不做任何事情,需要什么功能,就向中断向量表⾥⾯添加⽅法即可.操作系统的本质:就是⼀个死循环!

void main(void) /* 这⾥确实是void,并没错。 */
{ 
	/* 在startup 程序(head.s)中就是这样假设的。 */
	...
	/*
	* 注意!! 对于任何其它的任务,'pause()'将意味着我们必须等待收到⼀个信号才会返
	* 回就绪运⾏态,但任务0(task0)是唯⼀的意外情况(参⻅'schedule()'),因为任
	* 务0 在任何空闲时间⾥都会被激活(当没有其它任务在运⾏时),
	* 因此对于任务0'pause()'仅意味着我们返回来查看是否有其它任务可以运⾏,如果没
	* 有的话我们就回到这⾥,⼀直循环执⾏'pause()'。
	*/
	
	for (;;)
	pause();
} // end main

🦋 小结

操作系统的本质就是一个 死循环 + 时钟中断(不断调度系统的任务): 操作系统中的进程调度依赖于时钟来分配处理器时间。时钟中断定期触发,使操作系统能够检查当前进程的运行状态,并根据需要进行进程切换或调整进程的优先级。时钟通过产生时钟中断来实现进程的时间片管理。每个进程被分配一个固定的时间片来执行,当时钟中断发生时,如果当前进程的时间片已经用完,则操作系统会将其挂起,并选择另一个进程来执行。这种方式确保了每个进程都有机会获得处理器资源,从而提高了系统的整体性能。因此,时钟通过提供稳定的时间基准、实现进程调度、处理中断以及提高系统稳定性与可靠性等方面来推动操作系统的运行。它是操作系统中不可或缺的一部分,对于保证系统的正常运行和任务的有序执行具有重要意义。

🦋 如何理解系统调用

软中断
• 上述外部硬件中断,需要硬件设备触发。
• 有没有可能,因为软件原因,也触发上⾯的逻辑?有!
• 为了让操作系统⽀持进⾏系统调⽤,CPU 也设计了对应的汇编指令 (int 0x80 或者 syscall), 可以让CPU内部触发中断逻辑。
所以:

用户程序在代码中调用系统调用时,会执行一个特殊的中断指令,如 int 0x80(在x86架构中)或 syscall 指令。在执行中断指令前,将系统调用号放入特定的寄存器中(如eax寄存器)。CPU 暂停当前执行的代码,根据中断的中断号,在中断向量表中找到对应的中断处理程序(如Linux中的 system_call ),并调用它。中断处理程序会检查系统调用号的有效性,并从系统调用表中找到相应的系统调用函数进行调用。

我们只要找到特定数组下标的方法,就能执行系统调用了。

问题:
⽤⼾层怎么把系统调⽤号给操作系统? - 寄存器(⽐如EAX)
操作系统怎么把返回值给⽤⼾?- 寄存器或者⽤⼾传⼊的缓冲区地址
系统调⽤的过程,其实就是先int 0x80、syscall陷⼊内核,本质就是触发软中断,CPU就会⾃动执⾏系统调⽤的处理⽅法,⽽这个⽅法会根据系统调⽤号,⾃动查表,执⾏对应的⽅法
系统调⽤号的本质:数组下标

可是为什么我们⽤的系统调⽤,从来没有⻅过什么 int 0x80 或者 syscall 呢?都是直接调⽤上层的函数的啊?
• 那是因为 Linux 的 gnu C 标准库,给我们把⼏乎所有的系统调⽤全部封装了。

三:🔥 缺⻚中断?内存碎⽚处理?除零野指针错误?

  • 缺⻚中断?内存碎⽚处理?除零野指针错误?这些问题,全部都会被转换成为CPU内部的软中断,然后⾛中断处理例程,完成所有处理。有的是进⾏申请内存,填充⻚表,进⾏映射的。有的是⽤来处理内存碎⽚的,有的是⽤来给⽬标进⾏发送信号,杀掉进程等等。

📌 所以:

  • 操作系统就是躺在中断处理例程上的代码块!
  • CPU内部的软中断,⽐如 int 0x80 或者 syscall,我们叫做 陷阱
  • CPU内部的软中断,⽐如除零/野指针等,我们叫做 异常。(所以,能理解“缺⻚异常”为什么这么叫了吗?)

四:🔥 如何理解内核态和⽤⼾态


结论:
• 操作系统⽆论怎么切换进程,都能找到同⼀个操作系统!换句话说操作系统系统调⽤⽅法的执⾏,是在进程的地址空间中执⾏的!

  • 内核态: 0-4G 范围的虚拟空间地址都可以操作,尤其是对 3-4G 范围的⾼位虚拟空间地址必须由内核态去操作。

  • 3G - 4G 部分⼤家是共享的(指所有进程的内核态逻辑地址是共享同⼀块内存地址),是内核态的地址空间,这⾥存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。

  • 关于特权级别,涉及到段,段描述符,段选择⼦,DPL,CPL,RPL等概念, ⽽现在芯⽚为了保证兼容性,已经⾮常复杂了,进⽽导致OS也必须得照顾它的复杂性,这块我们不做深究了。

  • ⽤⼾态就是执⾏⽤⼾ [0,3] GB 时所处的状态

  • 内核态就是执⾏内核 [3,4] GB 时所处的状态

  • 区分就是按照CPU内的CPL决定,CPL的全称是Current Privilege Level,即当前特权级别。

  • ⼀般执⾏ int 0x80 或者 syscall 软中断,CPL会在校验之后⾃动变更

  • 这样会不会不安全??

五:🔥 可重入函数

  • main 函数调用 insert 函数向一个链表 head 中插入节点 node1, 插入操作分为两步,刚做完第一步的 时候, 因为硬件中断使进程切换到内核, 再次回用户态之前检查到有信号待处理, 于是切换 到 sighandler 函数, sighandler 也调用 insert 函数向同一个链表 head 中插入节点 node2 , 插入操作的两步都做完之后从 sighandler 返回内核态, 再次回到用户态就从 main 函数调用的 insert 函数中继续往下执行, 先前做第一步之后被打断, 现在继续做完第二步。结果是 main 函数和 sighandler 先后向链表中插入两个节点, 而最后只有一个节点真正插入链表中了。
  • 像上例这样, insert 函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数, 这称为重入, insert 函数访问一个全局链表, 有可能因为重入而造成错乱, 像这样的函数称为不可重入函数, 反之, 如果一个函数只访问自己的局部变量或参数, 则称为可重入 (Reentrant) 函数。想一下, 为什么两个不同的控制流程调用同一个函数, 访问它的同一个局部变量或参数就不会造成错乱?
    qquad

如果一个函数符合以下条件之一则是不可重入的:(大部分函数是不可被重入的,可重入或者不可重入,描述的是函数的特征)

  • 调用了malloc或free,因为malloc也是用全局链表来管理堆的。
  • 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。

六:🔥 使用信号对全局变量进行操作出现的问题(volatile)

int gflag = 0;
 
void changedata(int signo)
{
    std::cout << "get a signo:" << signo << ", change gflag 0->1" << std::endl;
    gflag = 1;
}
 
int main() // 没有任何代码对gflag进行修改!!!
{
    signal(2, changedata);
 
    while(!gflag); // while不要其他代码
    std::cout << "process quit normal" << std::endl;
}

我们捕捉了2号信号,当我们执行了2号信号后,全局变量 gflag 就会被更改为1,那么 main 函数中的 while 就会停止执行,因为 cpu 在执行 while 循环的时候,实时的从内存中取 gflag 来进行比较,但在这里我们对编译进行优化,这会让 cpu 保存之前在内存中取的 gflag 的值,只在内存中取最开始的一次值, 其余都在寄存器的缓存中读取,这就会导致 gflag 的变化无法被在 while 中实时更新,导致 while 循环无法结束:g++ -o test test.cc -O1(O1,是基础优化)

如果想让 gflag 在此优化下生效,就要使用 volatile(volatile关键字可以确保变量的可见性(即确保变量每次访问时都直接从内存中读取)关键字调整后,程序成功退出:

volatile int gflag = 0;

七:🔥 SIGCHLD信号

子进程退出时,不是静悄悄的退出的,会给父进程发送信号–SIGCHLD信号。
下面是一段示例:

#include 
#include 
#include 
#include 
#include 
 
void notice(int signo)
{
    std::cout << "get a signal: " << signo << " pid: " << getpid() << std::endl;
    while (true)
    {
        pid_t rid = waitpid(-1, nullptr, WNOHANG); // 阻塞啦!!--> 非阻塞方式
        if (rid > 0)
        {
            std::cout << "wait child success, rid: " << rid << std::endl;
        }
        else if (rid < 0)
        {
            std::cout << "wait child success done " << std::endl;
            break;
        }
        else
        {
            std::cout << "wait child success done " << std::endl;
            break;
        }
    }
}
 
void DoOtherThing()
{
    std::cout << "DoOtherThing~" << std::endl;
}

int main()
{
    signal(SIGCHLD, notice);
    for (int i = 0; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            std::cout << "I am child process, pid: " << getpid() << std::endl;
            sleep(3);
            exit(1);
        }
    }
    // father
    while (true)
    {
        DoOtherThing();
        sleep(1);
    }
 
    return 0;
}

这段代码创建了多个子进程,并在子进程结束时通过 SIGCHLD 信号进行处理。

  • SIGCHLD 信号被捕获时,notice 函数会被调用。这个函数会进入一个无限循环,尝试使用 waitpid 以非阻塞方式 (WNOHANG) 等待任何已终止的子进程。这是合理的,因为它允许父进程在子进程终止时及时回收资源,同时不阻塞父进程的其他操作。

八:🔥 共勉

以上就是我对 【Linux】进程信号全攻略(二) 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉

本文地址:https://www.vps345.com/7157.html

搜索文章

Tags

PV计算 带宽计算 流量带宽 服务器带宽 上行带宽 上行速率 什么是上行带宽? CC攻击 攻击怎么办 流量攻击 DDOS攻击 服务器被攻击怎么办 源IP 服务器 linux 运维 游戏 云计算 javascript 前端 chrome edge llama 算法 opencv 自然语言处理 神经网络 语言模型 ubuntu ssh RTSP xop RTP RTSPServer 推流 视频 科技 ai java 人工智能 个人开发 数据库 centos oracle 关系型 安全 分布式 deepseek Ollama 模型联网 API CherryStudio python MCP 进程 操作系统 进程控制 Ubuntu 阿里云 网络 网络安全 网络协议 rust http 开发语言 filezilla 无法连接服务器 连接被服务器拒绝 vsftpd 331/530 智能路由器 外网访问 内网穿透 端口映射 华为 HarmonyOS Next YOLO efficientVIT YOLOv8替换主干网络 TOLOv8 harmonyos typescript 计算机网络 asm numpy 宝塔面板访问不了 宝塔面板网站访问不了 宝塔面板怎么配置网站能访问 宝塔面板配置ip访问 宝塔面板配置域名访问教程 宝塔面板配置教程 运维开发 云原生 Flask FastAPI Waitress Gunicorn uWSGI Uvicorn macos adb EtherCAT转Modbus ECT转Modbus协议 EtherCAT转485网关 ECT转Modbus串口网关 EtherCAT转485协议 ECT转Modbus网关 fastapi mcp mcp-proxy mcp-inspector fastapi-mcp agent sse 物联网 tcp/ip mcu iot 信息与通信 android 鸿蒙 嵌入式 linux驱动开发 arm开发 嵌入式硬件 vue.js audio vue音乐播放器 vue播放音频文件 Audio音频播放器自定义样式 播放暂停进度条音量调节快进快退 自定义audio覆盖默认样式 ssl 面试 性能优化 jdk intellij-idea 架构 udp 客户端 后端 java-ee ESP32 c++ 单片机 ue5 vr docker 豆瓣 追剧助手 迅雷 nas 微信 前端框架 golang conda ipython 学习 aws googlecloud vSphere vCenter 软件定义数据中心 sddc jmeter 软件测试 HCIE 数通 ESXi rpc gateway Clion Nova ResharperC++引擎 Centos7 远程开发 jenkins mount挂载磁盘 wrong fs type LVM挂载磁盘 Centos7.9 node.js json html5 firefox Qwen2.5-coder 离线部署 sqlserver ollama 大模型 mac websocket Dify c# 深度学习 安装教程 GPU环境配置 Ubuntu22 CUDA PyTorch Anaconda安装 .netcore rust腐蚀 编辑器 鸿蒙系统 pycharm ide pip 机器学习 目标检测 计算机外设 电脑 软件需求 dell服务器 git elasticsearch WSL2 kubernetes 容器 学习方法 经验分享 程序人生 笔记 开源 ui 华为云 华为od AI 爬虫 数据集 live555 源码剖析 rtsp实现步骤 流媒体开发 ai小智 语音助手 ai小智配网 ai小智教程 智能硬件 esp32语音助手 diy语音助手 微信分享 Image wxopensdk c语言 qt stm32项目 stm32 gpu算力 vscode ddos flutter Hyper-V WinRM TrustedHosts 大数据 数据挖掘 网络用户购物行为分析可视化平台 大数据毕业设计 1024程序员节 zotero WebDAV 同步失败 代理模式 数据结构 命名管道 客户端与服务端通信 政务 分布式系统 监控运维 Prometheus Grafana debian PVE github 创意 社区 mysql GaN HEMT 氮化镓 单粒子烧毁 辐射损伤 辐照效应 银河麒麟 kylin v10 麒麟 v10 go php tcpdump unix cpu 内存 实时 使用 Agent LDAP protobuf 序列化和反序列化 安装 windows flask spring boot AI编程 AIGC .net C 环境变量 进程地址空间 tomcat maven intellij idea react.js 前端面试题 持续部署 YOLOv8 NPU Atlas800 A300I pro asi_bench Windsurf nginx dubbo word图片自动上传 word一键转存 复制word图片 复制word图文 复制word公式 粘贴word图文 粘贴word公式 统信UOS 麒麟 bonding 链路聚合 chatgpt llama3 Chatglm 开源大模型 jar gradle C# MQTTS 双向认证 emqx vim VMware安装mocOS VMware macOS系统安装 camera Arduino 电子信息 Dell R750XS 僵尸进程 温湿度数据上传到服务器 Arduino HTTP unity 计算机视觉 产品经理 agi microsoft sql KingBase 自动化 rag ragflow ragflow 源码启动 YOLOv12 oceanbase rc.local 开机自启 systemd uni-app cuda cudnn anaconda 微服务 springcloud pillow rtsp rtp 智能手机 NAS Termux Samba Linux postman mock mock server 模拟服务器 mock服务器 Postman内置变量 Postman随机数据 WSL win11 无法解析服务器的名称或地址 pytorch 迁移指南 ffmpeg 音视频 vue3 HTML audio 控件组件 vue3 audio音乐播放器 Audio标签自定义样式默认 vue3播放音频文件音效音乐 自定义audio播放器样式 播放暂停调整声音大小下载文件 向日葵 MacOS录屏软件 DeepSeek-R1 API接口 spring CH340 串口驱动 CH341 uart 485 vue safari Mac 系统 系统架构 网络穿透 云服务器 ollama下载加速 k8s bug 负载均衡 prometheus 远程工作 弹性计算 裸金属服务器 弹性裸金属服务器 虚拟化 跨域 微信小程序 小程序 工业4.0 openEuler unity3d 驱动开发 硬件工程 嵌入式实习 gitlab express okhttp CORS 飞书 微信开放平台 微信公众平台 微信公众号配置 nvidia dns r语言 数据可视化 恒源云 医疗APP开发 app开发 Trae IDE AI 原生集成开发环境 Trae AI 致远OA OA服务器 服务器磁盘扩容 Cline 系统安全 kylin arm 能力提升 面试宝典 技术 IT信息化 无人机 机器人 实时音视频 eureka bash k8s集群资源管理 云原生开发 apache 职场和发展 Kylin-Server 国产操作系统 服务器安装 大语言模型 LLMs django sqlite AI写作 prompt openssl 密码学 监控 自动化运维 Docker Hub docker pull 镜像源 daemon.json list 模拟实现 fd 文件描述符 蓝耘科技 元生代平台工作流 ComfyUI code-server MQTT mosquitto 消息队列 CPU 主板 电源 网卡 devops ci/cd DevEco Studio linux安装配置 kali 共享文件夹 虚拟机 硬件架构 半虚拟化 硬件虚拟化 Hypervisor https AISphereButler 课程设计 kamailio sip VoIP zabbix 大数据平台 threejs 3D echarts 信息可视化 数据分析 网页设计 LLM 大模型面经 Deepseek 大模型学习 SenseVoice 媒体 wsl Java Applet URL操作 服务器建立 Socket编程 网络文件读取 单元测试 集成测试 功能测试 selenium ukui 麒麟kylinos openeuler fpga开发 统信 虚拟机安装 rime 缓存 redis 灵办AI kvm 并查集 leetcode web3.py Open WebUI 毕设 VPS pyqt outlook IIS .net core Hosting Bundle .NET Framework vs2022 C语言 hadoop 测试工具 svn wsl2 服务器主板 AI芯片 gpt 信号处理 孤岛惊魂4 WebRTC 网络药理学 生信 生物信息学 gromacs 分子动力学模拟 MD 动力学模拟 trae openwrt RoboVLM 通用机器人策略 VLA设计哲学 vlm fot robot 视觉语言动作模型 具身智能 ux 多线程 VMware安装Ubuntu Ubuntu安装k8s RTMP 应用层 jupyter Python 网络编程 聊天服务器 套接字 TCP Socket vmware 卡死 DeepSeek 自动化编程 DNS IPMITOOL BMC 硬件管理 opcua opcda KEPServer安装 ssh漏洞 ssh9.9p2 CVE-2025-23419 游戏服务器 TrinityCore 魔兽世界 Invalid Host allowedHosts 远程连接 rdp 实验 代码调试 ipdb adobe 多层架构 解耦 RAGFLOW kafka web安全 中间件 iis OD机试真题 华为OD机试真题 服务器能耗统计 ros2 moveit 机器人运动 云服务 NPS 雨云服务器 雨云 可信计算技术 springsecurity6 oauth2 授权服务器 token sas 压力测试 低代码 分析解读 NFS redhat postgresql 云电竞 云电脑 todesk pdf 群晖 文件分享 智能音箱 智能家居 pygame 服务器数据恢复 数据恢复 存储数据恢复 raid5数据恢复 磁盘阵列数据恢复 交换机 telnet 远程登录 shell 远程控制 远程看看 远程协助 visualstudio 银河麒麟操作系统 国产化 gpt-3 文心一言 ping++ rsyslog wireshark 显示过滤器 ICMP Wireshark安装 三级等保 服务器审计日志备份 dba yum 串口服务器 实战案例 小艺 Pura X excel 黑客技术 线程 流式接口 html css llm 本地部署 api react next.js 部署 部署next.js 华为认证 网络工程师 拓扑图 DigitalOcean GPU服务器购买 GPU服务器哪里有 GPU服务器 ocr matlab AI大模型 visual studio code bootstrap Kali Linux 黑客 渗透测试 信息收集 ecmascript nextjs reactjs 压测 ECS P2P HDLC 思科 ssrf 失效的访问控制 RAID RAID技术 磁盘 存储 xrdp 远程桌面 string模拟实现 深拷贝 浅拷贝 经典的string类问题 三个swap gitee 开发环境 SSL证书 dify 网络结构图 王者荣耀 交叉编译 硬件 设备 GPU PCI-Express Google pay Apple pay 环境迁移 实时互动 k8s资源监控 annotations自动化 自动化监控 监控service 监控jvm android studio 交互 grafana thingsboard 程序员 远程 命令 执行 sshpass 操作 wps 安卓 jellyfin ArcTS 登录 ArcUI GridItem 设计模式 软件工程 arkUI rabbitmq 直播推流 TRAE 金融 openvpn server openvpn配置教程 centos安装openvpn 其他 状态管理的 UDP 服务器 Arduino RTOS 视觉检测 VMware创建虚拟机 gitea etcd 数据安全 RBAC 企业微信 Linux24.04 deepin ruoyi 强制清理 强制删除 mac废纸篓 腾讯云 Java Wi-Fi 自动驾驶 springboot远程调试 java项目远程debug docker远程debug java项目远程调试 springboot远程 Reactor C++ Ark-TS语言 UOS 统信操作系统 mybatis AI代码编辑器 小游戏 五子棋 mamba Vmamba docker搭建nacos详解 docker部署nacos docker安装nacos 腾讯云搭建nacos centos7搭建nacos transformer lio-sam SLAM cmos webrtc kind 重启 排查 系统重启 日志 原因 腾讯云大模型知识引擎 mysql离线安装 ubuntu22.04 mysql8.0 spring cloud 源码 毕业设计 多进程 大模型入门 大模型教程 IPMI Node-Red 编程工具 流编程 宝塔面板 混合开发 环境安装 JDK KylinV10 麒麟操作系统 Vmware 服务器配置 京东云 iBMC UltraISO KVM 命令行 基础入门 编程 报错 hive Hive环境搭建 hive3环境 Hive远程模式 SSH Xterminal firewalld 产测工具框架 IMX6ULL 管理框架 测试用例 centos-root /dev/mapper yum clean all df -h / du -sh 磁盘监控 Cookie JAVA 银河麒麟服务器操作系统 系统激活 chrome 浏览器下载 chrome 下载安装 谷歌浏览器下载 arcgis 开发 ansible playbook 剧本 Portainer搭建 Portainer使用 Portainer使用详解 Portainer详解 Portainer portainer virtualenv ue4 着色器 虚幻 pyautogui 博客 oneapi 大模型微调 开机自启动 Linux无人智慧超市 LInux多线程服务器 QT项目 LInux项目 单片机项目 Ubuntu Server Ubuntu 22.04.5 MS Materials yum源切换 更换国内yum源 飞牛NAS 飞牛OS MacBook Pro QQ bot Docker AP配网 AK配网 小程序AP配网和AK配网教程 WIFI设备配网小程序UDP开 安全架构 网络攻击模型 深度优先 图论 并集查找 换根法 树上倍增 n8n 工作流 workflow mariadb p2p 图像处理 框架搭建 游戏机 SWAT 配置文件 服务管理 网络共享 gaussdb 进程信号 remote-ssh 蓝桥杯 DeepSeek行业应用 Heroku 网站部署 IIS服务器 IIS性能 日志监控 RustDesk自建服务器 rustdesk服务器 docker rustdesk mongodb micropython esp32 mqtt iftop 网络流量监控 服务器繁忙 nuxt3 微信小程序域名配置 微信小程序服务器域名 微信小程序合法域名 小程序配置业务域名 微信小程序需要域名吗 微信小程序添加域名 EasyConnect linux 命令 sed 命令 springboot 算力 Redis Desktop 高效远程协作 TrustViewer体验 跨设备操作便利 智能远程控制 传统数据库升级 银行 hibernate 权限 npm windwos防火墙 defender防火墙 win防火墙白名单 防火墙白名单效果 防火墙只允许指定应用上网 防火墙允许指定上网其它禁止 asp.net大文件上传 asp.net大文件上传源码 ASP.NET断点续传 asp.net上传文件夹 asp.net上传大文件 .net core断点续传 .net mvc断点续传 安全威胁分析 matplotlib 多线程服务器 Linux网络编程 FTP 服务器 W5500 OLED u8g2 TCP服务器 log4j 矩阵 漏洞 服务器管理 配置教程 网站管理 同步 备份 建站 办公自动化 自动化生成 pdf教程 火绒安全 Nuxt.js 历史版本 下载 Xinference RAGFlow frp 内网服务器 内网代理 内网通信 RAG 检索增强生成 文档解析 大模型垂直应用 etl UOS1070e ruby 计算机 docker命令大全 Ubuntu DeepSeek DeepSeek Ubuntu DeepSeek 本地部署 DeepSeek 知识库 DeepSeek 私有化知识库 本地部署 DeepSeek DeepSeek 私有化部署 AD 域管理 网站搭建 serv00 bcompare Beyond Compare DocFlow mq rocketmq uniapp v10 软件 ip命令 新增网卡 新增IP 启动网卡 高级IO epoll 备选 网站 调用 示例 小智AI服务端 xiaozhi ASR TTS 边缘计算 Linux的权限 怎么卸载MySQL MySQL怎么卸载干净 MySQL卸载重新安装教程 MySQL5.7卸载 Linux卸载MySQL8.0 如何卸载MySQL教程 MySQL卸载与安装 SSH 服务 SSH Server OpenSSH Server cursor 上传视频至服务器代码 vue3批量上传多个视频并预览 如何实现将本地视频上传到网页 element plu视频上传 ant design vue vue3本地上传视频及预览移除 SSE Ubuntu 24 常用命令 Ubuntu 24 Ubuntu vi 异常处理 业界资讯 鲲鹏 文件系统 用户缓冲区 推荐算法 网卡的名称修改 eth0 ens33 EMUI 回退 降级 升级 监控k8s 监控kubernetes gnu 互信 apt Claude AnythingLLM AnythingLLM安装 SRS 流媒体 直播 skynet 版本 gcc dash 正则表达式 pgpool 做raid 装系统 端口测试 yolov8 LORA NLP 田俊楠 sublime text 反向代理 Kali 渗透 CrewAI 常用命令 文本命令 目录命令 python3.11 qemu libvirt minio 视频编解码 游戏程序 大大通 第三代半导体 碳化硅 图形化界面 URL 换源 国内源 Debian web VM搭建win2012 win2012应急响应靶机搭建 攻击者获取服务器权限 上传wakaung病毒 应急响应并溯源 挖矿病毒处置 应急响应综合性靶场 edge浏览器 远程过程调用 Windows环境 搜索引擎 h.264 ssh远程登录 big data langchain deep learning Jellyfin opensearch helm 云桌面 微软 AD域控 证书服务器 MI300x tensorflow 健康医疗 FTP服务器 web3 tcp GCC crosstool-ng USB网络共享 监控k8s集群 集群内prometheus open Euler dde Ubuntu22.04 开发人员主页 centos 7 IMM 输入法 c rustdesk 单一职责原则 移动云 崖山数据库 YashanDB ArkTs ArkUI 键盘 selete 昇腾 npu asp.net大文件上传下载 北亚数据恢复 oracle数据恢复 金仓数据库 2025 征文 数据库平替用金仓 jvm MCP server C/S cnn GoogLeNet zookeeper nfs 服务器部署ai模型 sqlite3 SSL 域名 dity make Anolis nginx安装 linux插件下载 高效日志打印 串口通信日志 服务器日志 系统状态监控日志 异常记录日志 DBeaver 数据仓库 kerberos 繁忙 解决办法 替代网站 汇总推荐 AI推理 Linux awk awk函数 awk结构 awk内置变量 awk参数 awk脚本 awk详解 MQTT协议 消息服务器 代码 Windows ai工具 H3C ldap MacMini 迷你主机 mini Apple 5G 3GPP 卫星通信 宠物 免费学习 宠物领养 宠物平台 ios searxng 3d PPI String Cytoscape CytoHubba GIS 遥感 WebGIS Docker引擎已经停止 Docker无法使用 WSL进度一直是0 镜像加速地址 XCC Lenovo 人工智能生成内容 docker run 数据卷挂载 交互模式 saltstack embedding 联想开天P90Z装win10 前后端分离 多个客户端访问 IO多路复用 回显服务器 TCP相关API 远程服务 openstack Xen IM即时通讯 剪切板对通 HTML FORMAT 大文件分片上传断点续传及进度条 如何批量上传超大文件并显示进度 axios大文件切片上传详细教 node服务器合并切片 vue3大文件上传报错提示错误 大文件秒传跨域报错cors 阿里云ECS 网工 个人博客 稳定性 看门狗 程序员创富 集成学习 QT 5.12.12 QT开发环境 Ubuntu18.04 VR手套 数据手套 动捕手套 动捕数据手套 技能大赛 聚类 程序 性能分析 linux环境变量 vue-i18n 国际化多语言 vue2中英文切换详细教程 如何动态加载i18n语言包 把语言json放到服务器调用 前端调用api获取语言配置文件 av1 电视盒子 机顶盒ROM 魔百盒刷机 数学建模 数据库架构 数据管理 数据治理 数据编织 数据虚拟化 Deepseek-R1 私有化部署 推理模型 ROS elk eNSP 网络规划 VLAN 企业网络 自动化测试 性能测试 小番茄C盘清理 便捷易用C盘清理工具 小番茄C盘清理的优势尽显何处? 教你深度体验小番茄C盘清理 C盘变红?!不知所措? C盘瘦身后电脑会发生什么变化? odoo 服务器动作 Server action 阻塞队列 生产者消费者模型 服务器崩坏原因 keepalived 虚拟局域网 sonoma 自动更新 less xshell termius iterm2 neo4j 数据库开发 database 显卡驱动 大模型应用 chrome devtools chromedriver 相差8小时 UTC 时间 Docker Compose docker compose docker-compose netty can 线程池 es seatunnel swoole Playwright Cursor nac 802.1 portal pppoe radius 无桌面 序列化反序列化 risc-v linux上传下载 SSH 密钥生成 SSH 公钥 私钥 生成 tidb GLIBC webstorm 我的世界 我的世界联机 数码 软考 游戏引擎 vasp安装 seleium AutoDL 信创 信创终端 中科方德 技术共享 执法记录仪 智能安全帽 smarteye Radius yaml Ultralytics 可视化 wordpress 无法访问wordpess后台 打开网站页面错乱 linux宝塔面板 wordpress更换服务器 SysBench 基准测试 ecm bpm 图形渲染 ceph 宕机切换 服务器宕机 黑苹果 sdkman sequoiaDB xml 音乐服务器 Navidrome 音流 windows日志 alias unalias 别名 EMQX 通信协议 深度求索 私域 知识库 Minecraft uv glibc DOIT 四博智联 虚拟显示器 prometheus数据采集 prometheus数据模型 prometheus特点 物联网开发 freebsd 软负载 HiCar CarLife+ CarPlay QT RK3588 CLion jina 匿名管道 Dell HPE 联想 浪潮 iDRAC R720xd ros idm 考研 rnn 聊天室 Linux的基础指令 curl wget 服务器无法访问 ip地址无法访问 无法访问宝塔面板 宝塔面板打不开 composer aarch64 编译安装 HPC XFS xfs文件系统损坏 I_O error muduo AD域 X11 Xming flash-attention uni-file-picker 拍摄从相册选择 uni.uploadFile H5上传图片 微信小程序上传图片 树莓派 VNC 系统开发 binder 车载系统 framework 源码环境 私有化 FunASR 域名服务 DHCP 符号链接 配置 file server http server web server 计算虚拟化 弹性裸金属 目标跟踪 OpenVINO 推理应用 MySql Linux PID 本地部署AI大模型 easyui 运维监控 LInux 邮件APP 免费软件 jetty undertow grub 版本升级 扩容 代理 飞牛nas fnos ISO镜像作为本地源 显示管理器 lightdm gdm ip 备份SQL Server数据库 数据库备份 傲梅企业备份网络版 华为机试 宝塔 CentOS Stream CentOS 自定义客户端 SAS 磁盘镜像 服务器镜像 服务器实时复制 实时文件备份 Erlang OTP gen_server 热代码交换 事务语义 OpenManus MNN Qwen 链表 hugo 指令 deepseek r1 UDP的API使用 Netty 即时通信 NIO x64 SIGSEGV xmm0 armbian u-boot HTTP 服务器控制 ESP32 DeepSeek miniapp 真机调试 调试 debug 断点 网络API请求调试方法 dns是什么 如何设置电脑dns dns应该如何设置 银河麒麟桌面操作系统 Kylin OS 在线预览 xlsx xls文件 在浏览器直接打开解析xls表格 前端实现vue3打开excel 文件地址url或接口文档流二进 AI作画 iphone HarmonyOS AI agent 思科模拟器 Cisco ftp ShenTong CVE-2024-7347 make命令 makefile文件 vscode1.86 1.86版本 ssh远程连接 qt项目 qt项目实战 qt教程 LLM Web APP Streamlit 模拟退火算法 英语 国标28181 视频监控 监控接入 语音广播 流程 SIP SDP xcode 设置代理 实用教程 镜像 WebUI DeepSeek V3 nlp 路径解析 rclone AList webdav fnOS 相机 银河麒麟高级服务器 外接硬盘 Kylin open webui 自动化任务管理 社交电子 数据库系统 vscode 1.86 minicom 串口调试工具 VSCode 直流充电桩 充电桩 DenseNet SEO chfs ubuntu 16.04 AI-native Docker Desktop spark HistoryServer Spark YARN jobhistory Attention Ubuntu 24.04.1 轻量级服务器 DIFY VS Code 需求分析 规格说明书 代码托管服务 opengl 离线部署dify 模拟器 教程 ubuntu24 vivado24 免费域名 域名解析 语音识别 c/c++ 串口 yolov5 perl 企业网络规划 华为eNSP 双系统 CDN 嵌入式Linux IPC EtherNet/IP串口网关 EIP转RS485 EIP转Modbus EtherNet/IP网关协议 EIP转RS485网关 EIP串口服务器 支付 微信支付 开放平台 PX4 Headless Linux Python基础 Python教程 Python技巧 axure 富文本编辑器 毕昇JDK wpf WLAN 多端开发 智慧分发 应用生态 鸿蒙OS idea cocoapods flink 中兴光猫 换光猫 网络桥接 自己换光猫 Mermaid 可视化图表 防火墙 NAT转发 NAT Server WebVM 基础环境 流水线 脚本式流水线 安防软件 java-rocketmq ubuntu20.04 开机黑屏 元服务 应用上架 Zoertier 内网组网 沙盒 项目部署到linux服务器 项目部署过程 增强现实 沉浸式体验 应用场景 技术实现 案例分析 AR css3 trea 虚幻引擎 virtualbox cpp-httplib 影刀 #影刀RPA# 存储维护 NetApp存储 EMC存储 Typore TrueLicense vpn 超融合 deekseek 浏览器开发 AI浏览器 实习 WSL2 上安装 Ubuntu sysctl.conf vm.nr_hugepages 强化学习 rancher 烟花代码 烟花 元旦 嵌入式系统开发 lsb_release /etc/issue /proc/version uname -r 查看ubuntu版本 figma 代理服务器 Mac内存不够用怎么办 信号 僵尸世界大战 游戏服务器搭建 磁盘清理 进程优先级 调度队列 进程切换 powerpoint 单例模式 perf fonts-noto-cjk conda配置 conda镜像源 cfssl TCP协议 架构与原理 抗锯齿 nftables banner 内网环境 firewall Logstash 日志采集 triton 模型分析 su sudo 本地知识库部署 DeepSeek R1 模型 大模型技术 本地部署大模型 GRUB引导 Linux技巧 IDEA 大模型部署 ArtTS 7z MVS 海康威视相机 Unity Dedicated Server Host Client 无头主机 环境配置 热榜 dock 加速 lb 协议 Linux环境 midjourney OpenSSH word sentinel 知识图谱 服务网格 istio 区块链 db IPv4 子网掩码 公网IP 私有IP 互联网医院 主从复制 佛山戴尔服务器维修 佛山三水服务器维修 K8S k8s管理系统 语法 我的世界服务器搭建 加解密 Yakit yaklang OpenHarmony 搭建个人相关服务器 linux内核 干货分享 黑客工具 密码爆破 Ubuntu共享文件夹 共享目录 Linux共享文件夹 iperf3 带宽测试 鸿蒙开发 移动开发 tailscale derp derper 中转 捆绑 链接 谷歌浏览器 youtube google gmail 线性代数 电商平台 安卓模拟器 服务器时间 虚拟现实 C++软件实战问题排查经验分享 0xfeeefeee 0xcdcdcdcd 动态库加载失败 程序启动失败 程序运行权限 标准用户权限与管理员权限 hosts 智能电视 eclipse 像素流送api 像素流送UE4 像素流送卡顿 像素流送并发支持 SVN Server tortoise svn 带外管理 本地环回 bind 自学笔记 小米 澎湃OS Android regedit 开机启动 onlyoffice 在线office lua HarmonyOS NEXT 原生鸿蒙 iventoy VmWare OpenEuler 端口 查看 ss webgl 本地化部署 读写锁 AI Agent 字节智能运维 autodl 玩机技巧 软件分享 软件图标 音乐库 飞牛 g++ g++13 k8s二次开发 集群管理 rtsp服务器 rtsp server android rtsp服务 安卓rtsp服务器 移动端rtsp服务 大牛直播SDK Spring Security react native ubuntu24.04.1 IO模型 游戏开发 移动魔百盒 USB转串口 harmonyOS面试题 大模型推理 软件构建 fast DeepSeek r1 Qwen2.5-VL vllm cd 目录切换 AzureDataStudio 网络建设与运维 minecraft NLP模型 xss Doris搭建 docker搭建Doris Doris搭建过程 linux搭建Doris Doris搭建详细步骤 Doris部署 xpath定位元素 IMX317 MIPI H265 VCU bat 李心怡 计算生物学 生物信息 基因组 查询数据库服务IP地址 SQL Server 分布式训练 docker部署Python llama.cpp docker部署翻译组件 docker部署deepl docker搭建deepl java对接deepl 翻译组件使用 HAProxy GameFramework HybridCLR Unity编辑器扩展 自动化工具 策略模式 根服务器 clickhouse 软链接 硬链接 laravel junit 上传视频文件到服务器 uniApp本地上传视频并预览 uniapp移动端h5网页 uniapp微信小程序上传视频 uniapp app端视频上传 uniapp uview组件库 hexo powerbi MDK 嵌入式开发工具 论文笔记 kotlin visual studio 开源软件 notepad 话题通信 服务通信 IO ranger MySQL8.0 隐藏文件 隐藏目录 管理器 通配符 Helm k8s集群 tar burp suite 抓包 vnc ebpf uprobe oracle fusion oracle中间件 lvm 磁盘挂载 磁盘分区 硅基流动 ChatBox wsgiref Web 服务器网关接口 zip unzip 网络爬虫 智慧农业 开源鸿蒙 团队开发 跨平台 ardunio BLE Linux 维护模式 WebServer mysql安装报错 windows拒绝安装 kernel Linux权限 权限命令 特殊权限 ABAP scapy CPU 使用率 系统监控工具 linux 命令 电视剧收视率分析与可视化平台 AI员工 MAC SecureCRT 问题解决 java-rabbitmq 论文阅读 服务器扩容没有扩容成功 UDP UEFI Legacy MBR GPT U盘安装操作系统 Sealos 视频平台 录像 视频转发 视频流 proxy模式 授时服务 北斗授时 性能调优 安全代理 MacOS scikit-learn shell脚本免交互 expect linux免交互 网络搭建 神州数码 神州数码云平台 云平台 copilot Apache Beam 批流统一 案例展示 数据分区 容错机制 网页服务器 web服务器 Nginx ELF加载 风扇控制软件 cmake ip协议 export import save load 迁移镜像 服务器部署 本地拉取打包 CosyVoice top Linux top top命令详解 top命令重点 top常用参数 华为证书 HarmonyOS认证 华为证书考试 docker搭建pg docker搭建pgsql pg授权 postgresql使用 postgresql搭建 输入系统 浪潮信息 AI服务器 fork wait waitpid exit milvus Web服务器 多线程下载工具 PYTHON MAVROS 四旋翼无人机 windows 服务器安装 ubuntu 18.04 查看显卡进程 fuser 项目部署 Web应用服务器 工具 Alexnet python2 ubuntu24.04 内核 多路转接 极限编程 安装MySQL 容器技术 通信工程 毕业 Carla 智能驾驶 合成模型 扩散模型 图像生成 多产物 mm-wiki搭建 linux搭建mm-wiki mm-wiki搭建与使用 mm-wiki使用 mm-wiki详解 Reactor反应堆 cron crontab日志 网络文件系统 samba 流量运营 对比 meld DiffMerge 服务器安全 网络安全策略 防御服务器攻击 安全威胁和解决方案 程序员博客保护 数据保护 安全最佳实践 端口聚合 windows11 达梦 DM8 System V共享内存 进程通信 mcp服务器 client close ros1 Noetic 20.04 apt 安装 docker desktop image nvm whistle Unity插件 deployment daemonset statefulset cronjob 图片增强 增强数据 欧标 OCPP fstab 浏览器自动化 ROS2 rpa 国产数据库 瀚高数据库 数据迁移 下载安装 Mac软件 Linux find grep 钉钉 宝塔面板无法访问 抓包工具 vu大文件秒传跨域报错cors nosql maxkb ARG 机柜 1U 2U 粘包问题 win服务器架设 windows server navicat 云耀服务器 React Next.js 开源框架 软件卸载 系统清理 状态模式 联机 僵尸毁灭工程 游戏联机 开服 显示器 MobaXterm 文件传输 VMware Tools vmware tools安装 vmwaretools安装步骤 vmwaretools安装失败 vmware tool安装步骤 vm tools安装步骤 vm tools安装后不能拖 vmware tools安装步骤 数字证书 签署证书 蓝牙 零售 yum换源 镜像下载 大屏端 西门子PLC 通讯 netlink libnl3 stable diffusion lighttpd安装 Ubuntu配置 Windows安装 服务器优化 工具分享 ubuntu安装 linux入门小白 弹性服务器 csrutil mac恢复模式进入方法 恢复模式 WINCC js 服务器ssl异常解决 生活 接口优化 代码规范 服务器正确解析请求体 macOS DevOps 软件交付 数据驱动 Docker快速入门 zerotier 解决方案 qt5 客户端开发 搜狗输入法 中文输入法 录音麦克风权限判断检测 录音功能 录音文件mp3播放 小程序实现录音及播放功能 RecorderManager 解决录音报错播放没声音问题