【Linux】状态机

2023-05-16

Linux 状态机

首先感谢阅读,作者是在工作中学习与积累,每一个笔记都是心得和积累,希望可以和大家一起交流学习。


学习咱们先定好计划,需要了解的都一样,有:

  1. (状态机)是什么?
  2. (状态机)为什么?
  3. (状态机)有什么?
  4. (状态机)怎么做?(实战)
  5. (状态机)扩展

1. (状态机)是什么?

官方定义:状态机是有限状态自动机的简称,是现实实物运行规则抽象而成的一个数学模型

其实,简而言之,就是设备根据不同的场景下,不同触发的条件,进行不同行为的一个运行机制。

举个栗子:

早晨是晴天,突然下雨了,天气变为雨天,我打开了伞;

下午雨停了,天气变为晴天,我收起了伞。

// 伪代码如下
// 两种状态
#define RAIN 0
#define SUN 1

uint_8 weather = SUN; //早晨是晴天

void main(void)
{
    while (1)
    {
        if (weather == SUN)
        {
            if (event == rain)      // 触发事件下雨了
            {
                open_umbrella();    // 打开伞
                weather = RAIN;     // 对应状态切位雨天
            }
            else
            {
                /* do nothing */    // 雨天状态下雨,伞已经开了,啥都不做
            }
        }
        else if (weather == RAIN)
        {
            if (event == rain_stop)      // 触发事件下雨了
            {
                close_umbrella();    // 打开伞
                weather = SUN;     // 对应状态切位雨天
            }
            else
            {
                /* do nothing */    // 雨天状态下雨,伞已经开了,啥都不做
            }
        }
        else
        {
            printf("天气出错了!");
        }
    }
}

可以看出去,这个状态机包含两种状态的切换(雨天和晴天),包含两种触发事件(下雨和雨停),使用if else或者switch便可以轻松实现,这就是最简单的状态机。


2. (状态机)为什么?

从上一节可以看出,状态机的优点:

具有有限数量的状态,任意时刻都处于有限状态集合中的某一状态。
(有事件(event)发生时,将从当前状态转换到另一个状态,或者仍然保持在当前状态。)
优点:编程快速简单。易于调试,很少的计算开销 ,灵活性

当设备的状态只有两个,触发事件和对应的操作只有两个时if else还绰绰有余。但是当状态不停增加时,触发事件也不停增加时,难道if else一直嵌套吗?

所以有了linux设备相对标准的状态机(至少博主目前的物联网设备跑的都是这个状态机)


3.(状态机)有什么?

也就是状态机的数据构造

3.1 状态(STATE)

首先判断自己项目包含几种运行状态,一定做到全面性覆盖设备的所有状态

此处博主用自己的蓝牙-GPS定位项目(使用LoRa通信)为例

typedef enum
{
    FW_STATE_BEGIN = 0,          // 起始状态
    FW_STATE_INIT,                      // 初始化状态
    FW_STATE_JOIN,                    // Join网络状态
    FW_STATE_WORKING,          // 工作状态
    FW_STATE_POWER_OFF,    // 下电状态
    FW_STATE_RESTRICT,          // 限制状态
    FW_STATE_MAX,                     // 用于STATE合法性判断
} FRAMEWORK_STATE;

为什么要有一个起始状态,状态机初始化也是需要一个默认状态的,就比如1.里的晴天SUN,一定得是设备已经处在一个状态中,才可以开启状态机运行。

3.2 事件(EVENT)

事件的设计,也要遵从全面性,事件可以将3.1的状态衔接起来

typedef enum
{
    EVENT_POWER_ON = 0,                 //开机
    EVENT_LOW_POWER,                     //关机
    EVENT_BUTTON_PUSH,                //短按按键
    EVENT_BUTTON_LONG_PUSH,  //长按按键
    EVENT_RESTRICT,                            //限制
    EVENT_INIT_OK,                               //初始化完成
    EVENT_JOIN_OK,                             //join网络完成
    EVENT_JOIN_FAILED,                     //join网络失败
    EVENT_HB_ACK_OK,                      //心跳应答接收成功,心跳上报成功
    EVENT_HB_ACK_LOST,                 //心跳应答丢失,心跳上报失败
    EVENT_CONNECTION_LOST,      //连接丢失
    EVENT_MAX,                                       //用于EVENT合法性判断
} FRAMEWORK_EVENT;

