Linux第71步_将linux中的多个文件编译成一个驱动模块

news2024/10/7 2:27:45

学习目的:采用旧字符设备测试linux系统点灯,进一步熟悉其设计原理。采用多文件参与编译,深度学习编写Makefile,有利于实现驱动模块化设计。

1、创建MyOldLED目录

输入“cd /home/zgq/linux/Linux_Drivers/回车

切换到“/home/zgq/linux/Linux_Drivers/”目录

输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/”目录的文件和文件夹

输入“mkdir MyOldLED回车”,创建MyOldLED目录

切换到“/home/zgq/linux/Linux_Drivers/MyOldLED/”目录

输入“ls回车”查看“/home/zgq/linux/Linux_Drivers”目录的文件和文件夹

2、新建LEDInterface.c

打开虚拟机上“VSCode”,点击“文件”,点击“打开文件夹”,点击“zgq”,点击“linux”,点击“Linux_Drivers”,点击“MyOldLED”。点击“文件”,点击“新建文件”,点击“文件”,点击“另存为”。然后在“名称”右边的文本框中输入“LEDInterface.c”,点击“保存

LEDInterface.c文件内容如下:

#include "LED.h"

#include <linux/types.h>

/*

数据类型重命名

使能bool,u8,u16,u32,u64, uint8_t, uint16_t, uint32_t, uint64_t

使能s8,s16,s32,s64,int8_t,int16_t,int32_t,int64_t

*/

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/ide.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/string.h>

#include <linux/errno.h>

#include <linux/gpio.h>

#define led_MAJOR   200

/*

定义主设备号

静态分配设备号:在串口输入“cat/proc/devices”查询当前已用的主设备号

然后使用一个“没有被使用的设备号”作为该设备的的主设备号

*/

#define led_NAME   "ledName"  //定义设备的名字

/* 打开设备 */

static int led_open(struct inode *inode, struct file *filp)

{

  int ret = 0;

  //printk("led_open!\r\n");

  return ret;

}

/* 向设备写数据,将数据块首地址为buf的数据,长度为cnt个字节,发送给用户 */

//file结构指针变量flip表示要打开的设备文件

//buf表示用户数据块的首地址

//cnt表示用户数据的长度,单位为字节

//loff_t结构指针变量offt表示“相对于文件首地址的偏移”

static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)

{

  int ret = 0;

unsigned char databuf[1];

unsigned char ledstat;

ret = copy_from_user(databuf, buf, cnt);

if(ret <0){

printk("kernel write failed!\r\n");

ret = -EFAULT;

}

ledstat = databuf[0];/*获取到应用传递进来的开关灯状态*/

led_switch(ledstat);/*执行开灯或执行关灯*/

  return ret;

}

/* 关闭/释放设备 */

static int led_release(struct inode *inode, struct file *filp)

{

  int ret=0;

printk("led_release!\r\n");

  return ret;

}

/*声明file_operations结构变量MyCharDevice_fops*/

/*它是指向设备的操作函数集合变量*/

const struct file_operations led_fops = {

  .owner = THIS_MODULE,

  .open = led_open,

  .write = led_write,

  .release = led_release,

};

/*驱动模块的入口函数 */

static int  __init led_init(void)

{

  int ret=0;

/* 1、寄存器地址映射 */

  led_ioremap();//寄存器地址映射

  led_Pin_Init();//LED灯引脚初始化

  printk("led_init!\r\n");

  ret = register_chrdev(led_MAJOR, led_NAME, &led_fops);

  //注册字符设备

  //led_MAJOR为主设备号,采用宏led_NAME定义设备名字

  //led_fops是设备的操作函数集合,它是file_operations结构变量

  if (ret < 0)

  {

printk("CharDeviceDriver register failed!!!\r\n");

goto faile_register;

  }

  return 0;

faile_register:

  return -EIO;

}

/*驱动模块的出口函数 */

static void __exit led_exit(void)

{

/* 1、取消寄存器地址映射 */

  led_iounmap();

  printk("led_exit!\r\n");

  unregister_chrdev(led_MAJOR, led_NAME);

  //注销字符设备

  //led_MAJOR为主设备号,采用宏led_NAME定义设备名字

}

