当前位置: 首页 > news >正文

Linux系统之Uboot、Kernel、Busybox思考之一

目录

一 基础环境

1 硬件基础环境

2 软件基础环境

2.1 Uboot

2.2 内核

2.3 文件系统

二 启动过程

1

2

3

4

5

6

7


一 基础环境

1 硬件基础环境

  CPU、内存和FLASH为基础环境,有了这三样,程序就可以跑起来。在此基础上补充各种外设,扩展功能,丰富应用场景。

2 软件基础环境

  软件基础环境主要由UBOOT、内核和文件系统构成。

2.1 Uboot

  UBOOT为引导程序,完成基本的一些初始化工作,可提供系统刷机升级、引导内核的功能。

  UBOOT中一般使用物理地址,不进行虚拟地址到物理地址的转换。当然也可以做这项工作,但是作为boot程序,简单考虑,没有这样做的必要。

  嵌入式Linux的引导程序也不止uboot一种,只是目前uboot较为流行。

  我们测试中,uboot配置的变量保存在flash中uboot结尾的部分。实际产品中,有不同的方案可以选择。比如对flash进行定制分区,提供专门存放数据的分区,并提供备份。

  在海思系列中,uboot中提供了片上芯片的专用配置,比如管脚复用情况,上拉下拉配置,输出驱动能力配置等。

  uboot会影响系统整体启动的时间,可以通过缩减部分检测功能,修改hit key时间等,加快整机启动速度。

  uboot对应的kernel格式为压缩后加头部信息的uImage格式镜像。可以传递参数给kernel。

  uboot自身支持组合命令,可以将多个操作放在一起,重命名为一个组合命令,有点类似函数调用子函数的意味。

  总的原则来讲,uboot就是用最简单的方式,提供一些便捷的基础功能。本身主要用于引导,执行完成后,就退出内存。

2.2 内核

  内核提供操作系统基础环境。诸如驱动、进程、内存管理、文件系统、网络、体系结构支持等。

  了解内核,需要了解

  1 内核有自己的编码风格

  2 内核使用GNU C,对标准C有扩展。这些扩展会要求汇编时做一些处理,这些处理会方便内核处理底层逻辑。比如放到特定的段,结构体的初始化,对齐,0长度数组等。但是内核也受C的一些约束,比如变量要在函数开头定义好。

  3 内核提供一些标准数据结构和宏,方便功能实现。比如链表、通过域获取结构体的地址等。另外提供树、加密等标准功能模块。

  4 内核提供一些数据结构和宏用于处理体系结构差异,比如机器相关数据结构,大小端、字节对齐、IO访问宏等

  5 内核工作基础基于时钟、中断

  6 上述基础上提供进程、进程管理、进程调度

  7 上述基础上提供内存、内存管理、内存映射、DMA内存

  8 上述基础上提供锁和同步原语接口,自旋锁、信号量、互斥锁、读写锁、读写更新锁

  9 内核提供SMP的支持,提供抢占,包括单CPU的抢占、CPU之间的抢占

  10 内核提供针对每个CPU独立的数据,减少锁和缓存失效可能

  11 内核提供文件系统接口,支持虚拟文件系统

  12 内核提供驱动框架,封装硬件,包括CPU、CPU片上控制器、各种硬件接口及总线、字符设备、块设备、网络设备,并进行全局的文件化抽象。

  13 内核提供驱动框架的抽象化,从总线、设备、驱动引申出平台总线、设备及驱动,再到对象、集合、类型框架,最终导出sysfs

  14 内核提供延迟、休眠接口,提供信号唤醒机制,提供异步IO机制,提供事件上报机制,基于sysfs。

  15 内核提供用户空间和内核空间信息的交换,包括内存映射、驱动ioctl、sysfs、netlink等

  16 内核提供模块机制,提供依赖解决方案,模块可支持参数读取,简化内核的扩展

  17 内核提供对错误信息的日志输出,方便调试

  18 内核提供系统调用,实现用户空间和内核空间的切换

  19 内核提供丰富全面的配置接口(大部分运行时可配),可对各种策略、算法、功能、模块进行粗调细调,从而发挥机制的统领作用,实现一定程度的通用性。

  20 内核提供大量的编译配置,从而具备很强的可伸缩性,适用于从单核、低速、低内存的嵌入式设备到集群、高性能、高可靠的服务器领域。