3.3 行为(ACTION)

当3.1的状态+3.2的事件时,状态机不仅要做到状态的跃迁,还要执行对应的动作,这也是大家设计状态的最初原因,也就是handle啦~

// 这里先空着,下面一起讲

3.4 跃迁(TRANSITION;)

可以说这是状态机的主体,上面是3.1,3.2和3.3还不能只是原料,这个模块三种原料组合起来

先看下状态机的结构体构成

typedef void (*FRAMEWORK_ACTION)(void);  //预留一个动作

typedef struct
{
    FRAMEWORK_STATE     current;  //当前状态
    FRAMEWORK_EVENT    event;      //触发事件
    FRAMEWORK_STATE     next;         //要切换的状态
    FRAMEWORK_ACTION  action;     //对应的动作
} FRAMEWORK_TRANSITION;

这样可以说,一条状态机器(运行规则)就构造完成了~

3.5 状态机(FSM)

一个状态机包含哪些东西

  1. 状态机的运行规则(上一个刚说)
  2. 状态机当前状态 (对应触发事件,哪些状态可以切入)
  3. 状态机的条数(遍历时控制遍历次数)
typedef struct
{
    FRAMEWORK_STATE         state;
    FRAMEWORK_TRANSITION    *transitions;
    uint32_t                    transition_count;
} FRAMEWORK_FSM;

4. (状态机)怎么做?(实战)

4.1 构造完整的跃迁

根据3.4的单条跃迁,我们设置一个完整的运行跃迁