module_init(led_init);

//加载“驱动模块”:指定led_init()为驱动入口函数

module_exit(led_exit);

//卸载“驱动模块”:指定led_exit()为驱动出口函数

MODULE_AUTHOR("Zhanggong");//添加作者名字

MODULE_LICENSE("GPL");//LICENSE采用“GPL协议”

MODULE_INFO(intree,"Y");

//去除显示“loading out-of-tree module taints kernel.”

3、新建LED.c

LED.c文件内容如下:

#include "LED.h"

#include <linux/module.h>

/* 映射后的寄存器虚拟地址指针 */

static void __iomem *MPU_AHB4_PERIPH_RCC_PI;

/*RCC_MP_AHB4ENSETR寄存器*/

static void __iomem *GPIOI_MODER_PI; /*GPIOx_MODER寄存器,x=A to K, Z*/

static void __iomem *GPIOI_OTYPER_PI;/*GPIOx_OTYPER,x=A to K,Z*/

static void __iomem *GPIOI_OSPEEDR_PI;/*GPIOx_OSPEEDR,x=A to K, Z*/

static void __iomem *GPIOI_PUPDR_PI; /*GPIOx_PUPDR,x=A to K, Z*/

static void __iomem *GPIOI_BSRR_PI;/*GPIOx_BSRR,x=A to K, Z*/

void led_ioremap(void);

void led_iounmap(void);

void led_Pin_Init(void);

void led_switch(u8 sta);

/* 寄存器地址映射 */

void led_ioremap(void)

{

   MPU_AHB4_PERIPH_RCC_PI = ioremap(RCC_MP_AHB4ENSETR, 4);

GPIOI_MODER_PI = ioremap(GPIOI_MODER, 4);

   GPIOI_OTYPER_PI = ioremap(GPIOI_OTYPER, 4);

GPIOI_OSPEEDR_PI = ioremap(GPIOI_OSPEEDR, 4);

GPIOI_PUPDR_PI = ioremap(GPIOI_PUPDR, 4);

GPIOI_BSRR_PI = ioremap(GPIOI_BSRR, 4);

}

/*取消“寄存器地址映射”*/

void led_iounmap(void)

{

  iounmap(MPU_AHB4_PERIPH_RCC_PI);

  iounmap(GPIOI_MODER_PI);

  iounmap(GPIOI_OTYPER_PI);

  iounmap(GPIOI_OSPEEDR_PI);

  iounmap(GPIOI_PUPDR_PI);

  iounmap(GPIOI_BSRR_PI);

}

void led_Pin_Init(void)

{

u32 val = 0;

/* 2、使能RCC时钟 */

val = readl(MPU_AHB4_PERIPH_RCC_PI);/* 读RCC_MP_AHB4ENSETR寄存器 */

val &= ~(0X1 << 8);/* 清除以前的bit8设置 */

val |= (0X1 << 8); /* 设置新的bit8值 */

writel(val, MPU_AHB4_PERIPH_RCC_PI);

/* 将val的值写入RCC_MP_AHB4ENSETR寄存器 */

/* 3、将PI0输出引脚。*/

val = readl(GPIOI_MODER_PI);/*读GPIOI_MODER寄存器*/

val &= ~(0X3 << 0); /* bit0:1清零 */

val |= (0X1 << 0); /* bit0:1设置01,配置为输出模式 */

writel(val, GPIOI_MODER_PI);

/* 将val的值写入GPIOI_MODER寄存器 */

/* 4、设置PI0为推挽模式 */

val = readl(GPIOI_OTYPER_PI);/*读GPIOI_OTYPER寄存器*/

val &= ~(0X1 << 0); /* bit0清零,设置为上拉*/

writel(val, GPIOI_OTYPER_PI);

/* 将val的值写入GPIOI_OTYPER寄存器 */

/* 5、设置PI0为高速 */

val = readl(GPIOI_OSPEEDR_PI);/*读GPIOI_OSPEEDR寄存器*/

val &= ~(0X3 << 0); /* bit0:1 清零 */

val |= (0x3 << 0); /* bit0:1 设置为11,极高速*/

writel(val, GPIOI_OSPEEDR_PI);

/* 将val的值写入GPIOI_OSPEEDR寄存器 */

/* 6、设置PI0为上拉。*/

val = readl(GPIOI_PUPDR_PI);/*读GPIOI_PUPDR寄存器*/

val &= ~(0X3 << 0); /* bit0:1 清零*/

val |= (0x1 << 0); /*bit0:1 设置为01,配置为上拉*/

writel(val,GPIOI_PUPDR_PI);

/* 将val的值写入GPIOI_PUPDR寄存器 */

/* 6、默认打开LED,PI0=0 */

val = readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/

val &= ~(0X1 << 16); /* bit16 清零*/

val |= (0x1 << 16); /*bit16 设置为1,令PI0输出低电平*/

writel(val, GPIOI_BSRR_PI);

/* 将val的值写入GPIOI_BSRR寄存器 */

/* 6、默认关闭LED,PI0=1 */

val = readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/

val &= ~(0X1 << 0); /* bit0 清零*/

val |= (0x1 << 0);/*bit0 设置为1,令PI0输出高电平*/

writel(val, GPIOI_BSRR_PI);

/* 将val的值写入GPIOI_BSRR寄存器 */

}

