Ortec974A EPICS IOC程序

1) 创建一个用户存放这个IOC程序结构的目录:

root@orangepi4-lts:/usr/local/EPICS/program# mkdir ortec974A
root@orangepi4-lts:/usr/local/EPICS/program# cd ortec974A/
root@orangepi4-lts:/usr/local/EPICS/program/ortec974A# ls

2)使用makeBaseApp.pl构建这个IOC程序架构:

root@orangepi4-lts:/usr/local/EPICS/program/ortec974A# makeBaseApp.pl -t ioc ortec974A
root@orangepi4-lts:/usr/local/EPICS/program/ortec974A# makeBaseApp.pl -i -t ioc ortec974A
Using target architecture linux-aarch64 (only one available)
The following applications are available:ortec974A
What application should the IOC(s) boot?
The default uses the IOC's name, even if not listed above.
Application name?
root@orangepi4-lts:/usr/local/EPICS/program/ortec974A# ls
configure  iocBoot  Makefile  ortec974AApp

3)编辑configure/RELEASE文件,添加这个IOC程序所需要的其它依赖模块:

...
SUPPORT=/usr/local/EPICS/synApps/support
ASYN=$(SUPPORT)/asyn
AUTOSAVE=$(SUPPORT)/autosave
CALC=$(SUPPORT)/calc
SCALER=$(SUPPORT)/scaler
...

4) 进入源文件目录ortec974AApp/src目录下:

a) 编写974A驱动程序源文件:

// drvOrtec974A.cpp
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <math.h>#include <asynPortDriver.h>
#include <asynOctetSyncIO.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <epicsTime.h>
#include <errlog.h>
#include <iocsh.h>
#include <epicsExport.h> /* Defines epicsExportSharedSymbols */#include "devScalerAsyn.h"#define MAX_CHANNELS 4#define timeOut 0.1
static const char *driverName= "Scaler974A";class Scaler974A:public asynPortDriver
{
public:Scaler974A(const char *portName, const char *serialPort, int serialAddr, int poll);virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);virtual asynStatus readInt32Array(asynUser *pasynUser,epicsInt32 *value, size_t nElements, size_t *nIn);virtual void report(FILE *fp, int details);void eventThread();private:int scalerReset;int scalerChannels;int scalerRead;int scalerReadSingle;int scalerPreset;int scalerArm;int scalerDone;double polltime;epicsEventId eventId;asynUser *pasynUserScaler;asynStatus sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen);
};static void eventThreadC(void *pPvt)
{Scaler974A *pScaler974A = (Scaler974A *)pPvt;pScaler974A->eventThread();
}Scaler974A::Scaler974A(const char *portName, const char *serialPort, int serialAddr, int poll):asynPortDriver(portName, MAX_CHANNELS,asynInt32Mask | asynInt32ArrayMask | asynDrvUserMask,asynInt32Mask,/* Should also be ASYN_CANBLOCK, but device support does not work with asynchronous devices */ASYN_MULTIDEVICE,1,0,0)
{int i;asynStatus status;static const char *functionName="Scaler974A";if (poll==0) poll=100;this->polltime=poll / 1000.;this->eventId = epicsEventCreate(epicsEventEmpty);status = pasynOctetSyncIO->connect(serialPort, serialAddr, &this->pasynUserScaler, NULL);if (status != asynSuccess) {asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,"%s:%s: error connecting to port %s address %d\n",driverName, functionName, serialPort, serialAddr);return;}createParam(SCALER_RESET_COMMAND_STRING,        asynParamInt32,     &this->scalerReset);createParam(SCALER_CHANNELS_COMMAND_STRING,     asynParamInt32,     &this->scalerChannels);createParam(SCALER_READ_COMMAND_STRING,         asynParamInt32Array,&this->scalerRead);createParam(SCALER_READ_SINGLE_COMMAND_STRING,  asynParamInt32,     &this->scalerReadSingle);createParam(SCALER_PRESET_COMMAND_STRING,       asynParamInt32,     &this->scalerPreset);createParam(SCALER_ARM_COMMAND_STRING,          asynParamInt32,     &this->scalerArm);createParam(SCALER_DONE_COMMAND_STRING,         asynParamInt32,     &this->scalerDone);setIntegerParam(scalerChannels, MAX_CHANNELS);setIntegerParam(scalerDone, 1);for (i=0; i<MAX_CHANNELS; i++) setIntegerParam(i, scalerReadSingle, 0);epicsThreadCreate("Scaler974A",epicsThreadPriorityMedium,epicsThreadGetStackSize(epicsThreadStackMedium),(EPICSTHREADFUNC)eventThreadC,this);
}asynStatus Scaler974A::sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen)
{size_t nWrite;asynStatus status;double timeout = 1.0;int eomReason;static const char *functionName = "sendCommand";/** asynStatus (*writeRead)(asynUser *pasynUser,const char *write_buffer, size_t write_buffer_len,char *read_buffer, size_t read_buffer_len,double timeout,size_t *nbytesOut, size_t *nbytesIn, int *eomReason);要写的字符串,要写的字符串长度,读出缓存,要读的字节数目,超时时间,实际写出的字节数,实际读入的字符数,结束原因asynStatus (*write)(asynUser *pasynUser,  char const *buffer, size_t buffer_len,double timeout,size_t *nbytesTransfered);asynStatus (*read)(asynUser *pasynUser, char *buffer, size_t buffer_len,double timeout, size_t *nbytesTransfered,int *eomReason);** */status = pasynOctetSyncIO->write(this->pasynUserScaler, command, strlen(command),  timeout, &nWrite);
//      printf("In sendCommand write status: %d,write content:%s,write length:%d\n", status, command, nWrite);if (status != asynSuccess) goto done;epicsThreadSleep(.1);status = pasynOctetSyncIO->read(this->pasynUserScaler,statusString, maxStatusLen, timeout, statusLen, &eomReason);
//      printf("In sendCommand read status: %d, statusString:%s\n", status, statusString);done:if (status != asynSuccess) {asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,"%s:%s: writing command %s, error=%s\n",driverName, functionName, command, this->pasynUserScaler->errorMessage);}return(status);
}asynStatus Scaler974A::writeInt32(asynUser *pasynUser, epicsInt32 value)
{int function = pasynUser->reason;char response[256];size_t responseLen;asynStatus status = asynSuccess;static const char *functionName="writeInt32";setIntegerParam(function, value);if(function==this->scalerReset){this->sendCommand("STOP\r", response, sizeof(response), &responseLen);//printf("STOP:%s\n", response);this->sendCommand("CLEAR_ALL\r", response, sizeof(response), &responseLen);//printf("CLEAR_ALL:%s\n", response);asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s:%s scalerReset\n",driverName, functionName);}else if(function==this->scalerArm){if(value !=0){/* Start counting */this->sendCommand("START\r", response, sizeof(response), &responseLen);
//          printf("START:%s\n", response);setIntegerParam(scalerDone, 0);epicsEventSignal(this->eventId);}else{/* Stop counting */status = this->sendCommand("STOP\r", response, sizeof(response), &responseLen);
//          printf("STOP:%s\n", response);setIntegerParam(scalerDone, 1);}asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s:%s scalerArm=%d\n", driverName, functionName,value);}else if(function==this->scalerPreset){int m,n;char newstr[25];n=(int)log10(double(value));m=(int)(value/pow(10.0,n));sprintf(newstr, "SET_COUNT_PRESET %d,%d\r", m, n);this->sendCommand(newstr, response, sizeof(response), &responseLen);
//      printf("SET_COUNT_PRESET:%s\n", response);asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s;%s scalerPreset channel", driverName, functionName);}else{asynPrint(pasynUser,ASYN_TRACE_ERROR,"%s:%s got illegal function %d\n", driverName, functionName, function);}callParamCallbacks();return(status);
}asynStatus Scaler974A::readInt32Array(asynUser *pasynUser, epicsInt32 *value, size_t maxChannel, size_t *nIn)
{static const char *functionName="readInt32Array";int function = pasynUser->reason;int temp;int i;if (maxChannel > MAX_CHANNELS) maxChannel = MAX_CHANNELS;*nIn = maxChannel;if (function==scalerRead){for (i=0; i<(int)maxChannel; i++){getIntegerParam(i, scalerReadSingle, &temp);value[i] = temp;}asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,"%s:%s: value=%d %d %d %d\n",driverName, functionName, value[0], value[1], value[2], value[3]);} else {asynPrint(pasynUser,ASYN_TRACE_ERROR,"%s:%s got illegal function %d\n", driverName, functionName,  function);return(asynError);}return(asynSuccess);
}void Scaler974A::report(FILE *fp, int details)
{asynPortDriver::report(fp, details);
}void Scaler974A::eventThread()
{int done, presetCount;char response[100], statusString[256];size_t responseLen, statusLen;int counts[MAX_CHANNELS];int i;asynStatus status;static const char *functionName="eventThread";while(1){epicsEventMustWait(this->eventId);while(1){status = this->sendCommand("SHOW_COUNTS\r", statusString, sizeof(statusString), &statusLen);sscanf(statusString, "%d;%d;%d;%d;",&counts[0], &counts[1], &counts[2], &counts[3]);
//          printf("%d;%d;%d;%d\n", counts[0],counts[1],counts[2],counts[3]);asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"%s:%s status=%d, counts=%d %d %d %d\n",driverName, functionName, status, counts[0], counts[1], counts[2], counts[3]);this->lock();/* Get value of done in case scaler was stopped by scalerArm(0) */getIntegerParam(scalerDone, &done);getIntegerParam(scalerPreset, &presetCount);if (!done && (counts[0] >= presetCount)) done = 1;setIntegerParam(scalerDone, done);for (i=0; i<MAX_CHANNELS; i++) {setIntegerParam(i, scalerReadSingle, counts[i]);callParamCallbacks(i, i);}this->unlock();if (done) break;epicsThreadSleep(this->polltime/1000.0);}}
}extern "C" int initScaler974A(const char *portName, const char *serialPort, int serialAddr, int poll)
{new Scaler974A(portName, serialPort, serialAddr, poll);return(asynSuccess);
}/* iocsh function */
static const iocshArg initArg0 = {"Port Name", iocshArgString};
static const iocshArg initArg1 = {"IPPort", iocshArgString};
static const iocshArg initArg2 = {"Addr", iocshArgString};
static const iocshArg initArg3 = {"Poll", iocshArgInt};
static const iocshArg *const initArgs[] = {&initArg0,&initArg1,&initArg2,&initArg3};
static const iocshFuncDef initFuncDef = {"initScaler974A",4, initArgs};
static void initCallFunc(const iocshArgBuf *args)
{initScaler974A(args[0].sval, args[1].sval, args[2].ival, args[3].ival);
}void Scaler974ARegister(void)
{iocshRegister(&initFuncDef,initCallFunc);
}extern "C" {
epicsExportRegistrar(Scaler974ARegister);
}

b) 添加一个dbd文件ortec974ASupport.dbd:

registrar(Scaler974ARegister)

c) 修改同一目录下Makefile文件,指定编译中需要包含的库文件和源文件:

TOP=../..include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================#=============================
# Build the IOC applicationPROD_IOC = ortec974A
# ortec974A.dbd will be created and installed
DBD += ortec974A.dbd# ortec974A.dbd will be made up from these files:
ortec974A_DBD += base.dbd
ortec974A_DBD += ortec974ASupport.dbd# Include dbd files from all support applications:
#ortec974A_DBD += xxx.dbdortec974A_DBD += drvAsynIPPort.dbd
ortec974A_DBD += asyn.dbd
ortec974A_DBD += scalerSupport.dbd
ortec974A_DBD += calcSupport.dbd
ortec974A_DBD += asSupport.dbd# Include dbd files from all support applications:
#ortec974A_DBD += xxx.dbd# Add all the support libraries needed by this IOC
ortec974A_LIBS += asyn
ortec974A_LIBS += scaler
ortec974A_LIBS += calc
ortec974A_LIBS += autosave# Add all the support libraries needed by this IOC
#ortec974A_LIBS += xxxortec974A_SRCS += drvOrtec974A.cpp
# ortec974A_registerRecordDeviceDriver.cpp derives from ortec974A.dbd
ortec974A_SRCS += ortec974A_registerRecordDeviceDriver.cpp# Build the main IOC entry point on workstation OSs.
ortec974A_SRCS_DEFAULT += ortec974AMain.cpp
ortec974A_SRCS_vxWorks += -nil-# Add support from base/src/vxWorks if needed
#ortec974A_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary# Finally link to the EPICS Base libraries
ortec974A_LIBS += $(EPICS_BASE_IOC_LIBS)#===========================include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