static FRAMEWORK_TRANSITION m_fw_transition[] =
{
    /* BEGIN */
    {FW_STATE_BEGIN, EVENT_POWER_ON,  FW_STATE_INIT,      proc_init},
    {FW_STATE_BEGIN, EVENT_LOW_POWER, FW_STATE_POWER_OFF, proc_power_off},

    /* INIT */
    {FW_STATE_INIT, EVENT_RESTRICT,         FW_STATE_RESTRICT,  proc_restrict},
    {FW_STATE_INIT, EVENT_INIT_OK,          FW_STATE_JOIN,      proc_join},
    {FW_STATE_INIT, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* JOIN */
    {FW_STATE_JOIN, EVENT_JOIN_FAILED,      FW_STATE_JOIN,      proc_join_retry},
    {FW_STATE_JOIN, EVENT_JOIN_OK,          FW_STATE_WORKING,   proc_working},

    {FW_STATE_JOIN, EVENT_LOW_POWER,        FW_STATE_POWER_OFF, proc_power_off},
    {FW_STATE_JOIN, EVENT_BUTTON_PUSH,      FW_STATE_JOIN,      proc_indicate_join},
    {FW_STATE_JOIN, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* WORKING */
    {FW_STATE_WORKING, EVENT_CONNECTION_LOST,  FW_STATE_JOIN,      proc_join_retry},
    {FW_STATE_WORKING, EVENT_HB_ACK_OK,        FW_STATE_WORKING,   heartbeat_ack_ok},
    {FW_STATE_WORKING, EVENT_HB_ACK_LOST,      FW_STATE_WORKING,   heartbeat_ack_lost},

    {FW_STATE_WORKING, EVENT_LOW_POWER,        FW_STATE_POWER_OFF, proc_power_off},
    {FW_STATE_WORKING, EVENT_BUTTON_PUSH,      FW_STATE_WORKING,   proc_indicate_join},
    {FW_STATE_WORKING, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* POWER_OFF */
    {FW_STATE_POWER_OFF, EVENT_BUTTON_LONG_PUSH, FW_STATE_BEGIN, proc_power_on},

    /* RESTRICT */
    {FW_STATE_RESTRICT, EVENT_BUTTON_PUSH, FW_STATE_RESTRICT, proc_indicate_restrict},
    {FW_STATE_RESTRICT, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},
};

4.2 初始化函数

设置起始状态,运行哪个状态,状态机有多少条

//顺便在先创建一个状态机
static LST_FRAMEWORK_FSM m_fw_fsm;

void lst_framework_start(void)
{
    m_fw_fsm.state = LST_FW_STATE_BEGIN;
    m_fw_fsm.transitions = m_fw_transition;
    m_fw_fsm.transition_count = ARRAY_SIZE(m_fw_transition);
}

4.3 寻找状态机函数

static FRAMEWORK_TRANSITION *fw_find_transition(FRAMEWORK_FSM *fsm, FRAMEWORK_EVENT event)
{
    FRAMEWORK_TRANSITION *transform = NULL;
    uint32_t i;

    for (i = 0; i < fsm->transition_count; i++)
    {
        if ((fsm->transitions[i].current == fsm->state)
                && (fsm->transitions[i].event == event))
        {
            transform = &fsm->transitions[i];
        }
    }

    return transform;
}

4.4 事件发送函数

调用4.3状态机寻找函数

static void framework_event_send(FRAMEWORK_EVENT event)
{
    FRAMEWORK_TRANSITION *transform;

    transform = fw_find_transition(&m_fw_fsm, event);
    if (transform != NULL)
    {
        transform->action();
        m_fw_fsm.state = transform->next;
    }
}

只需要在业务代码判断条件适合时发送触发事件即可。

最后会贴上博主项目中的状态机源码


5. 扩展

当多层状态叠加需要考虑时(此处借用博主的另一个项目,汽车流媒体后视镜),如:


├── 关机                             
├── 开机
│   ├── 前进
│   │  ├──  左转
│   │  └──  右转
│   ├── 后退
│   │  ├──  左转
│   │  └──  右转
│   ├── 驻车
│   └── 空挡
└── 待机                

此时可以设计多层状态机

对应修改3.1

typedef struct
{
	/* data */
	SYSTEM_STATE 	system_state;
	MODE_STATE 	 	 mode_state;
	STEER_STATE     steer_state;
} FRAMEWORK_STATE;

单条跃迁不修改,因为上面状态已改为三层状态机

typedef struct
{
	FRAMEWORK_STATE current;  //要修改这个,见上一个代码块
	FRAMEWORK_EVENT event;
	FRAMEWORK_STATE next;
	FRAMEWORK_ACTION action;
} FRAMEWORK_TRANSITION;

对应修改4.2和4.3函数即可


源码:

已删除业务代码,只剩下框架,感谢理解~~

#include "nordic_common.h"
#include "nrf_log.h"

typedef enum
{
    FW_STATE_BEGIN = 0, // 起始状态
    FW_STATE_INIT,      // 初始化状态
    FW_STATE_JOIN,      // Join网络状态
    FW_STATE_WORKING,   // 工作状态
    FW_STATE_POWER_OFF, // 下电状态
    FW_STATE_RESTRICT,  // 限制状态
    FW_STATE_MAX,       // 用于STATE合法性判断
} FRAMEWORK_STATE;

typedef void (*FRAMEWORK_ACTION)(void);

typedef struct
{
    FRAMEWORK_STATE     current;
    FRAMEWORK_EVENT     event;
    FRAMEWORK_STATE     next;
    FRAMEWORK_ACTION    action;
} FRAMEWORK_TRANSITION;

typedef struct
{
    FRAMEWORK_STATE         state;
    FRAMEWORK_TRANSITION    *transitions;
    uint32_t                    transition_count;
} FRAMEWORK_FSM;

static void proc_init(void)
{

    return;
}
APP_TIMER_DEF(m_join_retry_timer);

static void join_retry_expire(void *p_context)
{
    return;
}

static void proc_join_retry(void)
{
    return;
}

static void proc_join(void)
{
    return;
}

static void proc_working(void)
{
    return;
}

static void proc_power_off(void)
{
    return;
}

static void proc_restrict(void)
{
    return;
}

static void proc_power_on(void)
{
    return;
}

static void proc_indicate_join(void)
{
    return;
}

static void proc_indicate_restrict(void)
{
    return;
}

static FRAMEWORK_FSM m_fw_fsm;

static FRAMEWORK_TRANSITION m_fw_transition[] =
{
    /* BEGIN */
    {FW_STATE_BEGIN, EVENT_POWER_ON,  FW_STATE_INIT,      proc_init},
    {FW_STATE_BEGIN, EVENT_LOW_POWER, FW_STATE_POWER_OFF, proc_power_off},

    /* INIT */
    {FW_STATE_INIT, EVENT_RESTRICT,         FW_STATE_RESTRICT,  proc_restrict},
    {FW_STATE_INIT, EVENT_INIT_OK,          FW_STATE_JOIN,      proc_join},
    {FW_STATE_INIT, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* JOIN */
    {FW_STATE_JOIN, EVENT_JOIN_FAILED,      FW_STATE_JOIN,      proc_join_retry},
    {FW_STATE_JOIN, EVENT_JOIN_OK,          FW_STATE_WORKING,   proc_working},

    {FW_STATE_JOIN, EVENT_LOW_POWER,        FW_STATE_POWER_OFF, proc_power_off},
    {FW_STATE_JOIN, EVENT_BUTTON_PUSH,      FW_STATE_JOIN,      proc_indicate_join},
    {FW_STATE_JOIN, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* WORKING */
    {FW_STATE_WORKING, EVENT_CONNECTION_LOST,  FW_STATE_JOIN,      proc_join_retry},
    {FW_STATE_WORKING, EVENT_HB_ACK_OK,        FW_STATE_WORKING,   heartbeat_ack_ok},
    {FW_STATE_WORKING, EVENT_HB_ACK_LOST,      FW_STATE_WORKING,   heartbeat_ack_lost},

    {FW_STATE_WORKING, EVENT_LOW_POWER,        FW_STATE_POWER_OFF, proc_power_off},
    {FW_STATE_WORKING, EVENT_BUTTON_PUSH,      FW_STATE_WORKING,   proc_indicate_join},
    {FW_STATE_WORKING, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},

    /* POWER_OFF */
    {FW_STATE_POWER_OFF, EVENT_BUTTON_LONG_PUSH, FW_STATE_BEGIN, proc_power_on},

    /* RESTRICT */
    {FW_STATE_RESTRICT, EVENT_BUTTON_PUSH, FW_STATE_RESTRICT, proc_indicate_restrict},
    {FW_STATE_RESTRICT, EVENT_BUTTON_LONG_PUSH, FW_STATE_POWER_OFF, proc_power_off},
};

static FRAMEWORK_TRANSITION *fw_find_transition(FRAMEWORK_FSM *fsm, FRAMEWORK_EVENT event)
{
    FRAMEWORK_TRANSITION *transform = NULL;
    uint32_t i;

    for (i = 0; i < fsm->transition_count; i++)
    {
        if ((fsm->transitions[i].current == fsm->state)
                && (fsm->transitions[i].event == event))
        {
            transform = &fsm->transitions[i];
        }
    }

    return transform;
}

static void fw_event_handler(FRAMEWORK_EVENT event)
{
    FRAMEWORK_TRANSITION *transform;

    transform = fw_find_transition(&m_fw_fsm, *event);
    if (transform != NULL)
    {
        transform->action();
        m_fw_fsm.state = transform->next;
    }
}

void framework_start(void)
{
    m_fw_fsm.state = FW_STATE_BEGIN;
    m_fw_fsm.transitions = m_fw_transition;
    m_fw_fsm.transition_count = ARRAY_SIZE(m_fw_transition);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux】状态机 的相关文章

  • [week2]模拟OJ成绩排名系统(简易版)

    文章目录 题意InputOutput输入样例输出样例 分析总结代码 题意 题面宛如小作文233 程序设计思维作业和实验使用的实时评测系统 xff0c 具有及时获得成绩排名的特点 xff0c 那它的功能是怎么实现的呢 xff1f 我们千辛万苦
  • [week3]区间选点问题——贪心算法

    目录 题意InputOutput输入样例输出样例 分析总结代码 题意 数轴上有 n 个闭区间 a i b i 取尽量少的点 xff0c 使得每个区间内都至少有一个点 xff08 不同区间内含的点可以是同一个 xff09 Input 第一行1
  • [week3]区间覆盖问题——贪心算法

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 数轴上有 n 1 lt 61 n lt 61 25000 个闭区间 ai bi xff0c 选择尽量少的区间覆盖一条指定线段 1 t xff08 1 lt 61 t
  • [csp模拟1]咕咕东的奇遇——(一)

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 咕咕东是个贪玩的孩子 xff0c 有一天 xff0c 他从上古遗迹中得到了一个神奇的圆环 这个圆环由字母表组成首尾相接的环 xff0c 环上有一个指针 xff0c 最
  • Linux挂载镜像的一些命令

    Linux挂载镜像的一些命令 在Linux中 xff0c 可以用losetup命令来设置无分区空白镜像到loop设备上 xff0c 用kpartx 来kpartx映射分区的镜像到loop设备上 之后通过mount命令将loop设备与系统文件
  • [week5]平衡字符串——尺取法

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 一个长度为 n 的字符串 s xff0c 其中仅包含 Q W E R 四种字符 如果四种字符在字符串中出现次数均为 n 4 xff0c 则其为一个平衡字符串 现可以将
  • [csp模拟2]T4——咕咕东的奇妙序列

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 咕咕东 正在上可怕的复变函数 xff0c 但对于稳拿A Plus的 咕咕东 来说 xff0c 她早已不再听课 xff0c 此时她在睡梦中 突然想到了一个奇怪的无限
  • [week9]签到题(长凳)——贪心算法

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 SDUQD 旁边的滨海公园有 x 条长凳 第 i 个长凳上坐着 a i 个人 这时候又有 y 个人将来到公园 xff0c 他们将选择坐在某些公园中的长凳上 xff
  • [week14] Q老师与十字叉

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 Q老师 得到一张 n 行 m 列的网格图 xff0c 上面每一个格子要么是白色的要么是黑色的 Q老师认为失去了 十字叉 的网格图莫得灵魂 一个十字叉可以用一个数对
  • [week15] ZJM 与霍格沃兹 —— 字符串哈希

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 为了准备霍格沃兹的期末考试 xff0c 决心背魔咒词典 xff0c 一举拿下咒语翻译题 题库格式 xff1a 魔咒 对应功能 背完题库后 xff0c ZJ
  • [week14] D - Q老师染砖(选做) —— 矩阵快速幂优化DP

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 衣食无忧的 Q老师 有一天突发奇想 xff0c 想要去感受一下劳动人民的艰苦生活 具体工作是这样的 xff0c 有 N 块砖排成一排染色 xff0c 每一块砖需要
  • [week14] E - Q老师度假(选做)—— 矩阵快速幂优化DP(拓展)

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 忙碌了一个学期的 Q老师 决定奖励自己 N 天假期 假期中不同的穿衣方式会有不同的快乐值 已知 Q老师 一共有 M 件衬衫 xff0c 且如果昨天穿的是衬衫 A
  • [week15] B - ZJM与生日礼物(选做)—— 字典树

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 收到了 Q老师 送来的生日礼物 xff0c 但是被 Q老师 加密了 只有 ZJM 能够回答对 Q老师 的问题 xff0c Q老师 才会把密码告诉 ZJM
  • [week15] C - ZJM与纸条(选做)—— KMP算法

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 的女朋友是一个书法家 xff0c 喜欢写一些好看的英文书法 有一天 ZJM 拿到了她写的纸条 xff0c 纸条上的字暗示了 ZJM 的女朋友 想给 ZJM
  • 51按键外部中断控制流水灯

    实验二 外部按键输入 一 实验目的 1 了解单片机检测口方法 2 了解单片机外部中断原理 3 了解按键输入原理 二 实验内容 1 完成按键扫描控制流水灯 2 完成按键外部中断控制流水灯 三 实验原理 四 实验电路与程序 1 软件实验一 xf
  • 树莓派4B构建debian镜像UEFI启动

    树莓派4B构建debian镜像UEFI启动 前言 今天按照大佬的博客树莓派俱乐部官方 Debian 系统镜像 支持UEFI跑了遍 完整的UEFI镜像构建过程 包括镜像分区 挂载 xff0c 根文件系统的制作 xff0c 内核的移植 xff0
  • Linux修改主机名问题

    记一次修改主机名不成功原因 场景 虽然使用hostname命令可以修改主机名 xff0c 但如果重启主机之后主机名还会变为之前的 xff0c 所以需要把修改的主机名称写到配置文件中 假设修改后的主机名为 new hostname 1 修改配
  • mybatisPlus分页插件报错,sql后面拼接多了一个limit。

    原本 用的mybatisPlus版本为3 1 0 xff0c 后来升级到3 4 2了 xff0c 使用分页的时候报错 解决 xff1a mybatisPlus 3 1 0 所用到的分页插件为 而mybatisPlus 3 4 2版本pagi
  • Deep Knowledge Tracing (深度知识追踪)

    boss又让我看这块的内容了 xff0c 刚开学 xff0c 还不太适应实验室的学习生活 xff0c 假期闲散惯了操 目录 1 概述2 表示3 1 DKT的优势3 2 DKT的不足4 模型5 序列的输入和输出输入输出 6 优化及应用7 三个
  • C程序代码

    一 C语言概述有算法 1 输出一行信息 span class token macro property span class token directive hash span span class token directive keyw

随机推荐

  • 【C语言-10】.求10 个整数中最大值。 (数组定义法和函数调用法)

    数组定义法 首先定义一个一维数组存放输入的数字 xff0c 然后将键盘输入的数字依次存入一维数组 xff1b 假定数组中某一元素为最大值 xff0c 将其与其他元素逐一比较 xff0c 得到最大的数为max值 xff1b 最后得到的max为
  • 【工程实践】解决 nvcc: command not found

    1 nvcc nvcc 是The main wrapper for the NVIDIA CUDA Compiler suite Used to compile and link both host and gpu code NVIDIA
  • hdu 5119(dp题)

    题目链接 xff1a http acm hdu edu cn showproblem php pid 61 5119 题目 xff1a Matt has N friends They are playing a game together
  • word(doc/docx)转markdown:使用Typora的插件

    打开你的Typora xff0c 选择文件 gt 导入 第一次导入会让你下载 pandoc 插件 下载链接如下 xff1a https github com jgm pandoc releases download 2 14 1 pando
  • 案例描述:update中,MySQL inner join 和 left join的区别,小结果集驱动大结果集

    场景描述 以一个场景为例 xff1a 单据A xff1a 下游子表 xff08 数据量级小 xff09 单据B xff1a 下游主表 xff08 数据量级小 xff09 单据C xff1a 中游子表 xff08 数据量级小 xff09 单据
  • Hadoop生态圈(一)- Hadoop详解

    目录 前言1 Hadoop概述1 1 Hadoop是什么1 2 Hadoop发展简史1 2 Hadoop三大发行版本1 3 Hadoop优势1 4 Hadoop的组成1 4 1 Hadoop1 x 2 x 3 x区别1 4 2 HDFS架构
  • arduino硬件总结

    文章目录 arduino硬件总结串口通讯I2CSPI中断函数基本了解实现测速 ADC读取光敏传感器的值 pwm舵机控制 arduino硬件总结 arduino 支持中断 xff0c ADC PWM xff0c I2C xff0c spi x
  • 文件上传 - Apache SSI远程命令执行

    文章目录 一 漏洞原理二 漏洞场景 挖掘思路三 触发条件四 漏洞复现4 1 启动环境4 2 访问环境4 3 复现过程 五 防御措施 一 漏洞原理 在测试任意文件上传漏洞的时候 xff0c 目标服务端可能不允许上传php jsp asp后缀的
  • Linux:chmod -R 777 *含义

    Linux xff1a chmod R 777 首先 xff0c chmod命令是linux上用于改变权限的命令 xff0c R 是递归遍历子目录 xff0c 因为你要操作的文件使用的 通配符 777 xff0c 第一个7代表文件所属者的权
  • STM32HAL库学习笔记七——I2C通信

    HAL库快速部署I2C 本文主要介绍如何使用STM32CubeMX快速部署I2C通信 xff0c 并与EEPROM进行数据收发 文章目录 HAL库快速部署I2CI2C简介EEPROM简介HAL库部署IIC通信实现多字节写入一 CubeMX配
  • python报错Statements must be separated by newlines or semicolons解决方法

    今天做练习时遇到这样的报错 xff1a Statements must be separated by newlines or semicolons 翻译一下就是 xff1a 语句必须用换行符或分号分隔 首先按报错提示 xff0c 我把cl
  • python自然语言处理之spacy详解

    spaCy简介 spaCy号称工业级Python自然语言处理 xff08 NLP xff09 软件包 xff0c 可以对自然语言文本做词性分析 命名实体识别 依赖关系刻画 xff0c 以及词嵌入向量的计算和可视化等 spaCy模块有4个非常
  • anaconda创建env报错 ResolvePackageNotFound

    具体错误 如图 xff1a 按照其他博主 xff08 方法详情 xff09 提供的方法操作了还是有部分报错 xff1a 解决策略 继续上面解决剩下的部分报错 xff0c 打开 yaml文件 xff0c 记事本打开就行 将报错列出的几个包移到
  • LDA主题建模过程及参数详解

    平台及工具 语言 xff1a python 平台 xff1a anaconda 43 jupyter notebook 语料库 xff1a 近三百篇英文文献的摘要 主要代码 首先 xff0c pandas处理csv数据 span class
  • 已经成功安装了但是jupyter notebook仍然找不到模块

    问题描述 工具 语言 jupyter notebook 43 anaconda python 有时会遇到这样的情况 xff0c 命名已经install了模块 xff0c notebook还是报找不到模块错误 再装已经提示satisfied
  • pyecharts 地图绘制

    环境描述 win11 jupyter notebook 目标效果 世界地图 43 按数据进行分级着色 xff1b 最终效果图如下 xff1a pyecharts 绘制地图时注意点 可以实现目标地图绘制效果的python库很多 xff0c 这
  • 指定wb用户在指定日期范围内的wb内容抓取

    一 操作步骤 只记录过程 xff0c 不讲述原理 1 获取用户ID和cookie 用户ID在进入个人主页时导航栏中就会有显示 xff0c 例如下面这样 xff1a cookie获取 xff08 有的代码无需cookie也能运行 xff09
  • 中介变量、调节变量与协变量

    在平时看论文过程中偶会接触到这几个概念 xff0c 然而都没想过弄明白 xff0c 每次总觉得只要看明白个大概反正自己又不用这种方法 作为科研人 xff0c 还是应该保持谦逊 xff0c 保持学习 一 中介变量 1 概念 中介变量 xff0
  • linux环境搭建

    文章目录 linux环境搭建基础工具环境docker镜像docker 的基本操作git amp amp sshbash脚本 python 环境 linux环境搭建 基础工具环境 docker镜像 Docker CE 镜像源站 docker如
  • 【Linux】状态机

    Linux 状态机 首先感谢阅读 xff0c 作者是在工作中学习与积累 xff0c 每一个笔记都是心得和积累 xff0c 希望可以和大家一起交流学习 学习咱们先定好计划 xff0c 需要了解的都一样 xff0c 有 xff1a xff08