void led_switch(u8 sta)

{

u32 val = 0;

if(sta == LEDON) {

val = readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/

    val &= ~(0X1 << 16); /* bit16 清零*/

val |= (0x1 << 16); /*bit16 设置为1,令PI0输出低电平*/

writel(val, GPIOI_BSRR_PI);

/* 将val的值写入GPIOI_BSRR寄存器 */

}

else if(sta == LEDOFF) {

val = readl(GPIOI_BSRR_PI);/*读GPIOI_BSRR寄存器*/

val &= ~(0X1 << 0); /* bit0 清零*/

val |= (0x1 << 0);/*bit0 设置为1,令PI0输出高电平*/

writel(val, GPIOI_BSRR_PI);

/* 将val的值写入GPIOI_BSRR寄存器 */

}

}

4、新建LED.h

LED.h文件如下:

#ifndef __LED_H

#define __LED_H

#include <linux/types.h>

/*

数据类型重命名

使能bool,u8,u16,u32,u64, uint8_t, uint16_t, uint32_t, uint64_t

使能s8,s16,s32,s64,int8_t,int16_t,int32_t,int64_t

*/

#define LEDOFF 0 /* 关灯 */

#define LEDON 1 /* 开灯 */

/* 寄存器物理地址 */

#define PERIPH_BASE      (0x40000000)

#define MPU_AHB4_PERIPH_BASE    (PERIPH_BASE + 0x10000000)

#define RCC_BASE         (MPU_AHB4_PERIPH_BASE + 0x0000)

#define RCC_MP_AHB4ENSETR (RCC_BASE + 0XA28)

#define GPIOI_BASE (MPU_AHB4_PERIPH_BASE + 0xA000)

#define GPIOI_MODER       (GPIOI_BASE + 0x0000)

#define GPIOI_OTYPER       (GPIOI_BASE + 0x0004)

#define GPIOI_OSPEEDR       (GPIOI_BASE + 0x0008)

#define GPIOI_PUPDR       (GPIOI_BASE + 0x000C)

#define GPIOI_BSRR       (GPIOI_BASE + 0x0018)

extern void led_ioremap(void);

extern void led_iounmap(void);

extern void led_Pin_Init(void);

extern void led_switch(u8 sta);

#endif

5、新建LED_APP.c

LED_APP.c文件内容如下:

#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/stat.h"

#include "fcntl.h"

#include "stdlib.h"

#include "string.h"

//APP运行命令:./LED_APP MyLED 1表示打开LED

//APP运行命令:./LED_APP MyLED 0表示关闭LED

#define LEDOFF 0 /* 关灯 */

#define LEDON 1 /* 开灯 */

/*

参数argc: argv[]数组元素个数

参数argv[]:是一个指针数组

返回值: 0 成功;其他 失败

*/

int main(int argc, char *argv[])