5) 进入ortec974AApp/Db目录,编写一个用于自动保存的文件scaler4_settings.req:

$(P)$(S).TP
$(P)$(S).TP1
$(P)$(S).CONT
$(P)$(S).DLY1
$(P)$(S).RAT1
$(P)$(S).PREC
$(P)$(S).FREQ
$(P)$(S).RATE
$(P)$(S).DLY
$(P)$(S).COUT
file "scaler_channelN_settings.req", P=$(P), S=$(S), Ch=1
file "scaler_channelN_settings.req", P=$(P), S=$(S), Ch=2
file "scaler_channelN_settings.req", P=$(P), S=$(S), Ch=3
file "scaler_channelN_settings.req", P=$(P), S=$(S), Ch=4

在同一目录下的Makefile中添加一行:DB += scaler4_settings.req

6) 退出到这个IOC的顶层目录,执行make进行程序编译。

7)进入到启动目录iocBoot/iocortec974A,创建两个目录:

root@orangepi4-lts:/usr/local/EPICS/program/ortec974A/iocBoot/iocortec974A# mkdir -p req/ortec974A
root@orangepi4-lts:/usr/local/EPICS/program/ortec974A/iocBoot/iocortec974A# mkdir -p autosave/ortec974A

在req/ortec974A下编写一个用于自动保存的文件auto_settings.req,内容如下:

file scaler4_settings.req  P=$(P) S=$(S)

编写启动脚本:

#!../../bin/linux-aarch64/ortec974A#- You may have to change ortec974A to something else
#- everywhere it appears in this file< envPathscd "${TOP}"## Register all support components
dbLoadDatabase "dbd/ortec974A.dbd"
ortec974A_registerRecordDeviceDriver pdbbasedrvAsynIPPortConfigure("ortec974A", "192.168.3.30:4001", 0, 0 ,1)initScaler974A("tcportec974A","ortec974A",0,10)
dbLoadRecords("${SCALER}/db/scaler.db", "P=Ortec974A:,S=Scaler1,OUT=@asyn(tcportec974A 0 0),DTYP=Asyn Scaler,FREQ=10,TP=1,TP1=0.5,PR1=1,CONT=1")set_requestfile_path("$(TOP)/db")
set_requestfile_path("$(SCALER)/db")
set_requestfile_path("$(TOP)/iocBoot/$(IOC)/req/ortec974A")# 通过调用set_savefile_path函数指定你想要.sav文件被写到哪个目录中。
set_savefile_path("$(TOP)/iocBoot/$(IOC)/autosave/ortec974A")# 使用set_pass<N>_restoreFile()函数
# 指定哪些save文件要在记录初始化前(pass 0)前被恢复,以及哪些save文件在记录初始化后(pass 1)被恢复
set_pass1_restoreFile("auto_settings.sav")save_restoreSet_numSeqFiles(3)
save_restoreSet_SeqPeriodInSeconds(600)
save_restoreSet_RetrySeconds(60)
save_restoreSet_CAReconnect(1)
save_restoreSet_CallbackTimeout(-1)dbLoadRecords("$(ASYN)/db/asynRecord.db","P=Ortec974A:Scaler1:,R=Asyn,PORT=ortec974A,ADDR=0,IMAX=100,OMAX=100")cd "${TOP}/iocBoot/${IOC}"
iocInitcreate_monitor_set("auto_settings.req",5,"P=Ortec974A:,S=Scaler1")

