存储课程学习笔记1_访问scsi磁盘读写测试(struct sg_io_hdr,ioctl,mmap)

创建虚拟机时,可以选择SCSI,STAT,NVME不同类型的磁盘。

0:总结

===》了解内核提供的访问scsi的结构和方法 (主要是sg_io_hdr_t 结构体和ioctl函数)。

===》需要读scsi协议文档,了解相关指令,只演示了16字节固定长度读和写指令。

===》了解mmap,直接映射磁盘可以实现读写功能。

1:简单了解概念。

sata 是串行接口,访问sata设备, 除了使用控制指令(原语交互),就是使用fis数据包进行数据交互。(直接使用串口连接进行通信)

scsi 采用并行传输方式,支持多个指令同时发送,需要参考对应的协议文档,构造协议进行磁盘的交互。

nvme是一种基于pcie总线封装的存储接口协议,支持多个队列、并行操作和低延迟I/O操作等。

2:构造scsi相关交互指令,和scsi设备进行读写交互。

这里采用虚拟机测试的方法,新增磁盘,选择磁盘类型为scsi,操作改磁盘。

2.1 内核中提供了专门的结构,使用ioctl进行写入。

主要关注struct sg_io_hdr 结构体,构造对应的对象,用ioctl进行与scsi设备的交互。

sg_io_hdr_t 是用于与 SCSI 设备进行通信的数据结构,它包含了执行 SCSI I/O 操作时所需的各种参数和状态信息。这个结构体在进行 SCSI 命令的传输和数据交互时起到关键的作用。主要了解 #include <scsi/sg.h> 头文件内容 
typedef struct sg_io_hdr
{int interface_id;           //表示接口标识,通常设置为 ‘S’,表示 SCSI generic。int dxfer_direction;        // 数据传输方向   SG_DXFER_NONE: 没有数据传输。   SG_DXFER_TO_DEV: 将数据从主机传输到设备。  SG_DXFER_FROM_DEV: 将数据从设备传输到主机。  SG_DXFER_TO_FROM_DEV: 双向数据传输。unsigned char cmd_len;      // SCSI 命令的长度(字节数)。unsigned char mx_sb_len;    //可写入 sense_buffer(感知缓冲区)的最大长度unsigned short iovec_count; //scatter-gather 元素的数量。0 表示没有 scatter-gather 操作。unsigned int dxfer_len;     //数据传输的总字节数void __user *dxferp;	    //指向数据传输内存或 scatter-gather 列表的指针   可以传多个地址unsigned char __user *cmdp;  //指向要执行的 SCSI 命令的指针void __user *sbp;		 //指向 sense_buffer 内存的指针,用于存储设备返回的感知数据unsigned int timeout;       // 操作的超时时间,单位为毫秒。MAX_UINT 表示没有超时限制unsigned int flags;         //标志位,控制操作的一些行为。可以使用 SG_FLAG... 常量int pack_id;                // 用于内部用途的包标识,通常不使用。void __user * usr_ptr;      // 内部用途的用户指针,通常不使用unsigned char status;       //SCSI 命令的状态unsigned char masked_status;//经过位移和掩码处理后的 SCSI 状态unsigned char msg_status;   //消息级别的数据(可选)。unsigned char sb_len_wr;    //实际写入到 sense_buffer 的字节数unsigned short host_status;   //主机适配器返回的错误状态unsigned short driver_status; //软件驱动程序返回的错误状态。int resid;                  //实际传输的字节数与预期传输的字节数之间的差值unsigned int duration;      // 命令执行的时间,单位为毫秒。unsigned int info;          /* [o] auxiliary information */
} sg_io_hdr_t;  /* 64 bytes long (on i386) */#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...); //request 是依赖于设备的请求码,使用SG_IO标志与scsi设备进行交互

2.2 参考scsi协议文档,构造对应指令与scsi设备进行交互。

这里参考文档中直接访问指令相关 写和读磁盘相关指令,可以看到提供不同长度的固定长度协议指令(6,10,12,16,32),这里只用固定长度16字节构造指令实现写和读的功能进行测试。

2.2.1 16字节固定长度读指令构造

文档中对应的16位固定长度读指令如下:

在这里插入图片描述

对应协议构造与触发指令如下:

//参考对应的协议  设置相关指令进行读取  blkname为对应的scsi设备 lba为读位置, cnt_of_blocks为读的块数
int scsi_cmd16_read(char *blkname, int lba, int cnt_of_blocks)
{int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");return -1;}//按上面固定长度构造对应的指令char cmd[16] = {0x88, 0, 0, 0, 0, 0, (lba >> 24), (lba >> 16), (lba >> 8), lba,(cnt_of_blocks >> 24), (cnt_of_blocks >> 16), (cnt_of_blocks >> 8), cnt_of_blocks,0, 0};char *buffer = (char *)malloc(cnt_of_blocks * BLOCK_SIZE);char sense_buffer[32] = {0};sg_io_hdr_t io_hdr;io_hdr.interface_id = 'S';io_hdr.cmdp = cmd;io_hdr.cmd_len = 16;io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;io_hdr.dxfer_len = BLOCK_SIZE * cnt_of_blocks;io_hdr.dxferp = buffer;io_hdr.sbp = sense_buffer; //附加数据地址io_hdr.mx_sb_len = 32;     //附加数据数据长度io_hdr.timeout = 20000;// syncint i = 0;if (ioctl(fd, SG_IO, &io_hdr) < 0) {for (i = 0;i < 32;i ++) { //附加数据中信息 printf("%hx ", sense_buffer[i]);}printf("\n");return -1;}for (i = 0;i < BLOCK_SIZE * cnt_of_blocks;i ++) {if (i % BLOCK_SIZE == 0) {printf("\n\n new block \n");}printf("%hx ", buffer[i]);}printf("\n");close(fd);
}
2.2.2 16字节固定长度写指令构造

协议文档文档中写16位固定长度对应的协议

在这里插入图片描述

对应的代码模块:

int scsi_cmd16_write(char *blkname, int lba, int cnt_of_blocks)
{int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");}//参考协议构造对应的指令 char cmd[16] = {0x8A, 0, 0, 0, 0, 0, (lba >> 24), (lba >> 16), (lba >> 8), lba,(cnt_of_blocks >> 24), (cnt_of_blocks >> 16), (cnt_of_blocks >> 8), cnt_of_blocks,0, 0};char *buffer = (char *)malloc(cnt_of_blocks * BLOCK_SIZE);int i = 0;for (i = 0;i < cnt_of_blocks * BLOCK_SIZE;i ++) {buffer[i] = i % 0x80;}char sense_buffer[32] = {0};  //附加信息 用于存储对应的执行结果sg_io_hdr_t io_hdr;io_hdr.interface_id = 'S';io_hdr.cmdp = cmd;io_hdr.cmd_len = 16;io_hdr.dxfer_direction = SG_DXFER_TO_DEV;io_hdr.dxfer_len = BLOCK_SIZE * cnt_of_blocks;io_hdr.dxferp = buffer;io_hdr.sbp = sense_buffer;io_hdr.mx_sb_len = 32;io_hdr.timeout = 20000;if (ioctl(fd, SG_IO, &io_hdr) < 0) {for (i = 0;i < 32;i ++) {printf("%hx ", sense_buffer[i]);}printf("\n");return -1;}printf("write successfull\n");return 0;
}
2.2.3 16字节固定长度读写指令进行测试 main函数。
//了解scsi文档 参考内部其中块控制指令read和write实现对其进行demo测试
int main(int argc, char *argv[]) {char *blkname;if (argc != 4) return -1;blkname = argv[1];      //scsi设备  //逻辑地址和物理地址有映射关系 可以研究,逻辑地址一般是512字节int lba = atoi(argv[2]);             //逻辑块地址 和物理地址有映射关系 int cnt_of_blocks = atoi(argv[3]);   //块个数int ret = scsi_cmd16_write(blkname, lba, cnt_of_blocks);if (ret) return -1; ret = scsi_cmd16_read(blkname, lba, cnt_of_blocks);if (ret) return -1;return 0;
}
2.2.4 测试运行
#查找对应设备 找到新增的scsi设备
ubuntu@ubuntu:~/start_test$ lsblk
...
sdb                         8:16   0   10G  0 disk 
sr0                        11:0    1  1.8G  0 rom  
root@ubuntu:/home/ubuntu/start_test# gcc scsi_cmd_test.c -o scsi_cmd_test
root@ubuntu:/home/ubuntu/start_test# ./scsi_cmd_test /dev/sdb 32 2
write successfullnew block 
0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 ...new block 
0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 ...