{

  int fd, retvalue;

  char *filename;

  unsigned char databuf[1];

  if(argc != 3)

  {

    printf("Error Usage!\r\n");

    return -1;

  }

  //argv[]是指向输入参数“./LED_App” “/dev/MyLED” “1”

  filename = argv[1];

  //argv[1]指向字符串“/dev/MyLED

  fd = open(filename, O_RDWR);

  //如果打开“/dev/LED”文件成功,则fd为“文件描述符”

  //fd=0表示标准输入流; fd=1表示标准输出流;fd=2表示错误输出流;

  if(fd < 0)

  {

    printf("Can't open file %s\r\n", filename);

    return -1;

  }

  databuf[0]= atoi(argv[2]); /* 写入的数据,是数字的,表示打开或关闭 */

  retvalue = write(fd, databuf, 1);

  //将databuf[]中前1个字节发送给用户

  //返回值大于0表示写入的字节数;

  //返回值等于0表示没有写入任何数据;

  //返回值小于0表示写入失败

  if(retvalue < 0)

  {

    printf("write file %s failed!\r\n", filename);

    close(fd);

    //fd表示要关闭的“文件描述符”

    //返回值等于0表示关闭成功

    //返回值小于0表示关闭失败

    return -1;

  }

  /* 关闭设备 */

  retvalue = close(fd);

  //fd表示要关闭的“文件描述符”

  //返回值等于0表示关闭成功

  //返回值小于0表示关闭失败

  if(retvalue < 0)

  {

    printf("Can't close file %s\r\n", filename);

    return -1;

  }

  return 0;

}

6、新建Makefile

Makefile文件如下:

KERNELDIR := /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31

#使用“:=”将其后面的字符串赋值给KERNELDIR

CURRENT_PATH := $(shell pwd)

#采用“shell pwd”获取当前打开的路径

#使用“$(变量名)”引用“变量的值”

MyAPP := LED_APP

MyOldLED_Module-objs = LEDInterface.o LED.o

obj-m := MyOldLED_Module.o

CC := arm-none-linux-gnueabihf-gcc

drv:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

app:

$(CC)  $(MyAPP).c  -o $(MyAPP)

clean:

$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

rm $(MyAPP)

install:

sudo cp *.ko $(MyAPP) /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -f

7、添加“c_cpp_properties.json

按下“Ctrl+Shift+P”,打开VSCode控制台,然后输入“C/C++:Edit Configurations(JSON)”,打开以后会自动在“.vscode ”目录下生成一个名为“c_cpp_properties.json” 的文件。

修改c_cpp_properties.json内容如下所示:

{

    "configurations": [

        {

            "name": "Linux",

            "includePath": [

                "${workspaceFolder}/**",

"/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31",  "/home/zgq/linux/Linux_Drivers/MyOldLED", "/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include", "/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/include", "/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31/arch/arm/include/generated"
            ],

            "defines": [],

            "compilerPath": "/usr/bin/gcc",

            "cStandard": "gnu11",

            "cppStandard": "gnu++14",

            "intelliSenseMode": "gcc-x64"

        }

    ],

    "version": 4

}

8、编译

输入“make clean回车

输入“make drv回车

输入“make app回车

输入“make install回车

输入“ls /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31/ -l回车”产看是存在“LED_APP和MyOldLED_Module.ko

9、测试

启动开发板,从网络下载程序

输入“root

输入“cd /lib/modules/5.4.31/回车

切换到“/lib/modules/5.4.31/”目录

注意:“lib/modules/5.4.31/在虚拟机中是位于“/home/zgq/linux/nfs/rootfs/”目录下,但在开发板中,却是位于根目录中

输入“ls -l”查看“LED_APP和MyOldLED_Module.ko”是否存在

输入“depmod”,驱动在第一次执行时,需要运行“depmod”

输入“modprobe MyOldLED_Module.ko”,加载“MyOldLED_Module.ko”模块

输入“lsmod”查看有哪些驱动在工作

输入“mknod /dev/MyOldLED_Module c 200 0回车

//“mknod”是创建节点命令

//“/dev/MyOldLED_Module”表示节点文件

//“c”表示LED是个字符设备

//“200”表示设备的主设备号

//“0”表示设备的次设备号

