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

【Linux】进程间通信——System V共享内存

🔥 个人主页:大耳朵土土垚
🔥 所属专栏:Linux系统编程

这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉

文章目录

  • 前言
  • 1. 基本原理
  • 2. 数据结构
  • 3. 创建与使用
    • ✨进程间通信实例
  • 4. 共享内存特点
  • 5. 结语

前言

  System V是一种在Linux系统中用于进程间通信(IPC)的机制。它提供了几种不同的通信方式,包括共享内存、消息队列和信号量。以下是关于Linux进程间通信System V共享内存的详细解释:

1. 基本原理

  System V共享内存是IPC(进程间通信)机制的一部分,它允许两个或多个进程共享一段物理内存。这段内存可以被所有参与的进程读取和写入。这种方式通常比较高效,因为进程可以直接对内存进行读写操作,而不需要通过内核进行数据传输。如下图所示:
在这里插入图片描述

2. 数据结构

  System V共享内存可以在内存中创建多个,所以操作系统需要借助一种数据结构来管理它。System V共享内存使用struct shmid_ds结构体来描述共享内存的状态和属性。该结构体包括共享内存的键值key用来唯一标识共享内存,还包括了共享内存的权限、大小、创建时间、最后访问时间等信息。

注意键值key是由用户定义的标识符,不是系统生成的,这是因为进程间需要通过key来确定和使用共享内存,如果是由系统创建的,那么其他进程就无法得知该共享内存的key,从而无法使用。如果是用户自己定义的,那么用户想让哪个进程使用都可以。

3. 创建与使用

  创建System V共享内存段的主要函数有shmgetshmatshmdtshmctl

  1. int shmget(key_t key, size_t size, int shmflg);

    • 该函数用于创建一个新的共享内存段或者获取一个已有的共享内存段。
    • 参数key是一个用户定义的标识符,通常通过ftok()函数生成。

    因为用户不确定哪些key值已经被使用了,哪些没被使用,所以操作系统提供了一个函数,可以帮助用户生成唯一的标识符。

    • key_t ftok(const char *pathname, int proj_id);

    ftok函数将给定的文件路径名(pathname)和项目ID(proj_id)根据算法转换为一个键值(key_t),用于创建或访问System V IPC资源(如消息队列、共享内存、信号量等)。这样不同进程间只需知道文件路径和项目ID就可以确定共享内存的标识符key了。

    • 参数size指定了共享内存段的大小(以字节为单位)。
    • 参数shmflg我们主要学习两种:IPC_CREATIPC_EXCL

    IPC_CREATIPC_EXCL都是宏,IPC_CREAT表示如果通过key值标识的共享内存不存在就创建;存在就获取该共享内存并返回它。

    IPC_EXCL单独使用无意义,通常是和IPC_CREAT搭配使用,IPC_CREAT|IPC_EXCL,使用逻辑运算符或连接:表示如果通过key值标识的共享内存不存在就创建;存在就出错返回。

    • shmget返回值是一个共享内存标识符,如果出错则返回-1。

    注意这个标识符不是key,而是给用户用的一个标识共享内存的标识符。

例如,创建一个共享内存:

#include<iostream>
#include<string>
#include <sys/ipc.h>
#include <sys/shm.h>
const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
const int ProcessId = 0;
const size_t gsize = 4096;
int main()
{key_t key = ftok(gpath.c_str(),ProcessId);//获取唯一key值int shmid = ::shmget(key,gsize,IPC_CREAT|IPC_EXCL);if(shmid < 0)std::cout<<"共享内存创建失败..."<<std::endl;std::cout<<"共享内存key值:"<<key<<", "<<"shmid:"<<shmid<<std::endl;return 0;
}

结果如下:

在这里插入图片描述

我们还可以通过命令行命令来管理共享内存:

  • ipcs -m:用来查看系统的共享内存:
    在这里插入图片描述