2.3 文件系统

  文件系统(典型的Busybox)提供应用基础环境。包括C库,基础命令工具,文件系统使用环境等。

  同uboot,busybox也只是一种比较流行的基础文件系统环境,还有其他的方案可供选择。比如buildroot?构建工具?

  Busybox主要是提供根文件系统。根文件系统首先提供一个init程序,该程序是内核完成工作后,调用用户空间的第一个程序。

  通过init程序,不断的准备用户空间环境并fork出新的程序,最终完成系统的整体启动,进入shell怠速状态。

  init作为所有用户空间进程的祖父进程,根据Linux的进程管理关系,可以最终获知任何僵尸进程的退出信息,并进行服务程序的重启管理等。

  在上述三者基础上,提供专有应用的软件基础环境。

二 启动过程

1

  内核可以接受多种参数,以便定制化自己的启动约束条件,诸如分区信息、初始程序等。

  内核参数一般可以由UBOOT提供。setenv可以设置保存UBOOT的环境参数。UBOOT将环境参数保存到UBOOT分区的特定位置,一般是开始或者结尾部分。

  UBOOT运行完成后,根据配置的分区信息、内核地址、启动地址及内核初始参数,将内核代码加载到内存固定地址中,然后跳转到内核起始代码处执行,并最终进入start_kernel执行。

  UBOOT在将CPU控制权限交给内核时,需要传递一些参数。参数传递方式无外乎两种,一种是通过压栈的方式,这跟函数调用一致;一种是传递参数存储地址的方式,比如将参数区域地址放入某个通用寄存器,然后kernel启动后,从该寄存器指示的地址区域获取启动参数。无论哪一种方式,都需要对参数格式有统一约定。

  对于栈方式,需要构建栈环境。开始的汇编代码,并不天然的具备栈调用基础。

  具体如何跳转的?从汇编角度来看,涉及修改pc寄存器值得指令,都可能实现跳转功能。但跳转到内核有一个特点,就是永远不会再回来了。这是跟普通代码中的跳转最大的不同。

  关于地址,内核各个模块编译后的地址都是相对地址。最后生成类似vmlinux文件后,各个符合的地址就是最终确定的(虚拟地址)。我们也可以使用vmlinux生成的符合来debug内核,协助解决内核中出现的问题。

2

  Start后,内核进行初始化工作。这过程中,包括对CPU子系统的初始化,进程管理的构建,内存管理的构建,公共子系统的构建,比如中断框架,锁框架,延时、定时器、模块、对象等等。

  这里,我们没有提到设备驱动,显然,驱动加载是初始化过程中的重要一环,总不能操作系统运行起来了,各种外设硬件资源不能使用。但是这里我们没有把驱动放在前面,这是为什么?

  这可以转化为一个新的问题,即设备驱动在内核初始化过程中,是什么时候加载执行的?答案是,驱动没有想象中加载的那么早。

  驱动是在内核线程1启动后,在内核线程1中加载的。该线程后续孵化了各种应用层程序,所以该内核线程是具有应用进程内存映射区的。关于这一点,后面会单独说明。

  根据内核注释,设备驱动加载时,CPU子系统已经构建起来,并运行了。内存和进程管理也开始工作了。

  据此,我们可以反推,在驱动中,可能用到内核的不少特性,比如内存分配,各种锁,中断子系统,软中断线程,工作队列,等待队列,睡眠等等。

  另外,驱动还可能与用户空间打交道,比如ioctl有可能要用吧,内核空间和用户空间内存拷贝可能要用吧,这也是为啥要用内核线程1,因为内核线程2孵化的线程都是纯内核线程,没有用户空间内存映射的。

  对了,驱动模型也需要提前构建好。比如sys子系统,其目录下的各个子目录,驱动加载过程中可能会用到。

  所以,总结一句话,驱动模块的加载没有想象的那么早,因为准备工作的确不少。驱动加载后,就要执行初始化程序。

  驱动的初始化是串行的吗?