输入“ls /dev/MyOldLED_Module  -l回车”,

发现节点文件“/dev/MyOldLED_Module

输入“./LED_APP /dev/MyOldLED_Module 1回车”执行写1开灯

输入“./LED_APP /dev/MyOldLED_Module 0回车”执行写0关灯

操作完成,则执行卸载模块:

输入“rmmod MyOldLED_Module.ko”,卸载“MyOldLED_Module.ko”模块

注意:输入“rmmod MyOldLED_Module”也可以卸载“MyOldLED_Module.ko”模块

输入“lsmod”查看有哪些驱动在工作。

 搞了一天才搞好,网上这方面的资料很少。如果Makeile写错了,就搞不好了。

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

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

相关文章

个人健康管理系统|基于微信小程序的个人健康管理系统设计与实现(源码+数据库+文档)

个人健康管理小程序目录 目录 基于微信小程序的个人健康管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2 运动教程管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设…

2024最新算法:斑翠鸟优化算法(Pied Kingfisher Optimizer ,PKO)求解23个基准函数

一、斑翠鸟优化算法 斑翠鸟优化算法&#xff08;Pied Kingfisher Optimizer ,PKO&#xff09;&#xff0c;是由Abdelazim Hussien于2024年提出的一种基于群体的新型元启发式算法&#xff0c;它从自然界中观察到的斑翠鸟独特的狩猎行为和共生关系中汲取灵感。PKO 算法围绕三个不…

售前方案工程师:程序员跨界闯新天,解码售前方案的魅力与挑战

在程序员的多元职业迷宫中&#xff0c;除了前端花园的绚烂和后端洞穴的深邃&#xff0c;还存在着一条独特的赛道——售前方案工程师。 这一角色融合了技术深度与商业洞察&#xff0c;是技术与市场交汇的桥头堡&#xff0c;为那些渴望将技术实力转化为商业价值的程序员提供了一…

【推荐】JuiceSSH 一款可以在手机端免费使用的SSH客户端工具

文章目录 一&#xff0c;官网地址二&#xff0c;下载链接三&#xff0c;使用说明 一&#xff0c;官网地址 https://juicessh.com/ 二&#xff0c;下载链接 https://juicessh.com/changelog#v3.2.2 三&#xff0c;使用说明 使用相当简单&#xff0c;手机上点击“快速连接…

GEE 将裁剪后的Sentinel-2影像 在ArcGIS中去除空值

在ArcGIS中&#xff0c;可以使用栅格计算器&#xff08;Raster Calculator&#xff09;工具来设置NoData值为空。以下是在ArcGIS中将NoData值设置为空的步骤&#xff1a; 打开ArcGIS软件并加载下载的Sentinel-2影像数据。 影像Nodata空值以黑色背景呈现&#xff0c;影响矢量数据…

就业班 2401--3.6 Linux Day12--计划任务和邮件和ssh远程连接

一、计划任务 计划任务概念解析 在Linux操作系统中&#xff0c;除了用户即时执行的命令操作以外&#xff0c;还可以配置在指定的时间、指定的日期执行预先计划好的系统管理任务&#xff08;如定期备份、定期采集监测数据&#xff09;。RHEL6系统中默认已安装了at、crontab软件…

Vue源码系列讲解——过滤器篇【二】(工作原理)

目录 1. 前言 2. resolveFilter函数分析 3. 串联过滤器原理 4. 过滤器接收参数 5. 小结 1. 前言 通过上一篇用法回顾我们知道&#xff0c;过滤器有两种使用方式&#xff0c;分别是在双花括号插值中和在 v-bind 表达式中。但是无论是哪一种使用方式&#xff0c;过滤器都是写…

Python 系统学习总结(基础语法+函数+数据容器+文件+异常+包+面向对象)

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 六天时间系统学习Python基础总结&#xff0c;目前不包括可视化部分&#xff0c;其他部分基本齐全&#xff0c;总结记录&#xff0…

快速上手:剧本杀dm预约平台小程序的制作流程