8) 用以上启动脚本启动这个IOC程序:

root@orangepi4-lts:/usr/local/EPICS/program/ortec974A/iocBoot/iocortec974A# ../../bin/linux-aarch64/ortec974A st.cmd

9)查看这个IOC加载的记录:

epics> dbl
Ortec974A:Scaler1:Asyn
Ortec974A:Scaler1

10) 用CSS编写操作客户端:

11) 在97A的3号输入端口接入一个3MHz的TTL信号,将计数时间设置为1.0秒,点击Count按钮,进行1秒钟计数:

通道3能够读出计数器的正确计数值。 

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

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

相关文章

mediapipe 训练自有图像数据分类

参考&#xff1a; https://developers.google.com/mediapipe/solutions/customization/image_classifier https://colab.research.google.com/github/googlesamples/mediapipe/blob/main/examples/customization/image_classifier.ipynb#scrollToplvO-YmcQn5g 安装&#xff1a…

CSS中的栅格布局

CSS中的栅格布局 在写前端项目的时候&#xff0c;我之前一直习惯使用flex布局&#xff0c;flex布局写起来比较随心&#xff0c;几乎可以实现任意形式的页面布局。不过自从B占看到某位大佬的grid布局后&#xff0c;发现布局居然还可以这么玩&#xff0c;正好自己在写一个vue3的…

【大数据Hive】hive 表数据优化使用详解

目录 一、前言 二、hive 常用数据存储格式 2.1 文件格式-TextFile 2.1.1 操作演示 2.2 文件格式 - SequenceFile 2.2.1 操作演示 2.3 文件格式 -Parquet 2.3.1 Parquet简介 2.3.2 操作演示 2.4 文件格式-ORC 2.4.1 ORC介绍 2.4.2 操作演示 三、hive 存储数据压缩优…

在线主动学习算法评估策略:prequential evaluation procedure

在线主动学习算法评估策略&#xff1a;prequential evaluation procedure 在在线主动学习领域(Online Active Learning)&#xff0c;对在线主动学习算法的评估策略有多种方法&#xff0c;而现如今常用的方法是prequential evaluation procedure(出自论文《High density-focuse…

c++二叉树遍历

参考文献 数据结构c语言版&#xff0c;严蔚敏_吴伟民著。 二叉树 中序遍历代码实现 #include<vector> #include<iostream> using namespace std;//Definition for a binary tree node. struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode() : v…

腾讯云轻量应用镜像、系统镜像、Docker基础镜像、自定义镜像和共享镜像介绍

腾讯云轻量应用服务器镜像类型分为应用镜像、系统镜像、Docker基础镜像、自定义镜像和共享镜像&#xff0c;腾讯云百科txybk.com来详细说下不同镜像类型说明和详细介绍&#xff1a; 轻量应用服务器镜像类型说明 腾讯云轻量应用服务器 应用镜像&#xff1a;独有的应用镜像除了包…

Mysql设置了更新时间自动更新,指定更新部分sql时不进行时间更新

现象&#xff1a; 因为字段设置了自动更新&#xff0c;所以sql语句一进行修改此字段就会自动更新时间&#xff0c;但是呢我们的有部分定时任务是半夜执行&#xff0c;并且不能让这个任务修改到数据的更新时间 解决&#xff1a; <update id"updateCreative">ALT…

GoLand GC(垃圾回收机制)简介及调优

GC(Garbage Collector)垃圾回收机制及调优 简单理解GC机制 其实gc机制特别容易理解&#xff0c;就是物理内存的自动清理工。我们可以把内存想象成一个房间&#xff0c;程序运行时会在这个房间里存放各种东西&#xff0c;但有时候我们会忘记把不再需要的东西拿出去&#xff0c…

HubSpot CRM是什么?如何添加、使用呢?

HubSpot CRM是一款强大的客户关系管理工具&#xff0c;它不仅简化了销售和市场营销过程&#xff0c;还提供了多种功能&#xff0c;有助于增强客户互动、提高销售效率和提供更多的洞察信息。 今天运营坛将带领大家深入了解HubSpot CRM&#xff0c;涵盖了它的定义、使用流程、添…

