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

asyn queueRequest使用实例

 使用queueRequest读写端口驱动的示例,驱动驱动程序使用一个基于asyn实现了asynCommon和asynOctet的驱动程序-CSDN博客中编写的驱动程序,本程序的C代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>#include <cantProceed.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsStdio.h>
#include <epicsAssert.h>
#include <asynDriver.h>
#include <asynOctet.h>
#include <iocsh.h>
#include <registryFunction.h>
#include <epicsExport.h>#define BUFFSIZE 80
/* 定义一个结构体:事件ID在驱动程序可以阻塞时,才有作用,一个asynOcte接口,驱动专用数据以及数据缓存*/
typedef struct MyData{epicsEventId     done;asynOctet       *pasynOctet;void            *drvPvt;char            buffer[BUFFSIZE];int             id;
}MyData;static void timeoutCallback(asynUser *pasynUser){printf("in timeoutCallback\n");
}/* queueRequest的回调函数,原型:typedef void (*userCallback)(asynUser *pasynUser);  */
static void queueCallback(asynUser *pasynUser)
{MyData      *pmydata    = pasynUser->userPvt;       //用户数据区asynOctet   *pasynOctet = pmydata->pasynOctet;      //asynOcte接口void        *pdrvPvt    = pmydata->drvPvt;          //驱动程序专用asynStatus  status;size_t      writeBytes, readBytes;int         eomReason;asynPrint(pasynUser,    ASYN_TRACE_FLOW,    "queueCallback entered for Data ID: %d\n", pmydata->id);//将用户传入的数据写入设备printf("Start to  Write '%s' to device\n", pmydata->buffer);/*原型:asynStatus (*write)(void *drvPvt,asynUser *pasynUser,const char *data,size_t numchars,size_t *nbytesTransfered);*/status = pasynOctet->write(pdrvPvt, pasynUser, pmydata->buffer, strlen(pmydata->buffer), &writeBytes);if (status != asynSuccess){asynPrint(pasynUser, ASYN_TRACE_ERROR, "queueCallback write failed:%s\n"  ,pasynUser->errorMessage);}else{asynPrintIO(pasynUser, ASYN_TRACEIO_DEVICE, pmydata->buffer, strlen(pmydata->buffer),"queueCallback write sent %lu bytes\n", (unsigned long)writeBytes);printf("finished writing!\n");}// 清空用户缓存中的数据,为了验证回读的数据memset(pmydata->buffer, 0, BUFFSIZE);//  从设备读取数据到用户传入的缓存//  asynStatus (*read)(void *drvPvt,asynUser *pasynUser,//               char *data,size_t maxchars,size_t *nbytesTransfered,//               int *eomReason);printf("Start to read from device\n");status = pasynOctet->read(pdrvPvt, pasynUser, pmydata->buffer, BUFFSIZE, &readBytes, &eomReason);if (status != asynSuccess){asynPrint(pasynUser, ASYN_TRACE_ERROR, "queueCallback read failed %s\n",  pasynUser->errorMessage);}else{asynPrintIO(pasynUser, ASYN_TRACEIO_DEVICE, pmydata->buffer, BUFFSIZE, "queueCallback read returned: retlen %lu eomReason 0x%x data %s\n",(unsigned long)readBytes, eomReason, pmydata->buffer);printf("Finished reading,content: '%s'\n", pmydata->buffer);}// 如果驱动程序可阻塞,需要对阻塞线程发送信号,表示数据已经处理完成if (pmydata->done){epicsEventSignal(pmydata->done);}else{pasynManager->memFree(pasynUser->userPvt, sizeof(MyData));}status = pasynManager->freeAsynUser(pasynUser);if (status){asynPrint(pasynUser, ASYN_TRACE_ERROR, "freeAsynUser failed %s\n", pasynUser->errorMessage);}
}static void asynQueueRequest(const char *port, int addr, const char *message)
{MyData                  *pmyData1,*pmyData2;asynUser                *pasynUser, *pasynUserDuplicate;asynStatus              status;asynInterface           *pasynInterface;int                     canBlock;// 分配两个结构体,并且初始化这两个结构体pmyData1 = (MyData *)pasynManager->memMalloc(sizeof(MyData));pmyData2 = (MyData *)pasynManager->memMalloc(sizeof(MyData));memset(pmyData1, 0, sizeof(MyData));memset(pmyData2, 0, sizeof(MyData));// 字符串传入第一个结构体缓存中strcpy(pmyData1->buffer,  message);pmyData1->id = 1;// 使用queueRequest需要创建asynUser结构体,并且放入回调程序pasynUser = pasynManager->createAsynUser(queueCallback,  NULL);pasynUser->timeout = 1.0;pasynUser->userPvt = pmyData1;// 通过port和addr连接驱动程序和使用的asynUserstatus = pasynManager->connectDevice(pasynUser, port, addr);if (status != asynSuccess){printf("can't connect to port:%s\n", pasynUser->errorMessage);return;}// 根据接口名称,查找对应的接口/*typedef struct asynInterface{const char *interfaceType;void *pinterface;void *drvPvt;}asynInterface;*/pasynInterface = pasynManager->findInterface(pasynUser, asynOctetType, 1);if (!pasynInterface){printf("this driver do not support interface: %s\n", asynOctetType);return;}// 获取asynOctet接口起始位置pmyData1->pasynOctet = (asynOctet *)pasynInterface->pinterface;// 获取驱动程序专用数据pmyData1->drvPvt = pasynInterface->drvPvt;// 结构体复制*pmyData2 = *pmyData1;pmyData2->id = 2;strcat(pmyData2->buffer, " repeated!");// 获取驱动程序是否可以阻塞canBlock = 0;pasynManager->canBlock(pasynUser, &canBlock);if (canBlock) pmyData2->done = epicsEventCreate(epicsEventEmpty);pasynUserDuplicate = pasynManager->duplicateAsynUser(pasynUser, queueCallback, NULL);pasynUserDuplicate->userPvt = pmyData2;// 排队两个请求status = pasynManager->queueRequest(pasynUser, asynQueuePriorityLow, 0.0);if (status){asynPrint(pasynUser, ASYN_TRACE_ERROR, "First queueRequest failed %s\n", pasynUser->errorMessage);}status = pasynManager->queueRequest(pasynUserDuplicate, asynQueuePriorityLow,  0.0);if (status){asynPrint(pasynUser, ASYN_TRACE_ERROR, "Second queueRequest failed %s\n", pasynUser->errorMessage);}if (canBlock){// 读写端口驱动的操作是在另外一个线程中进行,等待那个线程发送数据操作结束的事件epicsEventWait(pmyData2->done); // 数据2已经处理好了epicsEventDestroy(pmyData2->done);pasynManager->memFree(pmyData2, sizeof(MyData));}
}/* 向IOC shell注册 */
static const iocshArg asynQueueRequestArg0 = {"port", iocshArgString};
static const iocshArg asynQueueRequestArg1 = {"addr", iocshArgInt};
static const iocshArg asynQueueRequestArg2 = {"message", iocshArgString};
static const iocshArg *const asynQueueRequestArgs[] = {&asynQueueRequestArg0, &asynQueueRequestArg1, &asynQueueRequestArg2
};
static const iocshFuncDef asynQueueRequestDef = {"asynQueueRequest", 3, asynQueueRequestArgs};static void asynQueueRequestCall(const iocshArgBuf * args)
{asynQueueRequest(args[0].sval, args[1].ival, args[2].sval);
}static void asynQueueRequestRegister(void)
{static int firstTime = 1;if (!firstTime) return;firstTime = 0;iocshRegister(&asynQueueRequestDef, asynQueueRequestCall);
}epicsExportRegistrar(asynQueueRequestRegister);