3

  内核完成初始化后,需要挂载根文件系统,执行用户空间程序,将控制权交给应用层用户。这其中,用户空间的初始程序可以是通过bootargs参数传递给内核的,也可以是根文件系统中默认的。

  默认方式的程序,在内核的main文件中预定义了四个,分别处于不同的路径下。

  如何从内核空间切换到第一个用户空间?

  init进程调用run_init_process --> do_execve加载新的可执行文件执行。需要准备环境变量,需要加载elf可执行文件代码,需要加载相关动态库

  上述资源的加载更需要建立新的页表映射。

  最后是否需要通过模拟软中断返回,将控制权限交给应用层代码?这是需要的,切换到用户空间之后,特权指令就是关闭的。

  内核态切换到用户态,应该是需要通过模拟中断返回,退出内核态。init进程应该没有返回。否则,返回到哪里?在内核kernel_execve执行用户空间代码时,有b  ret_to_user的汇编。

  因此,这个调用就实现从内核态切换到用户态。仔细思考一下,不单单是init,后续创建新的进程时,都会通过系统调用进入到内核空间,在内核空间完成任务相关结构体的创建。

  虽然构建工作在内核空间,但运行时,最终都无一例外的要回退到用户空间,执行入口代码。所以,切换到用户空间,是一个通用需求。

  四个地方是不存在跳过亦或只执行第一个存在的init程序?比如找到了两个,是只执行第一个?

  内核1号进程先检查命令行是否提供了初始程序,如果有(分ramdisk和非ramdisk),并且执行成功,则返回,否则检查四个地方,这四个地方是或条件连接,所以任何一个执行成功则返回,并且有先后优先级顺序。

4

  内核启动过程中会创建创世进程idle进程,pid为0。idle进程是手工创建的,也就是进程结构体所需的各个资源都是手动配置的,之后的进程可以通过调用do_fork,从0进程孵化出来。

  idle进程创建过程中会逐步准备一个真正的内核进程所需要的资源,包括虚拟内存空间,等等。

  idle进程的主要工作是准备资源和环境,完成后,进入idle状态,什么也不做。内核会为每个核心配备一个idle进程,调度器在发现运行队列为空时,调度idle进程,放空CPU。

  我们看到idle进程一般执行死循环。对于CPU来讲,执行循环指令和执行普通的加减指令,并无特别大的区别(当然,指令涉及到的耗电是有一些差别的),所以idle循环时并不能真的让CPU处于idle状态。

  其实,现代CPU都有特殊指令提供,让idle的核心比较真的处于idle状态,类似睡眠中,并通过事件唤醒,这样可以真正的降低功耗。

  idle进程准备资源的过程。

5

  内核启动过程中,会创建两类线程,由idle进程通过调用do_fork孵化。第一类的父进程是1号进程,init进程。上述驱动初始化就在该进程中。

  1号进程所孵化的进程都有一个特点,就是这些进程都是用户空间进程。因为内核init线程挂载跟文件系统,执行用户空间init程序,由该init程序完成所有其他应用的创建,包括所有shell方式创立的进程。

  第二类是2号进程。2号进程所孵化的进程都有一个特点,这些进程,严格来讲,应该是内核线程,都没有用户空间映射。也就是说,2号的孩子都运行在内核空间中。

  比如,内核的软中断线程,工作队列线程,RCU,交换后台,设备驱动相关的一些工作线程。这些线程一般不需要跟用户空间打交道,是为整个内核服务的。

  内核的进程树关系?

  idle 即0进程创建了 1号init 进程和 2号kthreadd 进程。

  1号进程执行文件系统中的可执行程序或者命令程序,创建用户空间进程。用户空间进程进一步创建新的用户空间进程。

  2号进程创建内核工作所需的各类进程。这些进程是通过kernel_thread接口调用创建的。该调用将进程结构放到进程创建列表上,通知2号进程。2号进程检查内核进程创建列表,如果发现有需要创建的进程,则创建对应的内核进程。

  如果不采用这种方式,而是像用户进程那样,在需要的地方就直接调用do_fork创建进程,显然是不行的。因为在用户空间,任何一行代码都是在明确的用户进程上下文中的。

  直接调用do_fork,肯定是在当前用户进程基础上创建新的进程,不会有任何异议。而对内核来讲,如果当前的上下文是中断处理程序,则上下文是不明确的,

  有可能是从某个内核线程切换过来的,也有可能是从某个用户进程切换过来的。所以,通过上述指定父进程,遍历链表创建子进程的方式,明确了内核进程的上下文空间。