在当今的娱乐市场中&#xff0c;剧本杀已经成为一种备受欢迎的娱乐方式。为了给玩家提供更好的服务和体验&#xff0c;开发一个剧本杀DM预约平台小程序是至关重要的。下面&#xff0c;我们将详细介绍如何使用乔拓云第三方平台开发这样一个预约平台。 首先&#xff0c;打开乔拓云…

QLC SSD:LDPC纠错算法的优化方案

随着NAND TLC和QLC出现,LDPC也在不断的优化研究,提升纠错能力。小编看到有一篇来自Microchip发布的比较详细的LDPC研究数据,根据自己的理解分析解读给大家,如有错误,请留言指正! 文档中测试LDPC(Low-Density Parity-Check)码是为了评估其在不同配置下对数据错误的有效…

基于51单片机的四位并行数据主从机传输设计

基于51单片机的四位并行数据主从机传输设计[proteus仿真] 主从机通信系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的四位并行数据主从机传输设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文…

spring 事务失效的 12 种场景

文章目录 spring 事务失效的 12 种场景一、事务不生效1.访问权限问题2. 方法用 final 修饰3.方法内部调用&#xff08;自己玩自己&#xff09;3.1 新加一个 Service 方法3.2 在该 Service 类中注入自己3.3 通过 AopContent 类 4.Bean没有纳入Spring IOC容器管理5.多线程调用&am…

时间轮奇妙旅程:深度解析Netty中的时间轮机制

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 时间轮奇妙旅程&#xff1a;深度解析Netty中的时间轮机制 前言时间轮的基本概念时间轮的工作机制netty中时间轮的实现时间轮实现细节&#xff1a;简化的源码示例&#xff1a; 时间轮的应用场景时间轮的…

调研图基础模型(Graph Foundation Models)

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 图基础模型&#xff08;Graph Foundation Models&#xff0c;简称 GFMs&#xff09; 是一种经过预训练的图大模型&#xff0c;旨在处理不同领域的图数据和任务。让我们详细探讨一下这个概念。 Github …

掌握Nodejs高级图片压缩技巧提升web优化

掌握Nodejs高级图片压缩技巧提升web优化 在当今的数字时代,图像在网络开发中发挥着至关重要的作用。它们增强视觉吸引力、传达信息并吸引用户。然而,高质量的图像通常有一个显着的缺点——较大的文件大小会减慢网页加载时间。为了应对这一挑战并确保快速加载网站,掌握 Node…

SQL注入漏洞,常用注入函数及其pakachu漏洞靶场演示

目录 SQL注入漏洞概述 SQL注入的常用函数 漏洞分类与利用 1.基于联合查询的SQL注入 &#xff12;.盲注 时间盲注&#xff08;base on bool&#xff09;​编辑 &#xff13;.宽字节注入 4.inset&#xff0f;update&#xff0f;delete注入 &#xff15;.header注入 &…

【工作向】protobuf编译生成pb.cc和pb.py文件

序言 首先通过protoc --version查看protoc版本&#xff0c;避免pb文件生成方和使用方版本不一致 1. 生成pb.cc 生成命令 protoc -I${proto_file_dir} --cpp_out${pb_file_dir} *.proto参数&#xff1a; -I表示 proto 文件的路径&#xff1b; --cpp_out 表示输出路径&#xff…

关于Mybatis-Plus报错 Not Found TableInfoCache 解决办法

0. 接口结构&#xff1a;1. 方法报错&#xff1a;2. 解决方法&#xff1a;3. 原因分析&#xff1a; 0. 接口结构&#xff1a; 【接口】&#xff1a; public interface PurchaseOrderService extends IService<PurchaseOrder> {}【接口实现类】&#xff1a; public cla…

Java项目:39 springboot007大学生租房平台的设计与实现

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统有管理员、房东和用户 【主要功能】 1、后台&#xff1a;房源管理、信息审批管理、订单信息管理、房东管理、用户管理 2、前台&#xff1a;注册登…

PackagesNotFoundError:学习利用报错信息找到解决方法

反思&#xff1a;之前看到报错经常是直接复制报错信息去网上搜&#xff0c;但很多情况下报错信息里其实就给出了解决方案 报错信息&#xff1a; Collecting package metadata (current_repodata.json): done Solving environment: unsuccessful initial attempt using frozen …