Shared Memory Integration using the Symbol Table

The symbol table is only the repository for information needed for the communications protocol. A computer application read the symbol table and writes C code allowing programmer's to initialize, use, and clean up shared memory variables. Shared Memory is a communication protocol which works on a principle similar to global variables in a program. Except shared memory is global, not just for one program, but for any program on a computer. Therefore, several programs can now communicate with each other by reading and writing to a command shared memory variable. Shared memory works well with programs running on the same machine, if communication is need across a LAN or the internet another communication protocol should be used like NDDS(Network Data Delivery Service).

Three files are generated from the symbol table: sMvar_ranger.h, sMvarExtern_ranger.h, and sMvar_ranger.c.

The file names have meaning and are broken down:

 sM  Shared Memory, these files are for shared memory protocol.
 var  Variable, these files are used for accessing variables, other files are generated to create message handlers, for automatically broadcasting data, and other functions.
 Extern  This designates and extern file. This is similar to the corresponding .h file, however instead of actually declaring the variables, the extern .h file declare variable as extern.
 _ranger  The Ranger vehicle, the symbol table used is initially dedicated for support of the Ranger robotic project. however other symbol tables could be generated for other projects.

Defining a Subsystem of Variables

The symbol table currently has over 500 potential symbols. Very rarely does one program require every symbol to be available. Symbols are grouped into subsystems which have a specific area of interest, like an arm force/torque sensor control (C{Arm}FT subsystem) or input device control (Ior subsystem). Using the database search tool, a programmer should determine which symbols, and their corresponding subsystems need to be used.

To define a subsystem, a define flag must be set within the makefile. A define flag is similar to having a #define that is used by all files within the makefile. Use a -D to define a subsystem, make sure you have the correct subsystem by using the symbol table subsystem descriptions. Therefore to use the the actual joint angle variables for the 7DOF dexterous left arm, the C{Arm}2 subsystem can be found on the subsystem descriptions page. Using the required arm substitution, the CDxl2 subsystem must be defined using a -DCDxl2 flag in the makefile.

>cc -DCDxl2 ${FLAGSMACRO} ${SOURCESMACRO} ${LIBRARIESMACRO} -o executable name

Any number of subsystems can be defined at once, therefore to access every variable that the 7DOF left arm resolved rate controller uses the following flags would be used.

> cc -DCDxlRR -DCDxlRR1 -DCDxlRR2 ${FLAGSMACRO} ....

All other variables would be ignored, only 9 of over 500 variables would be used. This keeps the object code and executable size low, yet allowing the programmer access to all necessary variables within the entire symbol table.

sMvar_ranger.h

This file should referenced using

#include sMvar_ranger.h

in only one of the .c files in a computer project, preferably were most of the utilization of variables and functions will occur. This file performs many functions.

It includes several .h files which allows use of shared memory, the additional files declared are: sys/types.h, sys/ipc.h, and sys/shm.h. The sMvar_ranger.h also prototypes the three functions used: allocateShmemVariableMemory, freeShmemVariableMemory,and destroyShmemVariableMemory.

The .h file then type defines all the data structures used by the symbol table so that they can be properly used to define the variable later.

The shared memory variables are then declared. Only the variables within the subsystems defined in the makefile will be declared. Make sure that the subsystem is correctly defined. The shared memory variable names are generated from the symbol name with an 'SM_ ' prefix. Therefore the 7DOF dexterous left arm actual joint angles symbol name is {Arm}_Act_Joint_Pos and would generate a shared memory variable name of SM_Dxl_Act_Joint_Pos. The zeroth element in that 7 element array would be referenced like any other float array.

SM_Dxl_Act_Joint_Pos[0] = 0;

Finally the shared memory keys are defined. These keys are how different programs look to the correct location for data. If key 100 is used for a status message. Every program when initializing that variable/message would use the same key of 100. After initialization, every program could now read and write any changes made to that variable. However if the shared memory key is different for each program, each program would read/write to a different location and no communication would occur. Therefore the shared memory key list defined in this file must be used by every application written, or at least the keys must correspond to all applications that are to communicate. Since this key declaration is automatically generated from the symbol table, when the symbol table changes the key declarations also change. Programs using different versions of this file may not communicate properly. This is a common failure mode that should be known.

sMvarExtern_ranger.h

This file performs the exact function as sMvar_ranger.h, with only one exception. When the shared memory variables are declared, they are declared as extern. As mentioned before, sMvar_ranger.h is referenced only once. All other files which use the shared memory variables or functions should reference

#include sMvarExtern_ranger.h

so that those files will have the necessary extern declarations and function prototypes as well.

sMvar_ranger.c

This file contains the three functions used to setup, attach, detach, and destroy the shared memory.

void allocateShmemVariableMemory(void);

This function allocates and attaches to a shared memory segment for each symbol defined by the subsystem flags. Make sure that the subsystem is correctly defined. This function should be called before any shared memory variables are accessed, otherwise the program will likely crash. Typically this function is used during initialization of the program. If an error occurs the following message will be written to the shell running the program:

ERROR CREATING SHARED MEMORY for SM_SymbolName

This error typically occurs when the computer systems has already all its allocation for shared memory. This can occur easily if shared memory variables are not properly destroyed. See freeing up used shared memory.

void freeShmemVariableMemory(void);

This function detaches the defined symbols from shared memory. This function should be called when terminating the communication process, typically this function is call during the termination of the program. If an error occurs the following message will be written to the shell running the program:

ERROR DETACHING SHARED MEMORY for SM_SymbolName

This error typically occurs when a the shared memory was not attached correctly. Therefore detaching properly can not occur either.

void destroyShmemVariableMemory(void);

This function will destroy all the shared memory segments which have been defined by the subsystem flags. Make sure that the subsystem is correctly defined. This function should only be called when no further communication will occur using those shared memory segments. Any process attempting to use the destroyed shared memory will no longer be able to communicate. Those programs will need to be restarted to create and attach to a newly generated shared memory location. Often a separate program will use this function to clean up all shared memory after a programming session is complete.

Freeing Up Used Shared Memory

The first time a program using shared memory is executed, a shared memory location is created for each symbol. When other programs are executed, using the same symbols, they attach to the same shared memory location. This is how shared memory communication works, each program can read and write to the same location. Before terminating a program, it is good to detach to that shared memory location. I don't know of what adverse effect occurs if this doesn't happen, but it's at least good programming. When all programs are terminated that shared memory location can be destroyed. This frees up memory so that other shared memory location can be used. If the shared memory location is not destroyed, other programs using different keys may not be able to use shared memory. Worse other programs which happen to use the same shared memory key will attempt to attach to the incorrect memory segment. Therefore it is wise to destroy all created shared memory locations when finishing a programing session. This can be done using the destroyShmemVariableMemory function or using the following on the command line.

>ipcs

This command reports inter-process communications including shared memory segments. When completed with a programming session no additional shared memory process should exist. This list of items will also give a shared memory id which can be used to remove that shared memory segment using:

>ipcrm -m sharedMemoryId

The above command will destroy that shared memory segment. Make sure only shared memory segments which are not being used are destroyed. If any process is still using that location, communication with that symbol will be discontinued. All programs using that segment will need to be restarted. This command will allow the programmer to free shared memory space if an error has occurred during allocation.