调用其他服务器上的函数 消息传递,QNX操作系统信息传递
二.脉冲信号
在一些场合客户端不能阻塞等待服务器应答,例如中断处理函数,时钟函数,等。这种非阻塞的消息传递我们称之为脉冲。脉冲信号有如下特点:
1)有效传递40位数据(8位脉冲码,32位数据)
2)对发送者而言是非阻塞的
3)可以像其他消息一样被接受
4)脉冲会排队,只要接受者不是阻塞等待脉冲。
1.接受脉冲消息
可以利用MsgReceive函数接受消息,跟普通消息没有区别,但是不能用MsgReply,毕竟脉冲是异步的,不需要应答。MsgReceivePulse函数专门用来处理脉冲。如果程序调用MsgReceive返回值是0表明接受到的是一个脉冲信号。
例如:
#include
rcvid = MsgReceive (chid, …);
if (rcvid == 0) { // it's a pulse
// determine the type of pulse
// handle it
} else { // it's a regular message
// determine the type of message
// handle it
}
2.脉冲结构提体定义:
struct _pulse {
uint16_t type;
uint16_t subtype;
int8_t code;
uint8_t zero [3];
union sigval value;
int32_t scoid;
};
type和subtype为0,code和value组成40bits发送码。code指定脉冲类型,value携带数据。
value是一个联合体
union sigval {
int sival_int;
void *sival_ptr;
};
经常看到的典型应用是:
#include
rcvid = MsgReceive (chid, …
if (rcvid == 0) { // it's a pulse
// determine the type of pulse
switch (msg.pulse.code) {
case MY_PULSE_TIMER:
// One of your timers went off, do something
// about it...
break;
case MY_PULSE_HWINT:
// A hardware interrupt service routine sent
// you a pulse. There's a value in the "value"
// member that you need to examine:
val = msg.pulse.value.sival_int;
// Do something about it...
break;
case _PULSE_CODE_UNBLOCK:
// A pulse from the kernel, indicating a client
// unblock was received, do something about it...
break;
// etc...
} else { // it's a regular message
// determine the type of message
// handle it
}
3.脉冲接收函数
有时候我们只需要接受脉冲信号,例如,某个时刻,我们接受到客户端请求去做某事,但是我们不能立即给客户端作出响应,可能是我们在做一个长时间的硬件操作。在这种情况下,我们通常会给硬件设定一个定时器或则脉冲信号,当有事情发生。如果我们把服务器设计为经典的无线循环等待消息的模式,我们需要等待各种请求,这种设计是合理的,毕竟,服务器必须在一个时间服务多个线程。但是这样我们必须限制服务器数量。
在这种情况下,我们必须选择只是接受脉冲信号,而不是常规信号,这就是MsgReceivePulse函数的作用。
#include
int MsgReceivePulse (int chid,
void *rmsg,
int rbytes,
struct _msg_info *info);
4.如何设计需要接受脉冲信号和普通信号的服务器
通常我们设计一个线程池服务MsgReceive函数,对客户端请求作出响应。必须控制线程池线程数量,一些线程必须阻塞,等待脉冲到达,让线程池线程阻塞的典型方式是调用MsgReceivePulse函数,确保客户端请求会被及时察觉。
5.MsgDeliverEvent()函数的使用
之前我们提到发送消息时候的等级制度,有些情况我们需要打破,例如,客户端给服务器发送消息,服务器不能立刻应答而客户端不想等待。遇到这种情况,正确的做法是,告诉客户端,请求一段时间后会得到处理客户端得以继续运行,一旦服务器完成任务,服务器需要一些方式告诉客户端,请求完成。在发送等级的时候提到客户端不能给服务器发送消息,可能会导致死锁,如果同一时间客户端给服务器也发送消息请求。
解决这个问题需要多步操作。
1)客户端创建一个 struct sigevent 并且填充
2)客户端给服务器发送消息
3)服务器接受到消息存下结构体信息,以及Receive ID,立即对客户端应答。
4)客户端继续运行
5)当服务器完成任务调用 MsgDeliverEvent()通知客户端任务完成
int
MsgDeliverEvent (int rcvid,
const struct sigevent *event);
event服务器不需要作修改
rcvid是服务器从客户端接收的。当服务器给客户端应答,这个id将失去意义。
另外MsgDeliverEvent是非阻塞函数。
三、频道创建时候的标志位
_NTO_CHF_FIXED_PRIORITY
接受线程优先级不因为发送线程的优先级而发生改变。
_NTO_CHF_UNBLOCK
当客户端试图解除阻塞的时候,内核发送脉冲给服务器(_PULSE_CODE_UNBLOCK )
_NTO_CHF_THREAD_DEATH
当阻塞在频道内的一个线程死亡,内核发送脉冲(_PULSE_CODE_THREADDEATH )
_NTO_CHF_SENDER_LEN
内核把客户端消息的长度作为消息的一部分传递给服务器(srcmsglen)
_NTO_CHF_REPLY_LEN
内核把客户端应答消息缓存的长度作为消息的一部分传递给服务器(srcmsglen)
_NTO_CHF_COID_DISCONNECT
当进程内的所有连接都被终止了
_NTO_CHF_UNBLOCK详解:
我们知道,在消息传递中,为了保证可靠性,当
客户端向服务器发送消息时,客户端是被“阻塞”(BLOCK)住的。这种状态,要一直到服务器应答了以后才会被开放。这就造成了一个问题,有时候,如果服务器还没有应答,而客户端又希望从阻塞中恢复,那又怎么办呢? 最常见的,比如用户CTRL-C了客户端进程,按POSIX标准,一个SIGINT应该被发送到客户端进程,而客户端进程如果没有特别处理的话,应该被SIGINT终止。那么,如果这时,客户端正好在阻塞状态中,会怎么样呢? 如果客户端进程,就这样突然凭空消失的话,服务器端会混乱,因为服务器端的程序,是建立在客户端被阻塞的情形下的。试想一下,如果客户端突然消失了,而服务器端又要MsgRead(),或是MsgWrite()会发生什么事呢? 为了防止服务器端发生这种混乱,QNX规定如果一个进程,正REPLY
BLOCK在别的进程上的时候,它不能自动脱离BLOCK状态;相反地,如果进程有什么理由要退出BLOCK状态,系统会先给服务器端发送一个 “UNBLOCK”脉冲,好象是说“REPLY BLOCK中的xx线程希望脱离阻塞状态”;而由服务器自己判断应该如何处理。服务器端可以在自己内部数据结构做出整理后,选择MsgError(rcvid,
EINTR);以解除客户端的阻塞状态;也可以什么也不做,不理睬这个脉冲,这样客户端就不能退出BLOCK状态。有时候你会在QNX遇到Ctrl-c但进程却没有退出的情况,这就是因为进程正被阻塞在一个服务器上,而服务器没有正确处理
UNBLOCK PAULSE的结果。
四、同步问题
即使我们创建频道的时候设置了_NTO_CHF_UNBLOCK参数。实际情况下依然有一个同步问题需要我们处理。想象一下,服务器多个线程阻塞在MsgReceive函数,等待消息或者脉冲,这时候,客户端发送一个消息,其中一个线程接收了并开始工作。这期间,客户端希望解除阻塞状态,那么内核发送一个解除阻塞的脉冲消息。服务器其他线程接收到这个脉冲。这样第一个和第二个线程会发生竞争,如果第二个线程给客户端应答那么它会收到客户端对应的一些信息,这时候第一个线程应答客户端,可能这已经是客户端第二次请求了。另外一种情况是,第一个线程先应答,那么可能是把客户端第二次请求的阻塞解除了。通常解决这个问题的办法是用一个互斥锁。MsgReceive之后加锁MsgReply之前解锁。
五、消息在网络中的传递
55/5<12345
调用其他服务器上的函数 消息传递,QNX操作系统信息传递相关推荐
- QNX操作系统信息传递
一.QNX消息概述 QNX消息可以分为同步消息和异步消息.异步(脉冲)消息主要体现的是一种通知机制,同步消息主要是说消息在传递过程需要双方相互配合的过程. 二.QNX消息传递几个基本概念 1.频道与链 ...
- QNX操作系统信息传递-qnx任务之间的消息传递信息传递
转载:https://blog.csdn.net/xjhhjx/article/details/77139457 一.QNX消息概述 QNX消息可以分为同步消息和异步消息.异步(脉冲)消息主要体现的是 ...
- php怎么上传函数,PHP单文件上传原理及上传函数的封装操作示例
搜索热词 @H_404_0@本文实例讲述了PHP单文件上传原理及上传函数的封装操作.分享给大家供大家参考,具体如下: @H_404_0@表单: @H_404_0@0.PHP: 无标题文档 请选择您要上 ...
- java 线程 函数_java – 从后台线程调用主线程上的函数
更新 我已经更新了这个问题,使用建议的SwingWorker类包含Java实现的源代码,以实现与Objective-C示例相同的结果.希望这将有助于未来的冒险家. Document myDoc = . ...
- 无法加载服务器指定地图,用javascript调用iserver服务器上的地图不显示
我用javascript调用我自己在iserver上发布的地图不显示,但是调用官网教程上的原始地图实例可以显示,代码使用的是教程中快速入门的代码,我修改了地图的目标坐标系为EPSG:3857,并且在调 ...
- SpringSecurity(二十)---OAuth2:实现资源服务器(上)资源服务器搭建以及直接调用授权服务器模式
一. 前言 本章将讨论如何使用Spring Security实现一个资源服务器,资源服务器是管理用户资源的组件.另外,学习本章有个前提,需要先把前面搭建授权服务器的相关文章先给阅读,否则可能后面出现的 ...
- 普通的PHP上传到云函数,php封装上传函数代码示例
php封装上传函数代码示例 发布时间:2020-05-14 17:16:12 来源:亿速云 阅读:184 作者:Leah 今天小编就为大家带来一篇有关php封装上传函数的文章.小编觉得挺实用的,为此分 ...
- fMRI质量预检查与服务器批量处理:时间点、体素尺寸批量审查与Dpabi(DPARSFA)服务器上无GUI无弹窗处理脑功能影像(附matlab脚本)
| 图源-slice | 工具:dpabi5.0, spm12, NIfTI_20140122(密码:iizk) 我们知道在进行fMRI预处理的时候,要求所有被试时间点相同,它将直接影响到s ...
- 执行远程服务器上的脚本失败?(环境变量引起的问题)
我们在使用jenkins构建job时会调用远程服务器上的脚本,执行某项操作.有时因为脚本涉及到了环境变量,无法成功执行.解决这个问题的方法一直就是在脚本开始加入一行: source /etc/prof ...
最新文章
- 接口测试(postman jmeter)
- UEditor在线编辑器使用记录
- mysql5.1.6安装_mysql 5.1.6的安装启动
- 零基础学Android之常用控件
- C#中DataTable中的Compute方法使用收集
- 小程序采用mvvm设计模式_滴滴重磅开源跨平台统一 MVVM 框架 Chameleon
- 安卓中的@Nullable和NonNull(NotNull) 等 注释
- Palindrome Degree(hash的思想题)
- linux c编译 utf-8,在Linux C编程中使用Unicode和UTF-8
- LaTeX符号大全-基于lshort-zh-cn
- 计算几何之计算三角形的外接圆(三维)
- java 复制网页文字_网页文字复制不了?你这样做,全网文字任你免费复制!快get!...
- 斐讯k2虚拟服务器设置,斐讯K2调配设置
- 网易有道笔试题(2014届,2013.10北邮站)
- 【BZOJ4049】【Cerc2014】 Mountainous landscape 【凸包】【线段树】
- android16进制编辑器,16进制编辑器app
- 读书笔记: 经济学原理
- Mosquitto常用命令
- 中国上海人工智能CIMCAI世界第一完成两百万次AI验箱上亿次箱识别,成熟AI产品运行超7百万小时智慧港航智能化中国上海人工智能
- tkMapper的基本使用
热门文章
- 电脑C盘空间还很多,电脑却卡得飞起怎么办。
- 2017百度之星程序设计大赛 - 资格赛:1003 度度熊与邪恶大魔王
- STM32F103 扩展以太网口
- 用python生成动态樱花树
- 漫画图解python_80道漫画图解算法题汇总
- Debian 6.0安装igb驱动
- 在大厂入职三年已是老员工?大学教授:年轻人压力很大。。。
- 关于投篮的数学建模模型_投篮问题的数学建模[共10页]
- iOS小技巧总结,绝对有你想要的(持续更新)
- 流量卡设备状态已停用怎么开启_物联卡无故停机怎么办?最全操作指南点这里,亲测有效!...