RTLinux下的一种实时应用通信机制
td.h>
#include<fcntl.h>
#include<sys/mman.h>
intfd;
unsignedshort*sharemem;
fd=open("/dev/mem",O_RDWR);①
sharemem=(unsignedshort*)mmap(0,buflen,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED,
Fd,BASE_ADDRESS);②
注①:访问物理内存必须打开与其对应的设备文件/dev/mem。
注②:mmap命令的作用是将设备文件fd中,从当前进程的虚拟地址空间,其返回值可被非实时进程存取。
以上两种方式在实现机理上的不同之处在于,mbuff利用vmalloc从内核地址空间分配的共享内存空间仅仅在逻辑上连续,空间的大小不受实际物理内存空间的限制;而直接隔离物理内存所获取的缓冲区物理上连续,但是大小受到物理内存空间和当前系统状况的限制。共同之处在于,所获得的内存均被隔离于系统内核的运行环境之外,不会在页面交换中被换出,所以以上两种方法均适用于实时应用之中。
3两种通信接口的结合
以上两种通信接口具有不同的适用范畴,为了实现一个完整的实时应用,通常需要将两者结合,以一个实时数据采集程序为例,实时模块和非实时模块之间通常需要传送两种类型的数据;结果数据和控制信息。
结果数据:由实时模块周期性产生。非实时模块用于显示和存储,对读/写的时序性要求不高,但是通常需要由多个用户共享,因此,利用共享内存模块传输比较适合。
控制信息:主要用于实现非实时模块和实时模块之间的交互控制,数据量小,但是比较注重信号读/写的时序性和通信过程中实时性,采用RT_FIFO实现比较适合。
图2为通用的抽象数据流图。
3.1共享内存的内步控制和RT_FIFO的使用
由于对共享内存的存取通过直接访问指针来实现,操作系统不会为其提供任何同步控制,应用程序必须自行提供握手机制,来保证读/写进程之间同步。
实现同步的一种方式是接收方和发送方利用消息通信来实现握手。接收方对共享内存以轮询的方式监测新数据的到来,然后发送接收信息。为了实现握手,发送方对于每条接收消息都必须回复一个确认消息,新的接收消息只有在收到确认消息以后才能发出。
这种方式在实时模块和非实时模块中均须要采用轮询的方式监测新数据和消息的到来,因此会占用较多的处理器资源。所以,可以考虑利用RT_FIFO实现实时模块和非实时模块之间对共享内存的存取同步。利用RT_FIFO所提供的句柄功能能够避免实时模块对接收消息的轮询监测,在一定程度上提高程序运行效率。
具体实现,可以通过利用RT_FIFO实时传输当前所写入或被读出的共享内存块序号,实现实时进程和非实时进程之间的步。因为RT_FIFO是一种单向传输队列,为了实现交互,需要两个传输方向相反的RT_FIFO,连接于两个模块之间,如图3所示。
图3中,BufNo为笔者自行定义的队列。它的使用主要是为了避免由于RT_FIFO引起的实时部分和非实时部分之间的死锁。
实时部分和非实时部分的各线程路之间对共享内存的访问为异步进行;同时,RTLinux中对RT_FIFO
的进行读/写的API函数,为阻塞式操作。当FIFO0中目前没有可读数据时,对rtf_get函数的调用会使程序陷入无限等待之中,很容易造成实时模块和非实时模块之间的死锁。
为了避免这种情况,可以将BufNo作为缓冲区与FIFO0的句柄结合使用,临时存放FIFO0中被非实时线程写入的块序号。实时模块不再对FIFO0进行读/写,而是改由BufNo队列中获取当前有效的共享内存序号。如果当前无可用数据,则进入周期等待状态。
3.2共享内存访问的互斥
对共享内存访问的互斥操作,包括两个方面:实时模块与非实时模块之间的互斥、非实时模块中各采集线程之间的互斥。
(1)实时模块与非实时模块之间的互斥
多线程之间对共享资源访问的互斥,是操作系统中一个重要的研究分支。但是在实时模块和非实时模块之间,问题变得相对简单。因为,在实时进程和非实时进程之中,实时进程和非实时进程运行的环境区别很大。工作于RTLinux环境下的实时进程具有最高的优先级,不可能 《RTLinux下的一种实时应用通信机制(第3页)》
本文链接地址:http://www.oyaya.net/fanwen/view/144432.html
#include<fcntl.h>
#include<sys/mman.h>
intfd;
unsignedshort*sharemem;
fd=open("/dev/mem",O_RDWR);①
sharemem=(unsignedshort*)mmap(0,buflen,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED,
Fd,BASE_ADDRESS);②
注①:访问物理内存必须打开与其对应的设备文件/dev/mem。
注②:mmap命令的作用是将设备文件fd中,从当前进程的虚拟地址空间,其返回值可被非实时进程存取。
以上两种方式在实现机理上的不同之处在于,mbuff利用vmalloc从内核地址空间分配的共享内存空间仅仅在逻辑上连续,空间的大小不受实际物理内存空间的限制;而直接隔离物理内存所获取的缓冲区物理上连续,但是大小受到物理内存空间和当前系统状况的限制。共同之处在于,所获得的内存均被隔离于系统内核的运行环境之外,不会在页面交换中被换出,所以以上两种方法均适用于实时应用之中。
3两种通信接口的结合
以上两种通信接口具有不同的适用范畴,为了实现一个完整的实时应用,通常需要将两者结合,以一个实时数据采集程序为例,实时模块和非实时模块之间通常需要传送两种类型的数据;结果数据和控制信息。
结果数据:由实时模块周期性产生。非实时模块用于显示和存储,对读/写的时序性要求不高,但是通常需要由多个用户共享,因此,利用共享内存模块传输比较适合。
控制信息:主要用于实现非实时模块和实时模块之间的交互控制,数据量小,但是比较注重信号读/写的时序性和通信过程中实时性,采用RT_FIFO实现比较适合。
图2为通用的抽象数据流图。
3.1共享内存的内步控制和RT_FIFO的使用
由于对共享内存的存取通过直接访问指针来实现,操作系统不会为其提供任何同步控制,应用程序必须自行提供握手机制,来保证读/写进程之间同步。
实现同步的一种方式是接收方和发送方利用消息通信来实现握手。接收方对共享内存以轮询的方式监测新数据的到来,然后发送接收信息。为了实现握手,发送方对于每条接收消息都必须回复一个确认消息,新的接收消息只有在收到确认消息以后才能发出。
这种方式在实时模块和非实时模块中均须要采用轮询的方式监测新数据和消息的到来,因此会占用较多的处理器资源。所以,可以考虑利用RT_FIFO实现实时模块和非实时模块之间对共享内存的存取同步。利用RT_FIFO所提供的句柄功能能够避免实时模块对接收消息的轮询监测,在一定程度上提高程序运行效率。
具体实现,可以通过利用RT_FIFO实时传输当前所写入或被读出的共享内存块序号,实现实时进程和非实时进程之间的步。因为RT_FIFO是一种单向传输队列,为了实现交互,需要两个传输方向相反的RT_FIFO,连接于两个模块之间,如图3所示。
图3中,BufNo为笔者自行定义的队列。它的使用主要是为了避免由于RT_FIFO引起的实时部分和非实时部分之间的死锁。
实时部分和非实时部分的各线程路之间对共享内存的访问为异步进行;同时,RTLinux中对RT_FIFO
的进行读/写的API函数,为阻塞式操作。当FIFO0中目前没有可读数据时,对rtf_get函数的调用会使程序陷入无限等待之中,很容易造成实时模块和非实时模块之间的死锁。
为了避免这种情况,可以将BufNo作为缓冲区与FIFO0的句柄结合使用,临时存放FIFO0中被非实时线程写入的块序号。实时模块不再对FIFO0进行读/写,而是改由BufNo队列中获取当前有效的共享内存序号。如果当前无可用数据,则进入周期等待状态。
3.2共享内存访问的互斥
对共享内存访问的互斥操作,包括两个方面:实时模块与非实时模块之间的互斥、非实时模块中各采集线程之间的互斥。
(1)实时模块与非实时模块之间的互斥
多线程之间对共享资源访问的互斥,是操作系统中一个重要的研究分支。但是在实时模块和非实时模块之间,问题变得相对简单。因为,在实时进程和非实时进程之中,实时进程和非实时进程运行的环境区别很大。工作于RTLinux环境下的实时进程具有最高的优先级,不可能 《RTLinux下的一种实时应用通信机制(第3页)》