2.3 使用mmap映射直接进行写和读测试

测试代码如下:

int main(int argc, char *argv[]) {char *blkname;if (argc != 4) return -1;blkname = argv[1];      //scsi设备  //逻辑地址和物理地址有映射关系 可以研究,逻辑地址一般是512字节int lba = atoi(argv[2]);             //逻辑块地址 和物理地址有映射关系 int cnt_of_blocks = atoi(argv[3]);   //块个数//这里注意mmap映射时相关参数的设置  普通文件 设备文件的映射参数用MAP_SHARED才写入成功int ret;ret = scsi_mmap_write(blkname, lba, cnt_of_blocks);if (ret) return -1;ret = scsi_mmap_read(blkname, lba, cnt_of_blocks);if (ret) return -1;return 0;
}

运行结果如下:

root@ubuntu:/home/ubuntu/start_test# ./scsi_cmd_test /dev/sdb 128 2new block 
0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19...new block 
0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19...

2.4:完整测试代码

可以尝试使用指令和mmap交互写和读,查看结果。

//sata scsi nvme几种设备类型 sata串口通信的方式  scsi使用并行交互  nvme借助pcie
//sata 使用控制指令和fsi命令进行控制
//scsi 参考对应的文档中指令  按指令协议构造 sg_io_hdr_t 用ioctl 和scsi设备进行交互
//nvme 设备内核中也提供了对应的结构和函数 控制对应设备 可以设计对应的block数据结构依次控制整个磁盘 扇区 inode节点  block之间的关系/*************************************
struct sg_io_hdr {int interface_id;       // 接口标识符(通常设置为 'S')int dxfer_direction;    // 数据传输方向,可选值:SG_DXFER_NONE, SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV, SG_DXFER_TO_FROM_DEVunsigned char cmd_len;  // 命令长度(单位字节)unsigned char mx_sb_len;  // 最大附加数据长度(单位字节)unsigned short iovec_count;  // 散列/聚合缓冲区数量unsigned int dxfer_len;  // 数据传输长度(单位字节)void *dxferp;           // 数据缓冲区指针void *cmdp;             // 命令缓冲区指针void *sbp;              // 附加数据缓冲区指针unsigned int timeout;   // 超时时间(毫秒)unsigned int flags;     // 标志位控制参数int pack_id;            // 请求包 ID (多个请求可以使用相同的 ID 进行关联)void *usr_ptr;          // 用户定义的指针,可用于自定义操作或回调函数等
}void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);addr:指定映射的起始地址,通常设置为 NULL,由操作系统自动选择合适的地址。length:指定映射的长度,以字节为单位。prot:指定映射区域的保护方式(权限)。可以是以下值之一:PROT_NONE:无权限,不能访问。PROT_READ:可读权限。PROT_WRITE:可写权限。PROT_EXEC:可执行权限。 这些值也可以通过按位或运算组合使用。flags:指定了一些选项标志:MAP_SHARED:对映射区域的修改会反映到底层文件中,并且多个进程可以共享该区域(需要有正确设置的文件描述符)。MAP_PRIVATE:对映射区域进行修改不会影响底层文件,并且对该区域的写入操作会产生私有副本(每个进程独立拥有一份副本)。MAP_FIXED:指定映射到的地址必须是准确的,如果不可用则会报错。fd:要映射的文件描述符(仅在映射文件时使用),如果是共享内存或匿名映射,则为 -1。offset:文件中的偏移量,指定从哪个位置开始映射文件(仅在映射文件时使用)。
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
#include <sys/mman.h>#define BLOCK_SIZE		512
int scsi_cmd16_write(char *blkname, int lba, int cnt_of_blocks);
int scsi_cmd16_read(char *blkname, int lba, int cnt_of_blocks);int scsi_mmap_write(char *blkname, int lba, int cnt_of_blocks);
int scsi_mmap_read(char *blkname, int lba, int cnt_of_blocks);
//了解scsi文档 参考内部其中块控制指令read和write实现对其进行demo测试
int main(int argc, char *argv[]) {char *blkname;if (argc != 4) return -1;blkname = argv[1];      //scsi设备  //逻辑地址和物理地址有映射关系 可以研究,逻辑地址一般是512字节int lba = atoi(argv[2]);             //逻辑块地址 和物理地址有映射关系 int cnt_of_blocks = atoi(argv[3]);   //块个数// int ret = scsi_cmd16_write(blkname, lba, cnt_of_blocks);// if (ret) return -1; // ret = scsi_cmd16_read(blkname, lba, cnt_of_blocks);// if (ret) return -1;//这里注意mmap映射时相关参数的设置  普通文件 设备文件的映射参数用MAP_SHARED才写入成功int ret;ret = scsi_mmap_write(blkname, lba, cnt_of_blocks);if (ret) return -1;ret = scsi_mmap_read(blkname, lba, cnt_of_blocks);if (ret) return -1;return 0;
}int scsi_cmd16_write(char *blkname, int lba, int cnt_of_blocks)
{int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");}char cmd[16] = {0x8A, 0, 0, 0, 0, 0, (lba >> 24), (lba >> 16), (lba >> 8), lba,(cnt_of_blocks >> 24), (cnt_of_blocks >> 16), (cnt_of_blocks >> 8), cnt_of_blocks,0, 0};char *buffer = (char *)malloc(cnt_of_blocks * BLOCK_SIZE);int i = 0;for (i = 0;i < cnt_of_blocks * BLOCK_SIZE;i ++) {buffer[i] = i % 0x80;}char sense_buffer[32] = {0};  //附加信息 用于存储对应的执行结果sg_io_hdr_t io_hdr;io_hdr.interface_id = 'S';io_hdr.cmdp = cmd;io_hdr.cmd_len = 16;io_hdr.dxfer_direction = SG_DXFER_TO_DEV;io_hdr.dxfer_len = BLOCK_SIZE * cnt_of_blocks;io_hdr.dxferp = buffer;io_hdr.sbp = sense_buffer;io_hdr.mx_sb_len = 32;io_hdr.timeout = 20000;if (ioctl(fd, SG_IO, &io_hdr) < 0) {for (i = 0;i < 32;i ++) {printf("%hx ", sense_buffer[i]);}printf("\n");return -1;}printf("write successfull\n");return 0;
}
//参考对应的协议  设置相关指令进行读取
int scsi_cmd16_read(char *blkname, int lba, int cnt_of_blocks)
{int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");return -1;}// 1024, 0x400char cmd[16] = {0x88, 0, 0, 0, 0, 0, (lba >> 24), (lba >> 16), (lba >> 8), lba,(cnt_of_blocks >> 24), (cnt_of_blocks >> 16), (cnt_of_blocks >> 8), cnt_of_blocks,0, 0};char *buffer = (char *)malloc(cnt_of_blocks * BLOCK_SIZE);char sense_buffer[32] = {0};sg_io_hdr_t io_hdr;io_hdr.interface_id = 'S';io_hdr.cmdp = cmd;io_hdr.cmd_len = 16;io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;io_hdr.dxfer_len = BLOCK_SIZE * cnt_of_blocks;io_hdr.dxferp = buffer;io_hdr.sbp = sense_buffer; //附加数据地址io_hdr.mx_sb_len = 32;     //附加数据数据长度io_hdr.timeout = 20000;// syncint i = 0;if (ioctl(fd, SG_IO, &io_hdr) < 0) {for (i = 0;i < 32;i ++) { //附加数据中信息 printf("%hx ", sense_buffer[i]);}printf("\n");return -1;}for (i = 0;i < BLOCK_SIZE * cnt_of_blocks;i ++) {if (i % BLOCK_SIZE == 0) {printf("\n\n new block \n");}printf("%hx ", buffer[i]);}printf("\n");close(fd);
}int scsi_mmap_read(char *blkname, int lba, int cnt_of_blocks) {int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");return -1;}off_t size = lseek(fd, 0, SEEK_END);if (size == -1) {perror("Failed to get disk size");close(fd);exit(EXIT_FAILURE);}void *mmaped = mmap(NULL, BLOCK_SIZE * cnt_of_blocks, PROT_WRITE | PROT_READ, MAP_PRIVATE, fd, lba * BLOCK_SIZE); if (mmaped == MAP_FAILED) {perror("Failed to mmap disk\n");close(fd);return -1;}char *buffer = (char *)mmaped;int i = 0;for (i = 0;i < BLOCK_SIZE * cnt_of_blocks;i ++) {if (i % BLOCK_SIZE == 0) {printf("\n\n new block \n");}printf("%hx ", buffer[i]);}printf("\n");munmap(mmaped, BLOCK_SIZE * cnt_of_blocks);close(fd);return 0;
}//这里的写入是没有用的 需要通过协议写入 
int scsi_mmap_write(char *blkname, int lba, int cnt_of_blocks) {int fd;if ((fd = open(blkname, O_RDWR)) < 0) {printf("device file opening failed\n");return -1;}void *mmaped = mmap(NULL, BLOCK_SIZE * cnt_of_blocks, PROT_READ | PROT_WRITE, MAP_SHARED, fd, lba * BLOCK_SIZE); if (mmaped == MAP_FAILED) {perror("Failed to mmap disk\n");close(fd);return -1;}char *buffer = (char *)mmaped;int i = 0;for (i = 0;i < cnt_of_blocks * BLOCK_SIZE;i ++) {buffer[i] = i % 0x80;}if (msync(mmaped, BLOCK_SIZE * cnt_of_blocks, MS_SYNC) == -1) {perror("msync");close(fd);return 1;}munmap(mmaped, BLOCK_SIZE * cnt_of_blocks);close(fd);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智启新机,云驱增长 | 华宇亮相2024腾讯全球数字生态大会

9月5日-6日&#xff0c;以“智启新机&#xff0c;云驱增长”为主题的2024腾讯全球数字生态大会在深圳国际会展中心举办。本次大会聚集了多位企业领军人物及行业专家&#xff0c;共同聚焦数字化下的产业新增长&#xff0c;以前沿探索为基石&#xff0c;以行业最佳实践为标杆&…

解密SERP代理:如何提高排名跟踪效率

一、什么是 SERP 代理&#xff1f; SERP代理是指专门用于访问搜索引擎结果页面&#xff08;SERP&#xff09;的代理服务器。这些代理服务器能够模拟真实的用户请求&#xff0c;从而避免因频繁查询或位置变化而导致IP被封禁或数据不准确。通过使用SERP代理&#xff0c;您可以获…

java 项目结构 文件说明 潜规则 java入门

java 项目结构 潜规则 java入门 一、controller、service、serviceImpl、Mapper、Xml等文件的作用 下图为java约定俗成的几个文件的作用 二、在项目中的使用情况&#xff0c;由于业务逻辑很简单&#xff0c;所以每个文件中的代码行数都很少 controller.java /*** 资产rim项目…

Java许可政策再变,Oracle JDK 17 免费期将结束!

原文地址&#xff1a;https://www.infoworld.com/article/3478122/get-ready-for-more-java-licensing-changes.html Oracle JDK 17的许可协议将于9月变更回Oracle Technology Network License Agreement&#xff0c;这将迫使用户重新评估他们的使用策略。 有句老话说&#xf…

个人hic分析流程搭建4—compartment模块分析

参考我的上一篇博客https://blog.csdn.net/weixin_62528784/article/details/142132891?spm1001.2014.3001.5502&#xff0c; 在处理完hic上游分析模块之后&#xff0c;接下来就是正式的3层次模块分析了&#xff0c;compartmentTADloop 3大主层次&#xff0c;本篇介绍compart…

Linux 挂载磁盘与开机自动挂载操作指南

Linux 挂载磁盘与开机自动挂载操作指南 文章目录 Linux 挂载磁盘与开机自动挂载操作指南一 挂载磁盘1 查看硬盘信息2 新增数据盘执行分区3 新建分区4 创建一个主分区5 分区编号6 初始磁柱编号7 截止磁柱编号8 查看新建分区信息9 分区结果写入10 新分区同步操作系统11 设置新分区…

如何编译OpenHarmony SDK API

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 startup子系统之syspara_lite系统属性部件 &#xff08;1&#xff09; startup子系统之syspara_lite系统属性部件 &#xff08;2&#xff09; startup子系…

跟《经济学人》学英文:2024年09月07日这期 What to read about the British economy

What to read about the British economy Britain used to be the world’s richest country. These six books explain how it came to be, and why it is no longer 原文&#xff1a; IN RECENT YEARS the British economy has tended to be in the news for the wrong re…

逆向工程 反编译 C# net core

索引器访问 在您的代码中&#xff0c;您试图使用 configurationRoot.get_Item("AgileConfig:appId") 来访问配置项&#xff0c;但这里存在几个问题&#xff1a; 错误的访问方法&#xff1a;在 .NET 的 IConfigurationRoot 接口中&#xff0c;没有直接名为 get_Item 的…

kkFileView PDF Image Mode Preview BUG

kkFileView PDF & Image Mode Preview BUG lazyload.js officePicture.ftl pdf.ftl kkFileView getCorsFile?urlPath 会触发SSRF漏洞 kkFileView SSRF-CSDN博客 commonHeader.ftl initWaterMark() 修改代码的工作量&#xff0c;主要是先部署项目&#xff0c;解…

OpenAI全新发布o1模型:开启 AGI 的新时代

OpenAI全新发布o1模型&#xff1a;开启 AGI 的新时代 欢迎关注【youcans的AGI学习笔记】原创作品 2024年9月13日&#xff0c;OpenAI新模型o1 正式发布。o1 在测试化学、物理和生物学专业知识的基准 GPQA-diamond 上&#xff0c;全面超过了人类博士专家。 OpenAI 宣称&#xff…

VSCode C++ Tasks.json中的变量

前言 上文介绍了在VSCode中创建C项目和编译多文件的情况。本文将介绍Tasks.json中一些变量的含义&#xff1b; 内容 tasks.json文件 下文参考VSCode文档&#xff1a;Visual Studio Code 变量参考 预定义标量 ${userHome} - 用户主文件夹的路径${workspaceFolder} - 在 VS Co…

软件测试之测试用例详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、通用测试用例八要素   1、用例编号&#xff1b;    2、测试项目&#xff1b;   3、测试标题&#xff1b; 4、重要级别&#xff1b;    5、预置条…

Mysql高级篇(中)——SQL性能分析

Mysql高级篇&#xff08;中&#xff09;—— SQL性能分析 一、&#xff08;了解&#xff09;MySQL Query Optimizer 的主要功能和原理二、&#xff08;了解&#xff09;MySQL 常见瓶颈三、关键字 EXPLAIN1、是什么2、基本语法3、EXPLAIN 执行信息详解&#xff08;1&#xff09…

HTML 转 PDF API 接口

HTML 转 PDF API 接口 网络工具 / 文件处理 支持网页转 PDF 高效生成 PDF / 提供永久链接。 1. 产品功能 超高性能转换效率&#xff1b;支持将传递的 HTML 转换为 PDF&#xff0c;支持转换 HTML 中的 CSS 格式&#xff1b;支持传递网站 URL&#xff0c;直接转换页面成对应的 …

代码随想录打卡Day31

又是难绷的一天啊&#xff0c;第二题和第三题看完视频才AC的&#xff0c;第一道题又被官方测试样例恶心了&#xff0c;下面细说。 56. 合并区间 这道题没有什么新的思路&#xff0c;还是先将区间按照区间左值排序&#xff0c;然后遍历向量中的每一个区间&#xff0c;如果和前…

在职研生活学习--20240907

开学第一天 9月7日&#xff0c;中南大学商学院迎来了一支充满活力的队伍——2024级MBA新生集体整装待发&#xff0c;我们满怀期待地登上了前往长沙望城柏乐园的大巴&#xff0c;准备开启一场为期两天一夜的素质拓展与团队建设之旅。 迎新幼儿园PPT 出发 抵达柏乐园&#xff0c;…

Docker torchserve 部署模型流程

1.拉取官方镜像 地址: https://hub.docker.com/r/pytorch/torchserve/tags docker pull pytorch/torchserve:0.7.1-gpu2. docker启动指令 CPU docker run --rm -it -d -p 8380:8080 -p 8381:8081 --name torch-server -v /path/model-server/extra-files:/home/model-serve…

食品分类2检测系统源码分享

食品分类2检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vi…

应用层协议 —— https

目录 http的缺点 https 安全与加密 运营商挟持 常见的加密方式 对称加密 非对称加密 数据摘要&#xff08;数据指纹&#xff09; 不安全加密策略 1 只使用对称加密 2 只使用非对称加密 3 双方都是用非对称加密 4 对称加密和非对称加密 解决方案 CA证书 http的缺点 我们可…