Using shared memory streams

From University of Washington - Ubicomp Research Page
Revision as of 22:45, 24 August 2007 by Karl Koscher (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Introduction

Some sensor streams (e.g. the microphone and camera) produce so much data that IPC becomes too inefficient. For these streams, a shared-memory mechanism is used instead. Note that with shared memory, you lose some of the benefits of IPC, such as the ability to log and replay message streams, and to send the data across hosts. In some cases, specialized network streaming applications exist to fill this gap.

Reading from shared memory

libmsb_interface, liblsb_interface, and libcamera_interface all provide functions that read from their respective shared memory streams. In the case of the MSB, all sensors are combined into one stream. You must do some minimal parsing to determine packet boundaries and the type of packets. See audio-stream for an example of how to pull out audio data. In the case of the LSB, the GPS stream is seperate from the other sensors. gps-debug provides an example of parsing the GPS stream, and the LSB sensor stream can be parsed like the MSB sensor stream. The camera server provides one stream of continuous JPEG data. cam-net-stream provides an example of parsing the camera stream.

The shared memory streams can be accessed by simply calling the appropriate *_shm_nread function (e.g. msb_shm_nread, lsb_shm_nread, sirf_gps_shm_nread, etc.). These functions automatically initialize the shared memory system on the first call. When calling these functions, you must create a buffer for the data to be returned into. Pass the size of this buffer and a pointer to the buffer. Note that if there isn't enough bytes in the shared memory queue to fill the buffer, *_shm_nread will fill the buffer with only the number of available bytes. *_shm_nread returns the number of bytes read.

Writing from shared memory

In most cases, you'll never need to write to shared memory. However, if you'd like to create your own shared memory stream, the MSP software provides a framework that lets you easily do so:

  1. Create an interface.h file that will be shared by the client and server.
  2. Define a 32-bit "key" that will be used to identify the stream. In most cases, four ASCII characters are used. For example:
    #define CAM_SERVER_SHM_KEY		0x736D6163
  3. Include msp/shm.h.
  4. Define a global msp_shm_t variable. For example:
    msp_shm_t shm;
  5. Call msp_shm_server, passing a pointer to the msp_shm_t variable, and the key you defined above. For example:
    msp_shm_server(&shm, CAM_SERVER_SHM_KEY);
  6. Call msp_shm_write whenever you'd like to write data to the shared memory stream, passing a pointer to the msp_shm_t variable, the size of the buffer, and a pointer to the buffer. For example:
    msp_shm_write(&shm, n, jpgBuffer);
  7. Create an interface.c file that will be used by the client. The contents should be:
      <c>
      1. include <msp/msp.h>
      2. include <msp/shm.h>
      3. include <msp/MODULE_interface.h>
      int __MODULE_interface_shm_firsttime = TRUE; msp_shm_t __MODULE_interface_shm; int MODULE_shm_nread( int len, unsigned char * data ) { if (__MODULE_interface_shm_firsttime==TRUE) { if (msp_shm_client( &__MODULE_interface_shm, MODULE_SHM_KEY )<0) { exit(0); } __MODULE_interface_shm_firsttime = FALSE; } else { return(msp_shm_nread( &__MODULE_interface_shm, len, data )); } return(0); } </c> Replace MODULE with whatever your module is called.