QNX驱动开发——操作系统之进程调度和进程通信

一、进程调度方法

1.FIFO:先进先出队列法。一个最高优先级的线程可以一直执行到结束或是主动放弃CPU。高优先级的线程可以随时中断低优先级的线程,获得CPU的使用权限,与之相同优先级的CPU也只能等待其交出CPU的使用权限后才能按排队的顺序先后执行。

2.Round Robin:循环法。除了对于最高的相同优先级的使用时间片轮转的方法外,其他特点与FIFO法相同。注意此处的时间片轮转与windows的不一样,是随时可以被高优先级任务抢占的。

二、进程间通信

      QNX所有功能实现都是靠消息传递的机制实现的,并可以轻松实现网络通信。其中POSIX函数与底层的通信就是靠消息实现的。

      通信的过程分为三个步骤:client向server发送消息;server向client接受消息;server处理并将结果返回给client。

      A useful minimal set of functions is ChannelCreate(),ConnectAttach(),MsgReply(),MsgSend(), and MsgReceive().

对于client想要与server通信要通过ConnectAttach 与server建立连接,使用MsgSend向server发送一个消息。

对于server:

       首先要通过ChannelCreate创建一个通道,然后有“receive”和“reply”两个阶段来处理消息。

chid = ChannelCreate (0);或者(Name_attach_t *attach = name_attach(NULL,(char *)”myserver”,0);)

rcvid = MsgReceive (chid, message, sizeof (message),NULL);

MsgReply (rcvid, EOK, message, sizeof (message));

    对于client

    需要做两件事情,一是要通过ConnetAttach与server的channel建立连接,二是要通过MsgSend向server发送消息。

     1)与server建立连接

int ConnectAttach (int nd,

pid_t pid,

int chid,

unsigned index,

int flags);

例如coid = ConnectAttach (0, 77, 1, 0, 0);是连接了自己节点(0)的,进程号为77的一个进程的1号channel。可是如何获得server的ND/PID/CHID这几参数呢?

QNX提供了几种方法:

1.server向一个文件中写入自己的ND/PID/CHID参数,client发送消息时打开文件,读出字符串。(文件过多)

2.使用全局变量来存储这几个参数。(非常有局限性,如果有共享内存,无法使用网络连接到!)

3.使用命名功能来把client注册一个名字。

4.把server升级为一个resource manger,这样就可以打开/dev/**来建立通信消息。(一般不这样做)。

        在通常情况下,命名功能name_attach() and name_open()来完成比较方便。

比如:server_coid = name_open((char *)”myserver” ,0);来打开server创建的/dev/name/local/myserver,与server创建的channel建立连接。

在server端可以使用name_attach()在命名空间创建一个name,如

Name_attach_t *attach = name_attach(NULL,(char *)”myserver”,0);当server的线程结束时,此命名也自动地跟着删除掉。这就很好的解决了建立通道的问题。

        2)向server发送消息

       这里可以分为几种情况,需要回复数据、回复成功或失败但是不回复数据。于是我们可以使用一下函数完成功能。

int MsgSend (int coid, const void *smsg, int sbytes, void *rmsg, int rbytes);

MsgReply (rcvid, EOK, NULL, 0); //successful

MsgError (rcvid, EROFS); //failed

       Client和Server各参数之间的关系如下图所示:

        我做了一个这样的实验,在工程中建立一个名为server的工程和一个名为client的工程,两个进程之间完全时陌生的,通过name_attach和name_open的方式建立通道,这样就不需要获得ND/PID/CHID这几个参数了。在实验的过程中发现使用消息进行通信时非常方便的,但是最好自己定义一个命令消息格式,滤除掉不是原client发来的消息(系统还会对server发送消息进行控制),这样就不会出现误触发。

建立一个结构体

Struct _io_message{

Int nbyte;

Int type;

Char msg[1024];

};

        就可以很方便的判断传入消息的大小、消息类型以及消息的多少了,如果server的接收buffer太小,使得接收的数据丢失,可以通过判断实际传过来的nbyte和定义buffer的大小来判断这一情况,使用MsgRead()和MsgWrite()再把实际大小的数据读回来。

你可能感兴趣的:(QNX驱动程序开发)