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

🌈 个人主页: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 <iostream>
#include <signal.h>
#include <unistd.h>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 <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>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);}}// fatherwhile (true){DoOtherThing();sleep(1);}return 0;
}

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

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

八:🔥 共勉

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

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

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

相关文章

鸿蒙的进击之路

1. 题记&#xff1a; 为什么要写鸿蒙&#xff0c;因为她是华为的&#xff0c;为什么是华为就要写&#xff0c;因为华为背负了国人太多太多的包袱&#xff0c;或点赞或抨击。 我是强烈支持华为的&#xff0c;但我会客观公正地去评价华为的产品&#xff0c;就比如这篇博文&#…

Swagger的介绍和使用方式+常用注解

介绍: 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面.简单来说就是我们只需要知道使用Swagger可以帮助我们后端生成接口文档 Swagger官网:https://swagger.io/ 因为单独使用Swagger会有些…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码,AVPacket 重要函数,结构体成员学习

前提&#xff1a; 从前面的学习我们知道 AVFrame中是最原始的 视频数据&#xff0c;这一节开始我们需要将这个最原始的视频数据 压缩成 AVPacket数据&#xff0c; 我们前面&#xff0c;将YUV数据或者 RGBA 数据装进入了 AVFrame里面&#xff0c;并且在SDL中显示。 也就是说&…

QinQ VLAN技术

QinQ VLAN技术的主要作用包括扩展VLAN数量、实现私网VLAN透传、提供二层隔离和多租户环境等。以下是对这些作用的详细介绍&#xff1a; 扩展VLAN数量 解决VLAN ID不足问题&#xff1a;QinQ技术通过在原有的802.1Q标签基础上再增加一层802.1Q标签&#xff0c;从而将VLAN数量从40…

【机器学习】24. 聚类-层次式 Hierarchical Clustering

1. 优势和缺点 优点&#xff1a; 无需提前指定集群的数量 通过对树状图进行不同层次的切割&#xff0c;可以得到所需数量的簇。树状图提供了一个有用的可视化-集群过程的可解释的描述树状图可能揭示一个有意义的分类 缺点&#xff1a; 计算复杂度较大, 限制了其在大规模数据…

分析报告、调研报告、工作方案等的提示词

什么是提示词&#xff1f; 提示词的英文是Prompt&#xff0c;是你与人工智能&#xff08;AI&#xff09;进行交流的方式。简单来说&#xff0c;提示词就是你给AI的一段文字或问题&#xff0c;AI根据这段文字或问题来生成回应或完成任务。 举个例子&#xff1a;假设你在使用一…

Sentinel通过限流对微服务进行保护

目录 雪崩问题 解决雪崩问题的方法&#xff1a; 我们使用sentinel组件实现微服务的保护 一&#xff1a;下载sentinel 二.启动sentinel 三.访问&#xff1a;localhost:8080 默认的账号和密码都是sentinel 微服务整合sentinel 一.导入sentinel依赖 二.在application.yml配…

第三十篇——微分(上):如何从宏观变化了解微观趋势?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 微分给我们带来的思维方式的变化&#xff0c;更加符合现在这个时代对于我…

Springboot项目报错记录

SpringBoot测试报错&#xff1a;Unable to find a SpringBootConfiguration, you need to use Context 该测试类所在测试包test下的包名和类路径java下的包名不一致导致的 引发以下报错 java.lang.IllegalStateException: Unable to find a SpringBootConfiguration, you need…

VTK知识学习(3)-显示圆柱

1、添加显示控件 前台界面 <WindowsFormsHost x:Name"windowHost" Grid.Row"1"/> 构造函数中添加。 private RenderWindowControl renderWindowControl new RenderWindowControl();public MainWindow(){InitializeComponent();windowHost.Child …

《FreeRTOS的配置与临界段》

目录 1.FreeRTOS配置的重要性 2.初学者使用FreeRTOSConfig.h 文件 3.“INCLUDE_”开始的宏 4.FreeRTOS 中断配置和临界段 4.1 中断简介 4.2 中断优先级分组定义 4.3优先级设置 4.4 重要的中断屏蔽寄存器 一、PRIMASK 和 FAULTMASK 寄存器 二、BASEPRI 寄存器 4.5 F…

Vue:模板 MVVM

Vue&#xff1a;模板 & MVVM 模板插值语法指令语法 MVVMdefineProperty数据代理 模板 Vue实例绑定一个容器&#xff0c;想要向容器中填入动态的值&#xff0c;就需要使用模板语法。模板语法分为插值语法和指令语法。 插值语法 插值语法很简单&#xff0c;使用{{}}包含一…

极简实现酷炫动效:Flutter隐式动画指南第三篇自定义Flutter隐式动画

目录 前言 一、TweenAnimationBuilder 二、使用TweenAnimationBuilder实现的一些动画效果 1.调整透明度的动画 2.稍微复杂点的组合动画 3.数字跳动的动画效果 前言 上两节博客分别介绍了Flutter中的隐式动画的基础知识以及使用隐式动画实现的一些动画效果。当系统提供的隐…

熵基ZKTeco考勤机门禁如何重置密码(适用于大多数彩屏门禁机)

公司的一台门禁忘记密码了打不开&#xff0c;找了很久终于找到了密码重置的方法。 1、断电拆机(机器底部的螺丝,将机器从墙上拿下来) 2、插电重启&#xff08;或者杵下底部reset小孔&#xff09; 3、机器屏幕显示被拆除&#xff08;或右上角红色小感叹号闪烁&#xff0c;后者启…

​基于学习的地铁客流动态预测智能调度方法

1 文章信息 文章题为“A Learning Based Intelligent Train RegulationMethod With Dynamic Prediction forthe Metro Passenger Flow”&#xff0c;该文于2023年发表至“IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS”。文章的核心观点是提出了一种基于学习的智…

RNA-seq 差异分析的点点滴滴(1)

引言 本系列[1])将开展全新的转录组分析专栏&#xff0c;主要针对使用DESeq2时可能出现的问题和方法进行展开。 为何使用未经标准化的计数数据&#xff1f; DESeq2 工具包在接收输入时&#xff0c;期望得到的是未经处理的原始计数数据&#xff0c;比如从 RNA-seq 或其他高通量测…

Python初始环境搭建和Pycharm的安装

Python和PyCharm安装步骤 刚学习Python编程&#xff0c;按照书上的方法安装了Python和PyCharm&#xff0c;并做练习。但是今天PyCharm软件忽然不能使用了&#xff0c;不知道什么原因。于是&#xff0c;将这两个软件全部卸载&#xff0c;在网上查找软件安装方法&#xff0c;重新…

云上拼团GO指南——腾讯云博客部署案例,双11欢乐GO

知孤云出岫-CSDN博客 目录 腾讯云双11活动介绍 一.双十一活动入口 二.活动亮点 &#xff08;一&#xff09;双十一上云拼团Go (二&#xff09;省钱攻略 &#xff08;三&#xff09;上云&#xff0c;多类型服务器供您选择 三.会员双十一冲榜活动 (一)活动内容 &#x…

[ 常用工具篇 ] 使用 kali 实现 ARP 攻击 -- arpspoof 实战详解(ARP欺骗-断网攻击中间人攻击)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

无人机之飞行管控平台篇

无人机的飞行管控平台是一种基于互联网和物联网技术的智能管理系统&#xff0c;旨在实现对无人机飞行任务的全自动化、全过程化管理。 一、主要功能 飞行计划管理&#xff1a;用户可以通过平台提前设置好无人机的飞行计划&#xff0c;包括起飞时间、航线、飞行高度等信息。平…