共享内存和信号量
一、共享内存原理
1、基础前提
共享内存是为了进程之间通信服务的。进程间的通信的核心是要让两个不同的进程看到同一份资源。之前的匿名管道通过父子进程继承的关系,让父子进程看到同一份资源,进而进行通信;命名管道则是通过唯一的路径让两个不相关的进程看到同一份文件,进而通过该文件进行通信。
2、共享内存过程
共享内存的本质就是在内存中申请一块空间,让两个进程都能看到,这里的细节很多,因为进程是有自己的虚拟地址空间的,进程中的代码要看到物理内存中的数据,必须通过虚拟地址+页表的映射;也就是说,系统在创建共享内存时,要将共享内存的地址放入对应的进程的页表,该进程也要在虚拟地址上开辟与之对应的空间。
系统开辟共享内存的详细步骤为:
①申请物理内存
②将申请的物理内存地址填充到页表中,然后把在进程内相对应的共享区的地址空间的起始地址返回给上层(供用户使用)
共享内存可以在写代码时设置其大小;在OS中可能会同时存在很多个共享内存,那么就可以用结构体struct shm去组织管理这些共享内存。
共享内存的生命周期是随内核的(system V下的通信方式,消息队列、信号量等,生命周期都是随内核的)
3、创建与删除共享内存的系统接口
(1)int shmget(key_t key,size_t size,int shmflg)
①size:共享内存的大小
②shmflg
该标志位有俩个选项,IPC_CREAT和IPC_EXCL,其中:
单独使用IPC_CREAT表示创建共享内存,如果共享内存存在则返回该共享内存的shm_id;使用IPC_CREAT | IPC_EXCL表示创建共享内存,如果该共享内存存在则出错返回;在实际应用中,使用前者来获取共享内存,使用后者来创建共享内存。
③key
key是用户创建的共享内存的唯一标识,可以通过ftok()函数获取,是用户给操作系统使用的对共享内存的唯一标识
④return value
返回shm_id,也是共享内存的唯一标识,是系统传给用户供用户使用的标识,在删除时就要根据shm_id删除。
(2)int shmctl(int shmid, int cmd, struct shmid_ds *buf)
只是删除的话,直接将buf设置为空指针,cmd设置为IPC_RMID就可以了。
二、共享内存代码
shm.hpp:
#include <sys/ipc.h>
#include <sys/shm.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<iostream>
#include<string>
#include<cerrno>
#include<cstdio>#define Creater 1
#define User 2
#define BASE_SIZE 4096 //共享内存大小
#define DEFAULT_PROJ 0x66const std::string path_default_1= "/home/zwh/study_lesson/shm";class Myshm
{std::string ToHex(int key){char* buffer;sprintf(buffer,"%x",key);return buffer;}void Attach(){_attach_addr=shmat(_shmid,nullptr,0);if(_attach_addr==nullptr){perror("shmat");}}void Detach(){int deret=shmdt(_attach_addr);if(deret==-1){perror("shmdt");}}public:Myshm(const std::string& path,int proj_id,int who):_file_path(path),_proj_id(proj_id),_who(who){if(_who==Creater){int key=Get_Key();CreateShm(key);std::cout<<"key:"<<ToHex(key)<<" shmid:"<<_shmid<<std::endl;}else if(_who==User){int key=Get_Key();GetShm(key);std::cout<<"key:"<<ToHex(key)<<" shmid:"<<_shmid<<std::endl;}Attach();}~Myshm(){if(_who==Creater){int del_ret=shmctl(_shmid,IPC_RMID,nullptr);if(del_ret==-1){perror("delete shm");}std::cout<<"delete success!"<<std::endl;}Detach();}int Get_Key(){int key=ftok(_file_path.c_str(),_proj_id);if(key==-1){perror("get key");}return key;}void CreateShm(int key){if(_who==Creater){_shmid=shmget(key,BASE_SIZE,IPC_CREAT|IPC_EXCL|0666);if(_shmid==-1){perror("shmget");}}}void GetShm(int key){if(_who==User){_shmid=shmget(key,BASE_SIZE,IPC_CREAT|0666);if(_shmid==-1){perror("shmget");}}}void * Addr(){return _attach_addr;}private:int _shmid;std::string _file_path;int _proj_id;int _who;void* _attach_addr;};
server.cpp:
#include "shm.hpp"
#include<unistd.h>
#include"namedpipe.hpp"using namespace std;//读端int main()
{Myshm shm1(path_default_1,DEFAULT_PROJ,Creater);char* attach_addr=(char *)shm1.Addr();NamedPipe readnamedpipe(File_Path,Creater);readnamedpipe.OpenForRead();while(1){string outmessage;readnamedpipe.ReadFifo(&outmessage);cout<<"receive message:"<<attach_addr<<endl;sleep(1);}return 0;
}
client.cpp:
#include "shm.hpp"
#include<unistd.h>
#include"namedpipe.hpp"
using namespace std;int main()
{Myshm shm1(path_default_1,DEFAULT_PROJ,User);char* attach_addr=(char *)shm1.Addr();char word='A';int i=0;NamedPipe writenamedpipe(File_Path,User);writenamedpipe.OpenForWrite();while(1){//写attach_addr[i]=word;i++;word++;string my_message="wake up";writenamedpipe.WriteFifo(my_message);sleep(2);}return 0;
}
运行结果:(右边的命令行操作代码为 while :; do ipcs -m;sleep 1;done)
makefile:
.PHONY: all
all:server clientserver : server.cppg++ -o $@ $^ -std=c++11client : client.cppg++ -o $@ $^ -std=c++11.PHONY: clean
clean: rm -f server client
注意点:
1、共享内存不提供任何保护机制,不想管道一样,会有阻塞机制;这样容易导致数据不一致问题,我们的一种解决方法是在代码中利用管道强行使得共享内存达到同步,实现代码如上;
2、我们在访问共享内存时,没用使用任何系统调用(创建共享内存、挂接,得到共享内存区域的起始地址void *后,强转为我们需要写的数据类型的指针,直接像内存中写入数据)。没使用系统调用,使得共享内存的通信方式是所有通信方式中最快的,因为大大减少了数据的拷贝次数。
3、我们在设置共享内存的大小时,最好是4096的整数倍,因为系统是默认申请4096的整数倍给用户的。言下之意就是,我们如果设置共享内存的大小为4097字节,系统也会申请4096 *2的大小的内存空间,而剩下的4095就会浪费。
三、获取共享内存属性
shmctl不仅仅可以用来释放共享内存,还可以用来获取共享内存的属性
而ipc_perm结构体的内部属性如下:
所以要获取共享内存的属性,我们在shm.hpp中添加一个函数,如下代码:
void Get_attribute(){struct shmid_ds ds;int n=shmctl(_shmid,IPC_STAT,&ds);std::cout<<"key:"<<ToHex(ds.shm_perm.__key) <<std::endl;std::cout<<"nattch:"<<ds.shm_nattch<<std::endl;}
运行结果:
四、信号量
1、前提概念
①多个执行流(进程),能看到的一份资源,称其为公共资源(共享资源);
②将被保护起来的资源称为临界资源;我们保护资源的措施分为同步和互斥;
③同步:进程之间的通信有一定的顺序;互斥:任何时刻都只能有一个进程在访问共享资源。
④资源一定要被访问,资源被访问的方式是通过代码(朴素的理解)。代码分为访问共享资源的代码(称为临界区)和非访问共享资源的代码(称为非临界区)
⑤对共享资源的保护,使其成为临界资源,本质是对访问共享资源的代码进行保护。(对临界区的加锁和解锁)
2、信号量理论
信号量的作用是用来保护临界资源,本质就是对临界区代码的保护。
信号量本质是一个计数器。
对于一份共享资源,申请信号量的本质是在这个公共资源中预定一份自己的位置;公共资源被分为n份,n也是信号量的初始值;程序员要做的是让执行流和每一份资源一一对应;每当有一个执行流要申请资源时,信号量就-1。
上面是共享资源被分为好多份的情况,叫做多元信号量如果不分,一个共享资源只能对应一个执行流,那么这称为二元信号量,二元信号量就是互斥。
信号量可以在进程中定义成一个全局变量吗?不可以。理由:①全局变量不能被所有进程看到;②该全局变量的++ --不是原子的(在汇编中的语句不止一条)
那么进程就要和共享内存、消息队列一样,必须让不同的进程看到同一个信号量。
信号量需要和其他公共资源(例如共享内存)一起使用,也就是说访问公共资源之前,要先申请信号量;访问公共资源之后,释放信号量。这意味着信号量也是一个公共资源。
信号量是用来保护临界资源安全的,这意味着信号量本身要是安全的,信号量的++ 和-- 都要是安全的,信号量的操作被称为PV操作,是原子性的;只有未申请和申请结束两个状态。
3、指令
信号量的指令只要把在共享内存中的-m换成-s就可以了(消息队列是-q)
五、对共享内存、消息队列、信号量的统一管理
共享内存、消息队列、信号量的获取和控制都是xxxget、xxxctrl这些,并且都有一个结构体xxx_ds以及ipc_perm
ips_ids是一个全局数据结构,其中有一个结构体是struct ipc_id_ary,struct ipc_id_ary中有一个柔性数组(可变数组,大小由size决定)
柔性数组内部全是指针,指向下面这个结构体:
描述共享内存、消息队列、信号量的结构体的第一个字段都是kern_ipc_perm
kern_ipc_perm中指向的就是共享内存、消息队列、信号量中第一个字段的地址,对kern_ipc_perm进行管理就可以实现对三者的统一管理。而我们xxxget函数返回的id就是kern_ipc_perm数组的下标;共享内存、消息队列、信号量之间也相互冲突,同一个key无法生成两个共享内存、消息队列、信号量;将每一个下标中的数据强转成我们已知的对应的共享内存、消息队列、信号量中的一种。
这种技术叫多态。
ipc_perm里有一个字段(mode)标识了具体的共享内存、消息队列、信号量中的哪种类型。
相关文章:
共享内存和信号量
一、共享内存原理 1、基础前提 共享内存是为了进程之间通信服务的。进程间的通信的核心是要让两个不同的进程看到同一份资源。之前的匿名管道通过父子进程继承的关系,让父子进程看到同一份资源,进而进行通信;命名管道则是通过唯一的路径让两…...
SED命令
基本用法: sed命令具体应用: 1.删除第2-5行 nl regular_express.txt | sed 2d结果: 2.在第二行之后新增两行,分别为"drink tea…" 和"drink beer?" nl regular_express.txt | sed 2 a\ drink tea...\…...
洛谷 P6368 [COCI2006-2007#6] MAGIJA C语言
题目:https://www.luogu.com.cn/problem/P6368 题目背景 知名魔术师 AlDimi Kartimi 需要你帮助他来设计他扑克牌的背面图案。 题目描述 众所周知,扑克牌的背面是一个矩形,通过做两边的中垂线可以将矩形分成相等的四部分。 AlDimi Karti…...
TDesign:Picker 选择器
Picker 选择器 API文档地址 单列选择器用法 /// view onTap:(){TDPicker.showMultiPicker(context,data: [controller.coinList],title: ,rightTextStyle: TextStyle(color: AppColors.ColorMain),onConfirm: (selected) {controller.onTapCoin(selected);Navigator.of(contex…...
LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略
LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略 导读:这篇博文介绍了 Lares,一个由简单的 AI 代理驱动的智能家居助手模拟器,它展现出令人惊讶的解决问题能力。 >> 背景痛点:每天都有新的…...
实验3-实时数据流处理-Flink
1.前期准备 (1)Flink基础环境安装 参考文章: 利用docker-compose来搭建flink集群-CSDN博客 显示为这样就成功了 (2)把docker,docker-compose,kafka集群安装配置好 参考文章: …...
axios笔记
一、axios是什么 前端最流行的ajax请求库 二、json-server json-server可以帮助我们搭建http服务 为什么要搭建http服务? :是因为我们用axios的时候,需要向服务端发送请求 我们需要服务端这样一个角色,来与axios结合做实践 1.…...
python拆分Excel文件
按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文档样式如下: 结果:红色是按照Sheet名拆出的,蓝色和橙色是某个Sheet按照某列的不同值拆分的。 代码: # -*- coding: utf-8 -*- """ 拆分excel文件——按照…...
使用IntelliJ IDEA开发Gradle插件并发布到本地
博主所用软件版本为: IntelliJ IDEA 2024.1.4 (Community Edition) Android Studio Ladybug Feature Drop | 2024.2.2 Beta 1 1、制作gradle插件(IntelliJ IDEA 2024.1.4) 新建groovy工程,File–>New–>Project… 右键点…...
C# 通过smtp发送邮件(配置好了参数可以直接用)
可以直接用 using System; using System.Net; using System.Net.Mail;class EmailSender {// 发送邮件的函数,接收SMTP配置作为参数public static void SendEmail(string smtpServer, int smtpPort, string senderEmail, string senderPassword, string subject, s…...
【数据结构】栈和队列
目录 1.栈 1.1.栈的概念及结构 1.2.栈的实现 2.队列 2.1.队列的概念及结构 2.2.队列的实现 3.运用栈理解一道题 4.使用两个队列实现一个栈 1.栈 1.1.栈的概念及结构 首先,我们来了解一种新的数据结构——栈。栈是一种特殊的线性表,其只允许在固…...
使用 Spring Doc 为 Spring REST API 生成 OpenAPI 3.0 文档
Spring Boot 3 整合 springdoc-openapi 概述 springdoc-openapi 是一个用于自动生成 OpenAPI 3.0 文档的库,它支持与 Spring Boot 无缝集成。通过这个库,你可以轻松地生成和展示 RESTful API 的文档,并且可以使用 Swagger UI 或 ReDoc 进行…...
网络数据库安全和数据安全概述
1、数据安全的三要素 完整性,机密性,可用性 2、安全技术和措施 数据完整性技术、数据备份和恢复技术、数据加密技术、访问控制技术、用户管理和身份验证技术 3、数据库安全 数据库安全是指数据库的任何部分都不允许受到侵害,或未经授权的…...
STM32F10X与GD32工程创建区别
1.宏定义区别 GD32虽然与STM32F10X的管脚兼容,但是用keil创建工程时,GD32在选择芯片型号的时候就已经自己定义了宏。STM32F10x需要手动定义宏。在以下界面定义用到的单片机。 2.时钟区别。GD32最大时钟为120Mhz,所用的hal库里面的系统初始化会初始化时钟…...
cmakelist使用总结
支持能编译成在不同系统上运行程序的方法 我们代码就一份,但有时需要编译成arm32,有时需要编译成x86_64,或更多 1、首先先将代码定义一个名称: #将所有的源文件列为一个集合,集合名字叫做SRC_LISTS set(SRC_LISTS main.cpp A.cpp…...
【论文阅读】国际开源发展经验及其对我国开源创新体系建设的启示
作者:包云岗老师 包云岗老师是计算机体系结构方向的大牛,推动了体系结构方面的开源事业! 欢迎对本栏目感兴趣的人学习"一生一芯"~ 学习体会: 承接前文,唐志敏老师讲到已有的软硬件生态系统和开发成本制约了对新结构的探…...
React 初学者指南:从零开始构建第一个 React 应用
React 是一个用于构建用户界面的 JavaScript 库,它能够让我们高效地构建复杂的 UI。对于 React 初学者来说,最重要的就是理解它的基本概念以及如何开始使用它。本文将引导你从零开始构建你的第一个 React 应用 1.1. 安装 React 环境 首先,…...
力扣93题:复原 IP 地址
力扣93题:复原 IP 地址(C语言实现详解) 题目描述 给定一个只包含数字的字符串 s,复原它并返回所有可能的 IP 地址格式。 有效的 IP 地址需满足以下条件: IP 地址由四个整数(每个整数位于 0 到 255 之间…...
字符编码发展历史
文章目录 发展历史- ASCII- ISO-8859- Unicode- UTF系列- UTF-8- UTF-16- UTF-32 - 中文编码- GB2312- GBK- GB18030 - 其他编码 归纳总结 发展历史 计算机的基础是二进制数字(0和1)。虽然人类日常使用的是各种字符(如字母、数字、符号等&am…...
aws codepipeline + github + sonarqube + jenkins实践CI/CD
https://blog.csdn.net/u011564831/article/details/144007981文章浏览阅读1.2k次,点赞31次,收藏21次。本文使用 Jenkins 结合 CodeBuild, CodeDeploy 实现 Serverless 的 CI/CD 工作流,用于自动化发布已经部署 lambda 函数。在 AWS 海外区&a…...
KNN_识别图片数字
1.实验过程省略灰度化处理过程,用已经处理好的txt数据进行训练 3.jpg from PIL import Image def imgtotxt(imgfile,txtfile,size (32,32)):image_file Image.open(imgfile).resize(size,Image.LANCZOS).convert(L)width,height image_file.sizef open(txtfile,…...
python 清华pip镜像源报HTTP error 403
报错信息 ERROR: HTTP error 403 while getting https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/52/79/a64937a2185b91a96cc5406e3ea58120980c725543d047e112fb3084a972/fake_useragent-2.0.0-py3-none-any.whl (from https://mirrors.tuna.tsinghua.edu.cn/pypi/we…...
HTTP 网络技术学习:缓存;为什么有时候出现问题要清除浏览器缓存?客户端缓存和服务端缓存是什么。
目录: 问题的背景Http的缓存是什么客户端设置缓存,需要服务端允许?缓存分类:为什么会有客户端缓存和服务器端缓存?客户端缓存的参数设置,举例代码实现缓存 一、问题的背景 有时候网站出现问题࿰…...
极限科技三周年庆典:追求极致,共创未来科技新篇章
2024 年 12 月 3 日,一场盛大的庆典活动在香港 IFS 集团旗下长沙玛珂酒店璀璨启幕,极限科技迎来了其三周年的辉煌庆典。此次庆典不仅是对极限科技过往成就的回顾与庆祝,更是对未来科技梦想的展望并开始新的启航。 庆典现场,极限科…...
利用PHP和GD库实现图片拼接的方法
利用PHP和GD库实现图片拼接的方法主要涉及到加载图片资源、创建目标画布、将图片资源绘制到目标画布上,并最终输出或保存拼接后的图片。以下是实现图片拼接的基本步骤: 加载图片资源: 使用imagecreatefromjpeg()、imagecreatefrompng()或ima…...
SpringBoot自动配置底层核心源码
SpringBoot底层核心源码 一、工程创建二、进一步改造三、自动配置 探究SpringBoot的自动配置原理,我们可以自己写一个启动类的注解。 一、工程创建 首先创建一个工程,工程目录如下: 自定义一个启动函数: package org.springboo…...
故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab)
故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab) 目录 故障识别 | GADF-CNN-SSA-XGBoost数据分类预测/故障识别(Matlab)分类效果基本描述程序设计参考资料 分类效果 基本描述 格拉姆角场差(GADF&#…...
【VUE小型网站开发】优化通用配置 二
1. 引入 MyBatis Plus 1.1 添加依赖 <dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- My…...
基于阻塞队列的生产者消费者模型动画演示
一个基于阻塞队列的生产者消费者模型的动画演示: 这是打包好的程序。程序是用 QT 写的。 通过网盘分享的文件:CP模型.7z 链接: https://pan.baidu.com/s/1YjC7YiSqHGqdr6bbffaDWg?pwde6g5 提取码: e6g5 CP模型...
springSecurity认证流程
Spring Security 是spring家族中的一个安全管理框架。相比于另一个安全框架Shiro,它提供更丰富的功能和社区资源,但也较难上手。所以一般大项目用spring Security,小项目用Shiro。 一般web应用需要认证和授权,这也是spring Secur…...
vite5+vue3+Ts5 开源图片预览器上线
images-viewer-vue3:一款Vue3的轻量级图像查看器,它基于Flip动画技术,支持PC和h5移动网页预览照片,如果它是Vue3开发的产品。 npm开源地址:https://www.npmjs.com/package/images-viewer-vue3?activeTabreadme Flip 动画 < …...
Qt开发:元对象系统的介绍和使用
文章目录 概述元对象系统的概念和组成QObject 的详细介绍1.QObject 的主要特性信号与槽机制动态属性对象树(Object Trees)事件处理 2.QMetaObject的主要特性函数签名常用功能 概述 Qt本身并不是一种编程语言,它实质上是一个跨平台的C开发类库…...
.vscode文件中各个脚本需要修改的地方
NOTE: 此篇文章由VSCode编辑GCC for ARM交叉编译工具链Makefile构建OpenOCD调试(基于STM32的标准库)派生而来,对.vscode文件中各个脚本需要修改的地方作补充说明。 tasks.json 该json文件的主要作用:使用XX名称去执行…...
JavaScript模块化规范
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
第二篇:k8s工作流程
我们来看通过deployment部署pod的常规流程: kubectl向apiserver发送部署请求(例如使用 kubectl create -f deployment.yml)apiserver将 Deployment 持久化到etcd;etcd与apiserver进行一次http通信。controller manager通过watch a…...
什么是数据架构?
数据架构是如何使用数据的蓝图--它是数据和数据相关资源的高层结构,是整个组织的数据框架,包括模型、规则和标准。通过高效的数据架构,企业可以跟踪整个 IT 基础设施中数据的获取、移动、存储、安全性和可访问性。 数据架构总览 数据架构是…...
ChatGPT、Python和OpenCV支持下的空天地遥感数据识别与计算——从0基础到15个案例实战
在科技飞速发展的时代,遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究,空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而,对于许多专业人士而言,如何高效地处…...
微信小程序权限授权工具类
最近写微信小程序的时候需要在页面获取设备权限,又不想每个页面都写,就写了一个工具类方便管理 /*** 权限工具类用于获取授权* 权限工具类使用方法,注意调用时函数需要定义为异步函数 async* import PermissionUtils from "./permissio…...
CT中的2D、MPR、VR渲染、高级临床功能
CT中的2D、MPR、VR渲染 在CT(计算机断层扫描)中,2D、MPR(多平面重建)、VR(体积渲染)是不同的图像显示和处理技术,它们各自有独特的用途和优势。下面分别介绍这三种技术:…...
【MySQL】Windows下重启MySQL服务时,报错:服务名无效
1、问题描述 在终端中,停止、启动MySQL服务时报错:服务名无效 2、原因分析 1)权限不够 如果是权限不够,会提示:系统错误5,拒绝访问。 2)服务名错误 如果是服务名错误,会提示“…...
java枚举的基本用法
在 Java 中,枚举(enum)是一种特殊的类,用于定义一组常量。它可以使代码更具可读性和可维护性。枚举类型可以用于表示固定的、有限的值集合,比如星期几、季节、方向等。 以下是一些常见的枚举用法示例: 1.…...
Web网络安全
一. 浏览器系统安全方面,使用多进程方案,而js主线程运行在渲染进程中,渲染进程时运行在沙箱中的,没有对本地OS文件的直接读写权限,所以需要通过IPC与浏览器主线程通信,才可以获取cookie等信息,这…...
【分子材料发现】——GAP:催化过程中吸附构型的多模态语言和图学习(数据集处理详解)(二)
Multimodal Language and Graph Learning of Adsorption Configuration in Catalysis https://arxiv.org/abs/2401.07408Paper Data: https://doi.org/10.6084/m9.figshare.27208356.v2 1 Dataset CatBERTa训练的文本字符串输入来源于Open Catalyst 2020 (OC20…...
matlab Delaunay三角剖分提取平面点云的边界
目录 一、算法原理1、算法概述2、参考文献二、代码实现三、结果展示四、详细过程版一、算法原理 1、算法概述 Delaunay三角网在生成三角网过程中,以最近的三点形成三角形,且各三角形的边皆不相交,每条边都使用所在的三角形的顶点验算并记录相应的2个顶点坐标。整个验算过程…...
Spring07——AOP通知以及几个相关案例
切入点表达式 注意,不是参数,是参数类型 可以使用通配符描述切入点,快速描述 ■ *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的通配符出现 execution(public∗com.itheima.∗.UserServi…...
【AI工具】强大的AI编辑器Cursor详细使用教程
目录 一、下载安装与注册 二、内置模型与配置 三、常用快捷键 四、项目开发与问答 五、注意事项与技巧 参考资料 近日,由四名麻省理工学院(MIT)本科生共同创立的Anysphere公司宣布,其开发的AI代码编辑器Cursor在成立短短两年…...
CV工程师专用键盘开源项目硬件分析
1、前言 作为一个电子发烧友,你是否有遇到过这样的问题呢。当我们去查看函数定义的时候,需要敲击鼠标右键之后选择go to definition。更高级一些,我们使用键盘的快捷键来查看定义,这时候可以想象一下,你左手按下ALT&a…...
STM32标准固件库官网下载方法
Keil标准固件库官网下载方法 Keil中DFP.pack下载方法 打开keil官网 Keil 官网 www.keil.com 点击产品 点击“Products” 点击 “Arm Cortex-M” 下拉找到CMSIS-Packs 点击CMSIS-Pack index 搜索对应的MCU,我这里是STM32F4 注意搜索对应系列就好 点击下载...
数据库原理实验实验四 统计查询和组合查询
实验目的和要求加深对统计查询的理解,熟练使用聚簇函数。 实验环境SQL SERVER 2008 SQL Server Management Studio 20 实验内容与过程题目一: 学生(学号,年龄,性别,系名) 课程(课号,课名,学分,学时) 选课(学号,课号,成绩) 根据上面基本表的信息完成下列查…...
【电子通识】案例:USB Type-C USB 3.0线缆做直通连接器TX/RX反向
【电子通识】案例:连接器接线顺序评估为什么新人总是评估不到位?-CSDN博客这个文章的后续。最近在做一个工装项目,需要用到USB Type-C线缆做连接。 此前已经做好了线序规划,结果新人做成实物后发现有的USB Type-C线缆可用,有的不行。其中发现USB3.0的TX-RX信号与自己的板卡…...