虽然Server进程已经运行完了,但是共享内存还是存在;这是因为只要创建了共享内存没被删除,那么共享内存的生命周期就随内核!

  • ipcrm -m shmid:用来删除共享内存:
    在这里插入图片描述
  1. int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 对共享内存段执行特定的控制操作。
  • 参数shmid是由shmget()返回的共享内存标识符。
  • 参数cmd指定要执行的操作,例如IPC_RMID移除共享内存段,IPC_STAT获取共享内存段的状态等。
  • 参数buf是一个指向shmid_ds结构的指针,用来存储或修改共享内存段的信息。
  • 成功时返回0,出错时返回-1。

例如,使用shmctl删除一个共享内存:

#include<iostream>
#include<string>
#include<unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
const int ProcessId = 0;
const size_t gsize = 4096;
int main()
{//1.创建共享内存key_t key = ftok(gpath.c_str(),ProcessId);int shmid = ::shmget(key,gsize,IPC_CREAT|IPC_EXCL);if(shmid < 0)std::cout<<"共享内存创建失败..."<<std::endl;std::cout<<"共享内存key值:"<<key<<", "<<"shmid:"<<shmid<<std::endl;sleep(5);//2. 删除共享内存if(shmctl(shmid,IPC_RMID,nullptr)==0)std::cout<<"删除共享内存成功..."<<std::endl;return 0;
}

结果如下:
在这里插入图片描述

  1. void *shmat(int shmid, const void *shmaddr, int shmflg);

    • 将共享内存段连接到调用进程的地址空间。

    共享内存创建后必须挂接到进程中,获取到虚拟地址后才可以通过地址进行写入和读取

    • 参数shmid是由shmget()返回的共享内存标识符。
    • 参数shmaddr指定了共享内存段附加的位置,通常设置为NULL让系统选择适当的地址。
    • 参数shmflg可以包含标志如SHM_RNDSHM_RDONLY,这里我们设置为0即可。
    • 成功时返回指向共享内存段的指针,出错时返回(void *) -1

例如,将创建的共享内存挂接到进程中:

#include<iostream>
#include<string>
#include<unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
const int ProcessId = 0;
const size_t gsize = 4096;
int main()
{//1.创建共享内存key_t key = ftok(gpath.c_str(),ProcessId);int shmid = ::shmget(key,gsize,IPC_CREAT|IPC_EXCL);if(shmid < 0)std::cout<<"共享内存创建失败..."<<std::endl;std::cout<<"共享内存key值:"<<key<<", "<<"shmid:"<<shmid<<std::endl;sleep(5);//2. 挂接共享内存void* ret = shmat(shmid,nullptr,0);if((long long)ret == -1)std::cout<<"共享内存挂接失败..."<<std::endl;//3. 删除共享内存if(shmctl(shmid,IPC_RMID,nullptr)==0)std::cout<<"删除共享内存成功..."<<std::endl;elsestd::cout<<"共享内存挂接成功..."<<std::endl;return 0;
}

结果如下:
在这里插入图片描述

发现共享内存挂接失败,这是因为我们在创建共享内存时没有设置权限,导致我们没有权限挂接,所以在创建共享内存时必须带上权限:shmget(key,gsize,IPC_CREAT|IPC_EXCL|0600);,与文件权限一致0600表示拥有者可读可写,所以正确代码如下:

#include<iostream>
#include<string>
#include<unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
const int ProcessId = 0;
const size_t gsize = 4096;
int main()
{//1.创建共享内存key_t key = ftok(gpath.c_str(),ProcessId);int shmid = ::shmget(key,gsize,IPC_CREAT|IPC_EXCL|0600);if(shmid < 0)std::cout<<"共享内存创建失败..."<<std::endl;std::cout<<"共享内存key值:"<<key<<", "<<"shmid:"<<shmid<<std::endl;sleep(5);//2. 挂接共享内存void* ret = shmat(shmid,nullptr,0);if((long long)ret == -1)std::cout<<"共享内存挂接失败..."<<std::endl;elsestd::cout<<"共享内存挂接成功..."<<std::endl;//3. 删除共享内存if(shmctl(shmid,IPC_RMID,nullptr)==0)std::cout<<"删除共享内存成功..."<<std::endl;return 0;
}