6

  对于内核初始化的时间要求

  内核提供了initcall_debug参数,用于辅助调试启动时间

  另外,内核需要打开CONFIG_PRINTK_TIME

  scripts脚本目录下有一个python文件bootgraph.pl,可以处理启动输出的日志信息,然后绘制svg图,这样可以直观的看到内核启动过程的时间是如何消耗的。

  命令使用方式为 dmesg | perl scripts/bootgraph.pl > output.svg

7

  补充关闭过程

  restart软复位,调用到了machine绑定的restart函数,这是一个平台相关接口,在海思上,实现为写特定控制寄存器

  应用层执行reboot程序时,最终会通过系统调用执行到kernel_restart函数,但是该函数的使用似乎有一些条件。

  根据内核的注释来看,在中断上下文中调用该接口并不安全,实际测试,似乎也是。

  在rcu检测到stall后dump调用栈的接口中,执行该重启函数,并不能保证每次都会重启,应该来讲,大部分情况不会重启。

  另外,在上述接口中,单独进行海思平台的软复位,实际也没有重启。包括组合使用smp_send_stop、关闭中断、延时等

  最终都似乎是cpu关闭了,但是无法重新启动。

  对于kernel_restart,rcu检测到stall是在时钟中断上下文中,因此不符合内核对该接口调用的要求,无法完成重启似乎也能说过去,也许一些操作会出现问题。

  但是,直接暴力写复位寄存器,不能实现重启,原因就不得而知。

  解决方案是将kernel_restart放到工作队列中,参考ctrl_alt_del快捷键的处理。实际测试可以正常重启。

  另外,将上述写寄存器的方法放到工作队列中,让其在线程上下文中执行,测试发现,也不能重启。说明当前的CPU运行环境不满足复位条件。

  但是海思文档中没有说明复位需要什么条件,其中的原因是否跟多核有关?

  在应用环境中,单独使用devmem写寄存器命令测试,发现效果跟内核中使用命令是一样的,该问题暂放!

  halt,各个CPU核心处理后,关闭中断,然后while 1循环。

  poweroff关机,待分析。

相关文章:

Linux系统之Uboot、Kernel、Busybox思考之一

目录 一 基础环境 1 硬件基础环境 2 软件基础环境 2.1 Uboot 2.2 内核 2.3 文件系统 二 启动过程 1 2 3 4 5 6 7 一 基础环境 1 硬件基础环境 CPU、内存和FLASH为基础环境,有了这三样,程序就可以跑起来。在此基础上补充各种外设&#xff…...

CCNP350-401学习笔记(401-450题)

401、What is the function of vBond in a Cisco SDWAN deployment? A. initiating connections with SD-WAN routers automatically B. pushing of configuration toward SD-WAN routersC. onboarding of SDWAN routers into the SD-WAN overlay D. gathering telemetry dat…...

一文带你看透前端世界里的日期时间,对就是Date

很高兴我们能够通过不同空间,不同时间,通过这篇博客相识,那一定是一种缘分,一种你和狗哥的缘分。今天我希望通过这篇博客对我所熟知的前端世界里的日期时间做一个汇总,不止是代码上的汇总哦! 目录 一、时区…...

易基因|RRBS单碱基绘制580种动物的基因组规模DNA甲基化谱:Nature子刊

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。2023年01月16日,奥地利科学院分子医学研究中心(CeMM)研究团队在《Nat Commun》杂志发表了题为“Comparative analysis of genome-scale, base-resolution DNA methylation prof…...

面试官:能用JavaScript手写一个bind函数吗

经常会看到网上各种手写bind的教程,下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话,那么可以先看看上面两篇文章。 手写bind vs 原生bind 我们先使用一个典型的手写bind的例子,代码如下&a…...

美国拟发布纽扣电池或硬币电池安全标准和通知要求ANSI C18. 3M