添加一个文件asynQueueRequest.dbd,内容如下:

registrar("asynQueueRequestRegister")

更改同一路径下的Makefile文件:

...
echoDriver_DBD += asynQueueRequest.dbdechoDriver_SRCS += asynQueueRequest.c
...

编译以上文件,编写启动脚本:

...
# 可以阻塞驱动程序,模拟单设备端口
echoDriverInit("SIM",  0.1, 0, 0)
...

启动IOC,测试以上asynQueueRequest命令读写为名SIM的端口驱动:

可以看出客户端进行了两次写入-回读操作。

epics> asynQueueRequest "SIM" 0 "hello world"
Start to  Write 'hello world' to device
finished writing!
Start to read from device
Finished reading,content: 'hello world'
Start to  Write 'hello world repeated!' to device
finished writing!
Start to read from device
Finished reading,content: 'hello world repeated!'

使用asynOctet接口的窗口进行测试,直接运行Read一次,可以从Input ASCII文本框中读取了驱动程序回传的数据,与最后一次写入驱动的数据相同。

相关文章:

asyn queueRequest使用实例

使用queueRequest读写端口驱动的示例&#xff0c;驱动驱动程序使用一个基于asyn实现了asynCommon和asynOctet的驱动程序-CSDN博客中编写的驱动程序&#xff0c;本程序的C代码如下&#xff1a; #include <stdlib.h> #include <stdio.h> #include <string.h>#…...