在这里插入图片描述
使用ipcs -m可以看到(注意这里没有删除共享内存才可以看到):
在这里插入图片描述

  1. int shmdt(const void *shmaddr);
    • 断开与共享内存段的连接。
    • 参数shmaddrshmat()返回的指针。
    • 成功时返回0,出错时返回-1。
#include<iostream>
#include<string>
#include<unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
const int ProcessId = 0;
const size_t gsize = 4096;
int main()
{//1.创建共享内存key_t key = ftok(gpath.c_str(),ProcessId);int shmid = ::shmget(key,gsize,IPC_CREAT|IPC_EXCL|0600);if(shmid < 0)std::cout<<"共享内存创建失败..."<<std::endl;std::cout<<"共享内存key值:"<<key<<", "<<"shmid:"<<shmid<<std::endl;sleep(5);//2. 挂接共享内存void* ret = shmat(shmid,nullptr,0);if((long long)ret == -1)std::cout<<"共享内存挂接失败..."<<std::endl;elsestd::cout<<"共享内存挂接成功..."<<std::endl;//3.断联共享内存if(shmdt(ret) == 0)std::cout<<"断开共享内存成功..."<<std::endl;//4. 删除共享内存if(shmctl(shmid,IPC_RMID,nullptr)==0)std::cout<<"删除共享内存成功..."<<std::endl;return 0;
}

结果如下:
在这里插入图片描述

创建、挂接、断联以及删除共享内存原理如下:
在这里插入图片描述

✨进程间通信实例

  • 基于以上4个函数,我们就可以封装一个ShareMem类来进行进程间通信:
#pragma once#include <iostream>
#include <string>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdalign.h>
#include <unistd.h>const std::string gpath = "/home/tutu/ProcessCommunicate/sharemem";
int gprojId = 0x6666;
// 操作系统,申请空间,是按照块为单位的:4KB,1KB, 2KB, 4MB
int gshmsize = 4096;
mode_t gmode = 0600;class ShareMem
{
private:void CreateShmHelper(int flag){_key = ::ftok(gpath.c_str(), gprojId);if (_key < 0){std::cout << "创建共享内存时ftok出错..." << std::endl;return;}_shmid = ::shmget(_key, gshmsize, flag); // 不存在返回-1if (_shmid < 0){std::cout << "创建共享内存时shmget出错..." << std::endl;return;}}public:ShareMem() : _shmid(-1), _key(0),_pshm(nullptr){}// 创建共享内存void CreateShareMem(){if (_shmid < 0)CreateShmHelper(IPC_CREAT | IPC_EXCL | gmode);}//获取共享内存void GetShareMem(){if(_shmid < 0)CreateShmHelper(IPC_CREAT);}//挂接共享内存void AttachShareMem(){if(_shmid>0)_pshm = ::shmat(_shmid,nullptr,0);}//去关联共享内存void DetachShareMem(){if(_pshm)::shmdt(_pshm);}//删除共享内存void DeleteShareMem(){if(_shmid > 0)::shmctl(_shmid, IPC_RMID, nullptr);}//获取共享内存地址void* GetShareMemAddr(){return _pshm;}
private:int _shmid;key_t _key;void* _pshm;
};ShareMem shm;
  • 创建共享内存并写入内容:

因为共享内存的指针是void*,可以是任意类型,也就是说共享内存实际上是通过指针进行读取和写入的,所以这里我们将它强制转化为字符指针进行写入读取。

int main()
{//1.创建共享内存shm.CreateShareMem();//2.挂接共享内存shm.AttachShareMem();//3. 获取共享内存地址char *str = (char*)shm.GetShareMemAddr();//强转为字符指针//4. 写入数据到共享内存int n = 0;while(n <= 10){str[n] = n+'0';n++;sleep(2);}//5.断开共享内存shm.DetachShareMem();//6.删除共享内存shm.DeleteShareMem();return 0;
}
  • 获取共享内存并读取内容:
int main()
{//1.获取共享内存shm.GetShareMem();//2.挂接共享内存shm.AttachShareMem();//3. 获取共享内存地址char *str = (char *)shm.GetShareMemAddr();//强转为字符指针//4. 读取共享内存内容int n = 10;while(n--){printf("%s\n",str);sleep(2);}//5.断开共享内存shm.DetachShareMem();//6.删除另一个进程删即可return 0;
}

每隔2s读取一次内容并打印

同时运行两个进程,结果如下:
在这里插入图片描述

4. 共享内存特点

  1. 通信速度最快

这是因为相较于管道通信需要通过文件缓冲区操作而言,共享内存只需通过指针操作即可

  1. 不同进程间共享内存块,但是没有任何保护机制

所以共享内存需要由用户自己完成保护,可以通过命名管道、加锁等操作。

5. 结语

  System V共享内存是一种高效的进程间通信(IPC)机制,它允许多个进程共享一块物理内存区域,从而避免了数据的复制,显著提高了数据传输速率。以上就是有关进程间通信中System V共享内存的所有内容啦~ 完结撒花 ~🥳🎉🎉

相关文章:

【Linux】进程间通信——System V共享内存

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…...

fastAPI快速使用

1. 安装: pip install fastapi 并且安装uvicorn来作为服务器&#xff1a; pip install uvicorn 最简单的 FastAPI 文件可能像下面这样&#xff1a; # main.pyfrom fastapi import FastAPIapp FastAPI()app.get("/") async def root():return {"message&qu…...

ruoyi前后端不分离创建module

ruoyi创建module 1.创建表 2.在若依中创建module 3.注意选择maven 4.命名 5&#xff0e;把module加入到rouyi的pom.xml中 6.student 中加入common依赖 二.生成代码 2.1先创建目录 2&#xff0e;2导入创建的表 2.3 注意各种配置 2.4预览代码 2.5 生成代码 2.6…...

【AI日记】24.12.08 kaggle 比赛 Titanic-11

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 内容&#xff1a; 学习 kaggle 入门比赛 Titanic - Machine Learning from Disaster学习机器学习&#xff08;pandas&#xff0c;numpy&#xff0c;sklearn&#xff0c;seaborn&#xff0c;matplotlib&a…...

处理后端返回的时间格式问题

今天在做项目的时候&#xff0c;发现后端返回的时间格式是“2024-12-08T06:11:46.00000:00”。 通过查阅资料&#xff0c;我发现这是后端返回的ISO 8601标准时间格式。这种格式在前端展示时可能不符合用户习惯&#xff0c;需要转换为更常见的“yyyy-MM-dd HH:mm:ss”格式&…...

【读书笔记·VLSI电路设计方法解密】问题33:ASIC芯片构建的主要步骤是什么

如问题32所述,ASIC芯片构建的主要步骤包括:RTL编写、功能验证、逻辑综合、布局布线、最终逻辑验证、时序验证、物理验证以及流片(Tapeout)。 RTL编写(RTL Coding) 这一阶段将设计意图从自然语言(如英文或中文)翻译为计算机可模拟的语言,以便进行仿真验证设计意图。此外…...

[机器学习] 监督学习之线性回归与逻辑回归

这里写目录标题 一、监督学习概述二、线性回归&#xff08;一&#xff09;模型表示&#xff08;二&#xff09;损失函数&#xff08;三&#xff09;梯度下降算法导入所需库生成模拟数据&#xff08;可替换为真实数据&#xff09;初始化参数并进行训练可视化损失函数随迭代次数的…...

十五、全局搜索正则表达式

一.grep简介 grep 全程Globally search a Regular Expression and Print&#xff0c;是一种强大的文本搜索工具&#xff0c;它能使用特 定模式匹配&#xff08;包括正则表达式&#xff09;搜索文本&#xff0c;并默认输出匹配行。Unix的grep家族包括grep和egrep 二.grep的工作…...

kali Linux 安装配置教程(图文详解)

目录 一、下载安装VMware二、下载kali镜像三、安装kali到虚拟机 一、下载安装VMware 点我查看 二、下载kali镜像 官网下载&#xff1a;https://www.kali.org/get-kali/#kali-platforms 演示下载的为下图左边的&#xff0c;实际我们直接下载右侧虚拟机的直接使用就行 右侧下…...

QT QTableWidget::setModel”: 无法访问 private成员

//严重性代码说明项目文件行禁止显示状态 //错误C2248 “QTableWidget::setModel”: 无法访问 private 成员(在“QTableWidget”类中声明) QSqlQueryModel* sql_model; ui.tableView_database->setModel(sql_model); //ok ui.tableWidget_database->setModel(sql_model)…...

C#怎么判断电脑是否联网

在 C# 中&#xff0c;可以通过几种方法检测计算机是否联网。以下是几种常用的方式&#xff1a; 1. 使用 System.Net.NetworkInformation.Ping 类 通过发送一个 Ping 请求到公共 DNS 服务器&#xff08;如 Google 的 DNS 8.8.8.8&#xff09;来检测是否联网。这是最常见的一种…...

丢垃圾视频时间检测 -- 基于状态机的实现

文章目录 OverviewKey PointsPseudo-code Overview 需要考虑的方面 状态定义和转换条件时序约束空间约束异常处理 状态机的设计需要考虑的场景&#xff1a; 没有人人进入人携带垃圾人离开但垃圾留下垃圾消失异常情况&#xff08;检测失败、多人多垃圾等&#xff09; Key P…...

EEG2Rep自监督脑电大模型文献阅读

原文网址&#xff1a; EEG2Rep: Enhancing Self-supervised EEG Representation... - Google 学术搜索https://scholar.google.com/scholar?hlzh-CN&as_sdt0%2C5&qEEG2Rep%3AEnhancingSelf-supervisedEEGRepresentationThroughInformativeMaskedInputs&btnG 1.文…...

【前端知识】React简单入门

React语法介绍 概述一、产生背景与发展历程二、主要特点三、技术细节四、应用场景与优势五、学习与实践 JSX语法一、JSX的基本概念二、JSX的基本使用三、JSX中的JavaScript表达式四、JSX的条件渲染五、JSX的列表渲染六、JSX的样式处理七、JSX的其他注意事项 基础语法一、基础概…...

高通---Camera调试流程及常见问题分析

文章目录 一、概述二、Camera配置的整体流程三、Camera的代码架构图四、Camera数据流的传递五、camera debug FAQ 一、概述 在调试camera过程中&#xff0c;经常会遇到各种状况&#xff0c;本篇文章对camera调试的流程进行梳理。对常见问题的提供一些解题思路。 二、Camera配…...

电压电流声音信号采集与分析系统

基于Labview的电压电流与声音信号采集与分析系统可以同时采集&#xff1a;电压、电流与振动信号。该系统部件可以采集传感器的真实数据&#xff0c;而且可以对采集的信号进行时域与频域分析&#xff0c;并可以实时显示历史数据&#xff0c;保存历史数据。具体的功能如下&#x…...

MongoDB语法及MongoTemplate用法

文章目录 概念操作数据库语法数据库及文档操作文档操作 整合springboot的MongoTemplate用法springboot配置插入删除更新查询 概念 1.MongoDB 是一个文档数据库&#xff0c;数据以 BSON 方式存储&#xff08;类似于json&#xff09; 2.文档&#xff08;Document&#xff09;&am…...

【git reset】本地下载特定历史提交哈希值的github文件【未联网服务器】进行git reset操作

本地电脑下载git文件&#xff0c;并进行git reset操作 问题描述&#xff1a;解决方法&#xff1a;方法1&#xff1a;直接下载特定版本的github压缩包。方法二&#xff1a; 在本地windows电脑上安装git工具进行git reset版本回退&#xff0c;之后上传相应版本的压缩包到服务器上…...

【开源安全保护】如何安装JumpServer堡垒机

【开源安全保护】如何安装JumpServer堡垒机 什么是堡垒机 大家好&#xff0c;我是星哥&#xff0c;今天我以前来认识堡垒机 堡垒机&#xff08;Bastion Host&#xff09;&#xff0c;也称为跳板机&#xff08;Jump Server&#xff09;&#xff0c;是指在计算机网络中&#x…...

log4j漏洞复现--vulhub靶场

声明&#xff1a;学习过程参考了同站的B1g0rang大佬的文章 Web网络安全-----Log4j高危漏洞原理及修复(B1g0rang) CVE-2021-44228 RCE漏洞 Log4j 即 log for java(java的日志) &#xff0c;是Apache的一个开源项目&#xff0c;通过使用Log4j&#xff0c;我们可以控制日志信息输…...

K8s面试系列:K8s常用 API 资源总结速记

写在前面 博文内容为 K8s 中常用的API 资源简单总结适合对K8s 有基本认知,温习,面试准备的小伙伴内容涉及:API 资源组成 ,SSA 和 CSA 资源操作方式,以及下面资源类别简单描述 工作负载:Deployments,StatefulSets,HorizontalPodAutoscaler (HPA)…服务: Service,Ingress,E…...

汽车免拆案例 | 2007款宝马650i车发动机偶尔无法起动

故障现象 一辆2007款宝马650i车&#xff0c;搭载N62B48B发动机&#xff0c;累计行驶里程约为26万km。车主反映&#xff0c;发动机偶尔无法起动&#xff0c;故障频率较低&#xff0c;十几天出现1 次&#xff0c;且故障出现时起动机不工作。 故障诊断  接车后试车&#xff0c;…...

前端(三)html标签(2)

html标签(2) 文章目录 html标签(2)一、列表标签二、表格三、form表单 一、列表标签 html中的列表分为无序列表、有序列表和自定义列表。 <!--无序列表的使用--> <!--pycharm中可以用ul>li*3tab的快捷键快速生成无序列表--> <ul><li>秒杀</li&g…...

D91【python 接口自动化学习】- pytest基础用法

day91 pytest的setup&#xff0c;setdown详解&#xff08;三&#xff09; 学习日期&#xff1a;20241207 学习目标&#xff1a;pytest基础用法 -- pytest的setup&#xff0c;setdown详解&#xff08;三&#xff09; 学习笔记&#xff1a; setup、teardown详解&#xff08;三…...

云桌面:云计算桌面

目录 云桌面的定义和核心概念 技术架构详解 主流架构详解 管理成本分析 安全性措施 应用场景详解 云桌面的定义和核心概念 云桌面是一种通过云计算技术提供的虚拟桌面服务&#xff0c;它允许用户通过网络访问远程服务器上的虚拟机&#xff0c;这些虚拟机为用户提供了一个…...

Word处理表格的一些宏

目录 1、表格首行居中2、表格内容靠左上下居中&#xff08;排除首行&#xff09; 1、表格首行居中 说明&#xff1a; 遇到错误将进行捕获&#xff0c;然后继续处理下一个表格 宏&#xff1a; Sub 表格首行居中()Dim tbl As tableOn Error Resume Next 错误时继续执行下一个…...

Linux网络编程---本地套接字

1.概述 本地套接字 1&#xff1a;作用:本地的进程间通信 2.有关系的进程间通信 3.没有关系的进程间的通信 本地套结字实现流程和网络套结字实现相似&#xff0c;一般采用tcp 二.通信流程 本地套结字通信的流程:1.服务器端:1.1 int fd socket(AF_UNIX/AF_LOCAL,…...

C#自动验证发票真假的程序

C#自动验证发票真假的程序 using Microsoft.Azure.CognitiveServices.Vision.ComputerVision; using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models; using System; using System.IO; using System.Threading.Tasks;namespace InvoiceValidation {class Pr…...

后端技术进阶知识总结

前端开发、后端开发、AI算法与应用等技术进阶知识总结 前言1.前端开发2.后端开发3.AI算法3.1 Studio级别的AI工具使用 前言 本文不记录基础性问题和详细解决方案。只记录key idea。 1.前端开发 2.后端开发 依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&…...

opencv复习

目录 1.core 1.图像变换 1.1 affine仿射变换 1.2 透视变换 2.四元数&#xff08;旋转&#xff09; 2.1 轴角转四元数 2.2 旋转矩阵转四元数 2.3 欧拉角转旋转矩阵 2.4 四元数转旋转矩阵 2.5 四元数用eigen用的比较多 2. imgproc. Image Processing 2.1 bilateralF…...

【Unity高级】在编辑器中如何让物体围绕一个点旋转固定角度

本文介绍如何在编辑器里让物体围绕一个点旋转固定角度&#xff0c;比如上图里的Cube是围绕白色圆盘的中心旋转45度的。 目标&#xff1a; 创建一个在 Unity 编辑器中使用的旋转工具&#xff0c;使开发者能够在编辑模式下快速旋转一个物体。 实现思路&#xff1a; 编辑模式下…...

通过IP远程连接MySQL服务时不允许连接到这个MySQL服务器

当你在连接Mysql时报这个错误时 is not allowed to connect to this MySQL server&#xff0c;意思是 MySQL 服务器不允许来自 IP 地址的连接。这通常是由于 MySQL 服务器的访问控制列表&#xff08;ACL&#xff09;限制了特定主机的连接。 要解决这个问题&#xff0c;你需要授…...

试题转excel;pdf转excel;试卷转Excel,word试题转excel

一、问题描述 一名教师朋友&#xff0c;偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运&#xff0c;几百道题几乎需要一个下午的时间 关键这些事&#xff0c;枯燥无聊费眼睛&#xff0c;实在是看起来就很蠢的工作 就想着做一个工具&#xff0c;可以自动处理…...

wordpress网站使用Linux宝塔面板和SQL命令行导入导出超过50M限制的数据库

wordpress网站使用Linux宝塔面板添加mysql数据库&#xff0c;使用phpMyAdmin工具导入sql数据库文件&#xff0c;会有最大限制50M。即使把sql数据库文件压缩为gzip或zip压缩包&#xff0c;压缩包也超过50M&#xff0c;该怎么办&#xff1f;怎样导入超过50M数据库呢&#xff1f; …...

VCP-CLIP A visual context prompting modelfor zero-shot anomaly segmentation

GitHub - xiaozhen228/VCP-CLIP: (ECCV 2024) VCP-CLIP: A visual context prompting model for zero-shot anomaly segmentation 需要构建正样本&#xff0c;异常样本&#xff0c;以及对应的Mask...

【原生js案例】webApp实现鼠标移入移出相册放大缩小动画

图片相册这种动画效果也很常见&#xff0c;在我们的网站上。鼠标滑入放大图片&#xff0c;滑出就恢复原来的大小。现在我们使用运动定时器来实现这种滑动效果。 感兴趣的可以关注下我的系列课程【webApp之h5端实战】&#xff0c;里面有大量的css3动画效果制作原生知识分析&…...

杂谈随笔-关于unity开发游戏

最近有在做unity的游戏开发&#xff0c;都是自学&#xff0c;甚至没有完整的课程体系…… 在犹豫要不要出系列教程&#xff0c;帮助新手快速入门的同时算是巩固一下基础知识。 那这篇文章先谈谈我对于引擎开发游戏的一些小观点&#xff0c;算是做了这么十几个星期的微不足道的…...

base64转file文件对象

1.base64转file文件对象 //将base64转换为文件 dataURLtoFile(dataurl, filename) { var arr dataurl.split(,),mime arr[0].match(/:(.*?);/)[1],bstr atob(arr[1]),n bstr.length,u8arr new Uint8Array(n);while (n--) {u8arr[n] bstr.charCodeAt(n);}return new Fil…...

【jvm】为什么要有GC

目录 1. 自动内存管理2. 提升程序稳定性3. 优化性能4. 跨平台能力5. 分代回收策略 1. 自动内存管理 1.JVM中的GC机制负责自动管理内存&#xff0c;这意味着开发人员不需要手动分配和释放内存。2.这一特性大大简化了Java程序的内存管理&#xff0c;降低了内存泄漏和内存溢出等问…...

开发指南085-大号版elementUI

ElementUI有些地方显示实在太小&#xff0c;不方便操作&#xff0c;需要放大&#xff1a; 1、el-dialog的标题栏那个关闭符号 使用如下方法放大 ::v-deep .el-dialog__headerbtn { font-size: 40px; font-weight: 700; top: 0px; } 2、el-table-column 设置sor…...

#渗透测试#红蓝对抗#SRC漏洞挖掘# Yakit(5)进阶模式-MITM中间人代理与劫持(下)

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

使用WebStorm开发Vue3项目

记录一下使用WebStorm开发Vu3项目时的配置 现在WebStorm可以个人免费使用啦&#xff01;?? 基本配置 打包工具&#xff1a;Vite 前端框架&#xff1a;ElementPlus 开发语言&#xff1a;Vue3、TypeScript、Sass 代码检查&#xff1a;ESLint、Prettier IDE&#xff1a;WebSt…...

Mac 录制电脑系统内的声音的具体方法?

1.第一步&#xff1a;下载BlackHole 软件 方式1&#xff1a;BlackHole官方下载地址 方式2&#xff1a; 百度云下载 提取码: n5dp 2.第二步&#xff1a;安装BlackHole 双击下载好的BlackHole安装包&#xff0c;安装默认提示安装。 3.第三步&#xff1a;在应用程序中找到音频…...

计算机网络

1.网络协议是什么&#xff1f; 在计算机网络要做到有条不紊地交换数据&#xff0c;就必须遵守一些约定好的规则&#xff0c;比如交换数据地格式&#xff0c;是否需要发送一个应答信息。这些规则被称为网络协议。 分层结构 应用层&#xff1a;为计算机用户提供服务表示层&…...

爬取某市KFC餐厅信息(POST请求+PYMYSQL)

# 简介 本教程将指导您如何使用Python爬取石家庄市的KFC门店信息&#xff0c;并将这些信息存储到MySQL数据库中。我们将使用requests库来发送网络请求&#xff0c;pymysql库来操作MySQL数据库。 环境准备 在开始之前&#xff0c;请确保您已经安装了以下Python库&#xff1a…...

109.【C语言】数据结构之二叉树层序遍历

目录 1.知识回顾 2.代码实现 准备工作 LevelOrder函数 代码框架 关键代码 3.执行结果 1.知识回顾 层序遍历参见106.【C语言】数据结构之二叉树的三种递归遍历方式文章 截取的部分内容 定义:按层的方式遍历(,设n为树的深度,h1-->h2-->h3-->...-->hn) 以下面…...

Java转C之内存管理

从 Java 转向 C 语言开发&#xff0c;内存管理和指针是两个核心且关键的概念。这些概念在 Java 中被抽象和自动化处理&#xff0c;而在 C 语言中则需要开发者手动管理和操作。 目录 内存管理概述指针基础 指针的定义与初始化地址运算符 & 和解引用运算符 *指针运算 动态内…...

共享内存和信号量

一、共享内存原理 1、基础前提 共享内存是为了进程之间通信服务的。进程间的通信的核心是要让两个不同的进程看到同一份资源。之前的匿名管道通过父子进程继承的关系&#xff0c;让父子进程看到同一份资源&#xff0c;进而进行通信&#xff1b;命名管道则是通过唯一的路径让两…...

SED命令

基本用法&#xff1a; sed命令具体应用&#xff1a; 1.删除第2-5行 nl regular_express.txt | sed 2d结果&#xff1a; 2.在第二行之后新增两行&#xff0c;分别为"drink tea…" 和"drink beer?" nl regular_express.txt | sed 2 a\ drink tea...\…...

洛谷 P6368 [COCI2006-2007#6] MAGIJA C语言

题目&#xff1a;https://www.luogu.com.cn/problem/P6368 题目背景 知名魔术师 AlDimi Kartimi 需要你帮助他来设计他扑克牌的背面图案。 题目描述 众所周知&#xff0c;扑克牌的背面是一个矩形&#xff0c;通过做两边的中垂线可以将矩形分成相等的四部分。 AlDimi Karti…...