2023年2月10日,美国向WTO提交G/TBT/N/USA/1964号通报,拟发布纽扣电池或硬币电池以及含有此类电池的消费品的安全标准和通知要求,征求意见截止日期为2023年3月13日,拟通过日期和生效日期待定。联[1]系 拟定规则通知根据H.R.5313瑞…...

双因素方差分析

一、案例与数据 一家大型商业银行在多地区设有分行,其业务主要是进行基础设施建设,国家重点项目建设,固定资产投资等项目的贷款。近年来,该银行的贷款额平稳增长,但不良贷款额也有较大比例的提高,这给银行…...

[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

「TCG 规范解读」第8章 TPM工作组 TPM 1.2中 SHA1的使用

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…...

熵权法计算权重

文章目录1. 多属性决策问题2. 熵(entropy)3. 信息熵4. 熵权法5. 熵权法的实现基于信息论的熵值法是根据各指标所含信息有序程度的差异性来确定指标权重的客观赋权方法,仅依赖于数据本身的离散程度。熵用于度量不确定性,指标的离散…...

redis实现用户签到,统计活跃用户,用户在线状态,用户留存率

开发的过程中,可能会遇到用户签到、统计当天的活跃用户、以及每个用户的在线状态,用户留存率的开发需求,可能会用传统的方法,根据相应的需求设计数据库表等,但这样耗费的存储空间大,以及性能方面也不会太好…...

MySQL中有多少种索引?索引的底层实现原理

索引存储在内存中,为服务器存储引擎为了快速找到记录的一种数据结构。索引的主要作用是加快数据查找速度,提高数据库的性能。索引的分类(1) 普通索引:最基本的索引,它没有任何限制。(2) 唯一索引:与普通索引类似&#…...

LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解

LeetCode经典算法题:二叉树遍历(递归遍历迭代遍历层序遍历)以及线索二叉树java详解 文章目录二叉树遍历题目描述解题思路与代码递归遍历迭代遍历层序遍历线索二叉树:二叉树遍历 题目描述 从根节点往下查找,先找左子树…...

【Java闭关修炼】MyBatis-接口代理的方式实现Dao层

【Java闭关修炼】MyBatis-接口代理的方式实现Dao层实现规则代码实现代理对象分析接口代理方式小结实现规则 映射配置文件中的名称空间必须和Dao层接口的全类名相同映射配置文件的增删改查标签的id属性必须和Dao层接口方法的参数相同映射配置文件中的增删改查标签的parameterTyp…...

2022年网络安全政策态势分析与2023年立法趋势

近日,公安部第三研究所网络安全法律研究中心与 360 集团法务中心联合共同发布了《全球网络安全政策法律发展年度报告(2022)》。《报告》概览2022年全球网络安全形势与政策法律态势,并对2023年及后续短期内网络安全政策、立法趋势进…...

使用vmware制作云平台redhat7.9镜像模板

一、概述 1.1 redhat7.9 定制镜像上传到云平台。 这个制作镜像得方式适用于多种iso 镜像。 将iso 镜像通过vmware 创建出一台虚机,对虚机做一些基础配置。在虚机上安装kvm 虚拟化得工具, 将iso 镜像在导入虚机种通过kvm创建一下虚机, 虚机创…...

OpenCV基础(28)使用OpenCV进行摄像机标定Python和C++

摄像头是机器人、监控、太空探索、社交媒体、工业自动化甚至娱乐业等多个领域不可或缺的一部分。 对于许多应用,必须了解相机的参数才能有效地将其用作视觉传感器。 在这篇文章中,您将了解相机校准所涉及的步骤及其意义。 我们还共享 C 和 Python 代码以…...

APB总线详解及手撕代码

本文的参考资料为官方文档AMBA™3 APB Protocol specification文档下载地址: https://pan.baidu.com/s/1Vsj4RdyCLan6jE-quAsEuw?pwdw5bi 提取码:w5bi APB端口介绍介绍总线具体握手规则之前,需要先熟悉一下APB总线端口,APB的端口…...

【Linux/Windows】源文件乱码问题解决方法总结

🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd🌐系列专栏:Linux技术&…...

Python 四大主流 Web 编程框架

目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实。但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架:Django、Tornado、Flask、Twisted。 …...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、👨‍🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨‍&#x1f…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

命令行关闭Windows防火墙

命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)​方法二:CMD命令…...