关于jmeter设置为中文问题之后无法保存设置的若干问题

1、jemeter如何设置中文模式 Options--->Choose Language--->Chinese(Simplifies), 如此设置后就可显示中文模式(缺点&#xff1a;下次打开还是英文)&#xff1b;如下图所示&#xff1a; 操作完成之后&#xff1a; 但是下次重启之后依旧是英文&#xff1b; 2、在jmeter.…...

基于FPGA的信号发生器verilog实现,可以输出方波,脉冲波,m序列以及正弦波,可调整输出信号频率

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 输出方波 输出脉冲波 输出m随机序列 输出正弦波 2.算法运行软件版本 vivado2019.2 3.部分核心程序 &#xff08;完整…...

背景全文及翻译

背景 Oracle数据向MySQL同步&#xff0c;没有最新数据&#xff0c;于是在plsql手敲SQL筛选最新数据时&#xff0c;执行报错。 问题描述 通过日期字段筛选最近的数据&#xff0c;我用了类似这样的语句&#xff1a; SELECT * FROM orders WHERE order_date > 2022/01/01;我…...

JAVA地狱级笑话

为什么Java开发者总是不怕黑暗&#xff1f; 因为他们总是有null指针来照亮路。 Java程序员最讨厌的音乐是什么&#xff1f; Garbage Collection旋律&#xff0c;节奏总是让他们烦躁。 为什么Java中的HashMap很擅长社交&#xff1f; 因为它总是能快速找到key对应的朋友。 Java开…...

宝塔PHP8.1安装fileinfo拓展失败解决办法

在宝塔面板中安装PHP8.1后&#xff0c;安装fileinfo扩展一直安装不上&#xff0c;查看日志有报错&#xff0c;于是手动来安装也报错。 宝塔报错&#xff1a; 手动命令行编译安装同&#xff0c;也有报错 cd /www/server/php/81/src/ext/fileinfo/ make distclean ./configure …...

Python 魔术方法

在Python中&#xff0c;魔术方法&#xff08;Magic Methods&#xff09;或称为双下划线方法&#xff08;Dunder Methods&#xff09;&#xff0c;是一类具有特殊用途的方法&#xff0c;其名称前后都带有两个下划线&#xff08;如 __init__、__str__ 等&#xff09;。这些方法定…...

03 go语言(golang) - fmt包基本类型

fmt包 在Go语言中&#xff0c;fmt 包是一个非常重要且广泛使用的标准库包&#xff0c;它提供了格式化I/O&#xff08;输入/输出&#xff09;功能&#xff0c;类似于C语言中的 printf 和 scanf。通过这个包&#xff0c;你可以读取输入并将数据格式化输出到标准输出或其他写入器…...

Docker本地镜像发布到阿里云镜像服务的简易指南

1 阿里云容器镜像服务 阿里云容器镜像服务&#xff08;Alibaba Cloud Container Registry&#xff0c;简称ACR&#xff09;是一个为容器镜像、Helm Chart等云原生资产提供安全托管及高效分发的平台。它支持多架构容器镜像&#xff0c;包括Linux、Windows、ARM等&#xff0c;以…...

大数据学习---快速了解clickhouse数据库

ClickHouse数据库介绍 ClickHouse是一款由Yandex开发的列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;适用于在线分析处理&#xff08;OLAP&#xff09;场景。它具有高性能、可扩展性、实时更新等特点&#xff0c;适用于处理大规模数据。 特点 列式存储&#x…...

哪些方法可以缓解面试紧张?

面试紧张是许多人在面对重要职业机会时的一种常见情绪。虽然一定程度的紧张可能激发人的潜能&#xff0c;但过度的紧张则可能影响到面试表现。为了缓解面试紧张&#xff0c;以下是一些有效的方法&#xff1a; 1.充分准备&#xff1a; 深入了解公司背景、职位要求以及公司文化…...

即时通讯未读消息计数

单聊未读消息计数 未读消息的计数&#xff0c;分为两个部分&#xff1a;增加和减少 其中&#xff0c;未读消息计数的增加&#xff0c;是由数据库&#xff08;redis&#xff09;在写入消息的同时&#xff0c;增加对应接收方的未读消息计数 在线 用户在线时&#xff0c;客户端…...

在Openshift(K8S)上通过EMQX Operator部署Emqx集群

EMQX Operator 简介 EMQX Broker/Enterprise 是一个云原生的 MQTT 消息中间件。 我们提供了 EMQX Kubernetes Operator 来帮助您在 Kubernetes 的环境上快速创建和管理 EMQX Broker/Enterprise 集群。 它可以大大简化部署和管理 EMQX 集群的流程&#xff0c;对于管理和配置的知…...

Python酷玩之旅_数据分析入门(matplotlib)

导览 前言matplotlib入门1. 简介1.1 Pairwise data1.2 Statistical distributions1.3 Gridded data1.4 Irregularly gridded data1.5 3D and volumetric data 2. 实践2.1 安装2.2 示例 结语系列回顾 前言 翻看日历&#xff0c;今年的日子已划到了2024年10月19日&#xff0c;今天…...

uiautomatorviewer安卓9以上正常使用及问题处理

一、安卓9以上使用uiautomatorviewer问题现象 打开Unexpected error while obtaining UI hierarchy 问题详情 Unexpected error while obtaining UI hierarchy java.lang.reflect.InvocationTargetException 二、问题处理 需要的是替换对应D:\software\android-sdk-windows…...

Go语言gRPC快速入门

文章目录 前言gRPC是什么Go语言的gRPC技术栈准备工作接口定义代码生成服务端代码编写客户端代码编写效果演示完整代码链接最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;这篇博客想帮助初学者能够快速入门gRPC&#xff0c;希望能够为你节省宝贵的时间&#xff0c;让时间…...

Golang | Leetcode Golang题解之第479题最大回文数乘积

题目&#xff1a; 题解&#xff1a; func largestPalindrome(n int) int {if n 1 {return 9}upper : int(math.Pow10(n)) - 1for left : upper; ; left-- { // 枚举回文数的左半部分p : leftfor x : left; x > 0; x / 10 {p p*10 x%10 // 翻转左半部分到其自身末尾&…...

UDP协议讲解

预备知识&#xff1a; 端口号port&#xff1a; 我们在正常网络通信时&#xff0c;实际上是进程在互相通信。 我们所有的网络通信的行为&#xff0c;本质上都是进程间通信。 对双方而言&#xff0c;1.先保证数据能到达自己的机器 ip解决 2.找到指定的进程 端口号 ip地址用来…...

交叉注意力融合时域、频域特征的FFT + CNN -BiLSTM-CrossAttention轴承故障识别模型

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Transformer轴承故障一维信号分类(三)-CSDN博客 三十多个开源…...

CSDN Markdown 编辑器语法大全

Markdown 是一种轻量级标记语言&#xff0c;它以简洁、易读易写的特点&#xff0c;被广泛应用于技术文档、博客文章、笔记等领域。CSDN 的 Markdown 编辑器为用户提供了丰富的功能&#xff0c;让用户能够轻松地创建格式规范、内容丰富的文档。以下是一份详细的 CSDN Markdown 编…...

TCP/IP 协议【四次挥手】简要说明

四次挥手是为了确保数据的完整性和可靠性&#xff0c;解决的主要问题是双方在断开连接时&#xff0c;可能还有未完成传输的数据或者未被接收的数据。 具体来说&#xff0c;四次挥手解决的问题是&#xff1a; 第一次挥手&#xff08;发送方向接收方发送FIN包&#xff09;&#…...

第11篇:网络安全协议

目录 引言 11.1 安全套接字层&#xff08;SSL&#xff09;和传输层安全&#xff08;TLS&#xff09;协议 11.1.1 SSL/TLS 的工作原理 11.1.2 SSL/TLS 的应用场景 11.2 虚拟专用网&#xff08;VPN&#xff09;和 IP 安全协议&#xff08;IPSec&#xff09; 11.2.1 VPN 的工…...

ES-入门-javaApi-文档-新增-删除

新增指定索引的文档数据的代码如下&#xff1a; package com.atgulgu.es.test;import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpHost; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRe…...

【视频生成大模型】 视频生成大模型 THUDM/CogVideoX-2b

【视频生成大模型】 视频生成大模型 THUDM/CogVideoX-2b CogVideoX-2b 模型介绍发布时间模型测试生成的demo视频生成视频限制 运行环境安装运行模型下载开源协议参考 CogVideoX-2b 模型介绍 CogVideoX是 清影 同源的开源版本视频生成模型。 基础信息&#xff1a; 发布时间 2…...

【MR开发】在Pico设备上接入MRTK3(三)——在Unity中运行MRTK示例

在前面的文档中&#xff0c;介绍了如何在Unity工程中配置号MRTK和Pico SDK 【MR开发】在Pico设备上接入MRTK3&#xff08;一&#xff09;在Unity中导入MRTK3依赖【MR开发】在Pico设备上接入MRTK3&#xff08;二&#xff09;在Unity中配置Pico SDK 本文将介绍如何运行一个简单…...

C#中委托的应用与示例

委托 委托是指把事情托付给别人或别的机构办理。在C#语言中委托是一种特殊类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。委托是具有特定参数列表和返回类型的方法的引用的类型(不是引用对象,而是引用方法)。 可以委托将看作一个包含有序方法列表…...

算法: 模拟题目练习

文章目录 模拟替换所有的问号提莫攻击Z 字形变换外观数列数青蛙 总结 模拟 替换所有的问号 按照题目的要求写代码即可~ public String modifyString(String ss) {int n ss.length();if (n 1) {return "a";}char[] s ss.toCharArray();for (int i 0; i < n; i…...

软考中级科目怎么选?软考中级证书有什么用?

❇有计算机背景&#xff1a; 建议选择软件设计师或网络工程师。软件设计师更适合软件工程专业的同学报考&#xff0c;而网络工程师更适合网络工程专业的朋友&#xff08;仅供参考&#xff09;。 ❇没有计算机背景&#xff1a; 建议选择系统集成项目管理工程师作为入门科目。…...

HTTP 请求的请求体是什么

HTTP 请求的请求体(request body)是指在 HTTP 请求中除了请求行(request line)、请求头(headers)之外的实际数据部分。请求体通常包含用于向服务器发送数据的信息,这些信息可以是表单数据、JSON 对象、XML 文档或其他任何形式的数据。 http请求一般包含的内容 HTTP(超…...

助力语音技术发展,景联文科技提供语音数据采集服务

语音数据采集是语音识别技术、语音合成技术以及其他语音相关应用的重要基础。采集高质量的语音数据有助于提高语音识别的准确性&#xff0c;同时也能够促进语音技术的发展。 景联文科技作为专业的数据采集标注公司&#xff0c;支持语音数据采集。可通过手机、专业麦克风阵列、专…...