基于STM32闭环步进电机控制系统设计

**单片机设计介绍&#xff0c;1654基于STM32闭环步进电机控制系统设计&#xff08;仿真&#xff0c;程序&#xff0c;说明&#xff09; 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序文档 六、 文章目录 一 概要 基于STM32的闭环步进电机控制系统设计是…

Java版 招投标系统简介 招投标系统源码 java招投标系统 招投标系统功能设计

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

安卓逆向之雷电模拟器中控

一, 雷电模拟器 安装使用 官方地址: https://www.ldmnq.com ,官方论坛 https://www.ldmnq.com/forum/ . 有一个多开管理器,还有就是设置手机的参数比较关键。 二,雷电模拟器开启面具,安装LSP。 设置root 权限。

【数据结构实战项目】C语言实现数据结构顺序表万字详解(附完整运行代码)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 一.了解项目功能 在本次项目中我们的目标是实现一个顺序表: 该顺序表使用动态内存分配,可以用来存储任意数量的同类型数据. 顺序表需要包含三个要素:存储数据的数组arr,顺序表…

Python程序设计期末复习笔记

文章目录 一、数据存储1.1 倒计时1.2 os库1.3 字符串操作1.4 文件操作1.5 列表操作1.6 元组1.7 字典 二、文本处理及可视化2.1 jieba分词2.2 集合操作2.3 pdf文件读取2.4 参数传递2.5 变量作用域 三、数据处理分析3.1 Sumpy3.2 Matplotlib3.3 Numpy 四、Pandas4.1 索引操作4.2 …

技术视角下的跑腿小程序开发:关键挑战和解决方案

跑腿小程序作为连接服务提供者和用户的桥梁&#xff0c;面临着诸多技术挑战。本文将聚焦于技术层面的关键挑战&#xff0c;并提供解决方案&#xff0c;以帮助开发者应对技术上的复杂问题。 1. 实时性与性能挑战 挑战&#xff1a; 跑腿小程序需要实时地匹配订单、更新状态和提…

40基于MATLAB,使用模板匹配法实现车牌的识别。

基于MATLAB&#xff0c;使用模板匹配法实现车牌的识别。具体包括将原图灰度化&#xff0c;边缘检测&#xff0c;腐蚀操作&#xff0c;车牌区域定位&#xff0c;车牌区域矫正&#xff0c;二值化&#xff0c;均值滤波&#xff0c;切割&#xff0c;字符匹配&#xff0c;最终显示车…

小程序request请求封装

以上为本人的项目目录 1.首先在utils中创建request.js文件封装request请求&#xff0c;此封装带上了token&#xff0c;每次请求都会自带token&#xff0c;需要你从后端获取后利用wx.setStorageSync(token,返回的token),不使用的话就是空。 直接复制即可&#xff0c;需要改一下…

(三)库存超卖案例实战——使用redis分布式锁解决“超卖”问题

前言 在上一节内容中我们介绍了如何使用mysql数据库的传统锁&#xff08;行锁、乐观锁、悲观锁&#xff09;来解决并发访问导致的“超卖问题”。虽然mysql的传统锁能够很好的解决并发访问的问题&#xff0c;但是从性能上来讲&#xff0c;mysql的表现似乎并不那么优秀&#xff…

vue3后台管理系统之跨域代理

vite.config.js中 server: {port: 5002,host: true, //0.0.0.0open: false,strictPort: true,proxy: {// 请求前缀/api&#xff0c;只有加了/api前缀的请求才会走代理(前端自定义)/api: {target: http://127.0.0.1:8000,// 获取服务器地址的设置changeOrigin: true,// 路径重写…

AMD HIP并行编程语言及其矢量相加实例——一文带你快速入门

✍️写在前面&#xff1a;随着计算的应用场景变得日益复杂多样&#xff0c;为了跟上人工智能算法对算力的需求&#xff0c;GPU硬件架构快速走向多样化&#xff0c;GPU生产厂家众多&#xff0c;且在商业和市场等因素的影响下&#xff0c;GPU通用计算编程模型也日益多元化。因此&…