QNX中进程间通信(IPC)之Pulse篇

主要内容翻译自QNX开发文档,根据自己理解翻译,错误之处在所难免,目的还是提供给大家对照阅读,我自己也写了一些代码,抽空后继也会放上

 

除了支持消息传递方式 (message) 来同步之外, Photon 也支持脉冲 (pulse) 。一个进程如果仅仅为了通知对方而不需要回复的情况下,可以使用 pulse 。例如,在 server 发送消息可能导致双方互锁 (SEND-blocked) 引起的死锁 (deadlocked) 的情况下,应该使用 pulse

一个 Photon pulse 由一个 PtAppAddInput() pid 参数的 PID 标识, PID 对你的应用程序而言是本地的。如果你希望接收另一应用程序发送的 pulse ,你必须使用 PtPulseArm() 函数来“瞄准 (arm) ”对方。该函数创建一个可以通过消息发送给其他进程的 PtPulseMsg_t 对象。这样其他进程就可以通过 MsgDeliverEvent() 函数发送 pulse

注意

QNX Neutrino OS 6 中, PtPulseMsg_t 是一个 sigevent 类型的结构。 msg.sigev_value.sival_int 位对应的 _NOTIFY_COND_MASK 被清除,但发送 pulse 的应用程序可以进行设置。更多内容参见 QNX Neutrino Library Reference

PtPulseArm() (Photon Library Reference 中有说明 ) 函数参数中包含一个 sigevent 结构类型变量。 PtPulseArmFd() PtPulseArmPid() 兼容于早期 QNX Neutrino OS Photon microGUI 版本。

1.1     Photon application that receives a pulse

对于 pulse 接收端 ( 我们称为 server) ,需要做如下工作:

1)        创建 pulse

2)        瞄准 (arm)pulse.

3)        发送 pulse 消息到发送 pulse ( 我们称之为 client)

4)        注册 pulse 处理函数。

5)        如有必要,发送 pulse 到自身。

6)        pulse 不需要时删除。

注意 :退出前请通知发送端停止发送 pulse

1.1.1     Creating a pulse

调用 PtAppCreatePulse() 函数创建一个 Photon pulse

pid_t PtAppCreatePulse( PtAppContext_t app,

                        int priority );

参数列表:

app

PtAppContext_t 结构类型标识的应用程序上下文地址,使用 NULL 表示使用默认上下文。

priority

pulse 优先级,使用 -1 表示调用程序使用的优先级。

PtAppCreatePulse() 返回一个非零整数表示的 pulse process ID

1.1.2     Arming a pulse

Arm 一个 pulse 填充一个可以被大部分 QNX Neutrino 调用使用的 sigevent 结构。

注意

多个 client 发出相同的 pulse 是正常的,尽管 server 不知道是由哪个进程发出的。

PtPulseArm() 函数原型如下:

int PtPulseArm( PtAppContext_t app,

                pid_t pulse,

                struct sigevent *msg );

参数如下:

app

当前应用上下文地址。 ( 一般设置为 NULL)

pulse

PtAppCreatePulse() 创建的 pulse

msg

函数创建的 pulse message 指针,我们应该将其传递到 client

函数返回 pulse message ID ,后面将会用到。

1.1.3     Sending the pulse message to the deliverer

发送 pulse message client ,如下:

l  对于 resource manager ,使用 ionotify()

ionotify (fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT,

          &pulsemsg);

l  对于其他类型进程,可以使用 MsgSendv()

/* Create your own message format: */

msg.pulsemsg = pulsemsg;

MsgSendv (connection_id, &msg, msg_parts, &rmsg, rmsg_parts);

 

1.1.4     Registering an input handler

注册 pulse 的消息处理与 message 的处理基本相同。将 PtAppCreatePulse() 返回的 pulse ID 作为参数传递到 PtAppAddInput() 即可。

Rcvid 参数没有必要与 pulse ID 相同:在 _NOTIFY_DATA_MASK 位上与 pulse ID 相同 ( 参见 QNX Neutrino Library Reference ionotify() 部分 ) ,但是其余位自 Neutrino pulse 接收。

1.1.5     Delivering a pulse to yourself

如果应用程序需要发送 pulse 到自身,可以使用 PtAppPulseTrigger() 函数:

int PtAppPulseTrigger( PtAppContext_t app,

                       pid_t pulse );

两个参数分别是应用程序上下文和 PtAppCreatePulse() 返回的 pulse ID

1.1.6     Example — message queues

以下是接收 Photon pulse 的例子。该例子打开一个消息队列 (message queue)( 默认使用 /dev/mqueue/testqueue) ,设置一个 pulse ,并且在从消息队列读取到内容时使用 mq_notify() 给自身一个 pulse

 

 

/* Standard headers */ #include #include #include #include #include #include #include #include /* Toolkit headers */ #include #include #include /* Local headers */ #include "abimport.h" #include "proto.h" mqd_t mqd = -1; struct sigevent sigev; static void readqueue( void ) { static unsigned counter; unsigned mprio; ssize_t msize; char mbuf[ 4096 ]; while ( ( msize = mq_receive( mqd, mbuf, sizeof(mbuf), &mprio ) ) >= 0 ) { char hbuf[ 40 ]; PtTextModifyText( ABW_mtext, 0, 0, -1, hbuf, sprintf( hbuf, "Msg #%u (prio %d):/n", ++counter, mprio ) ); PtTextModifyText( ABW_mtext, 0, 0, -1, mbuf, msize ); } if ( errno != EAGAIN ) perror( "mq_receive" ); } static int input_fun( void *data, int rcvid, void *message, size_t mbsize ) { if ( mq_notify( mqd, &sigev ) == -1 ) perror( "mq_notify" ); readqueue(); return Pt_HALT; } pid_t pulse; /* Application Options string */ const char ApOptions[] = AB_OPTIONS ""; /* Add your options in the "" */ int init( int argc, char *argv[] ) { if ( ( pulse = PtAppCreatePulse( NULL, -1 ) ) == 0 || PtAppAddInput( NULL, pulse, input_fun, NULL ) == NULL ) { fputs( "Initialization failed/n", stderr ); exit( EXIT_FAILURE ); } PtPulseArm( NULL, pulse, &sigev ); /* eliminate 'unreferenced' warnings */ argc = argc, argv = argv; return( Pt_CONTINUE ); } int open_queue( PtWidget_t *link_instance, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) { const char *name; PtArg_t arg; if ( mqd >= 0 ) mq_close( mqd ); PtSetArg( &arg, Pt_ARG_TEXT_STRING, &name, 0 ); PtGetResources( ABW_qname, 1, &arg ); if ( ( mqd = mq_open( name, O_RDONLY | O_CREAT | O_NONBLOCK, S_IRUSR | S_IWUSR, NULL ) ) < 0 ) perror( name ); else if ( mq_notify( mqd, &sigev ) == -1 ) { perror( "mq_notify" ); mq_close( mqd ); mqd = -1; } else readqueue(); /* eliminate 'unreferenced' warnings */ link_instance = link_instance, apinfo = apinfo; cbinfo = cbinfo; return( Pt_CONTINUE ); }

 

 

1.1     Photon application that delivers a pulse

发送 pulse Photon 应用程序 (Client ) 需要做以下工作:

l  使用一个 input handler 处理 Server 发送的 pulse 消息。使用 input handler 来处理包含 pulse 消息在内的各种消息,并且通知发送方停止发送 pulse 。注:保存消息中的 rcvid 值来发送 pulse ,你可能需要用来发送该 pulse

l  调用 MsgDeliverEvent() 发送 pulse

你可能感兴趣的:(QNX)