I. Creating Functions
void *rtai_malloc_adr (void *adr, unsigned long name, int size);
void *rtai_malloc (unsigned long name, int size);
void *rtai_kmalloc (unsigned long name, int size);
//rtai_malloc_adr and rtai_malloc are used for user space allocation while rtai_kmalloc is used for kernel space allocation.
parameter
adr user's desired address, allocated memory should be mapped to user space.
name unsigned long identifier
The amount of shared memory required by size
Since name can be a complex identifier, the system provides the service of converting a 6-character identifier into an integer of unmatched length, and vice versa. It is implemented by functions nam2num and num2nam.
unsigned long nam2num (const char *name);
void num2nam(unsigned long id, const char* name);
It must be said that the first allocation is a real allocation, and any subsequent allocation with the same name called from the Linux process only maps the region to user space or returns the relevant pointer to the space already allocated in the kernel space.
This function returns a pointer to the allocated memory, mapped appropriately to the memory space used.
Function return
Successfully, return a valid address
Failure, return 0.
Note: If the same process calls rtai_malloc_adr and rtai_malloc twice in the same process, it will return 0 on the second call.
2. Free function
void rtai_free (unsigned long name, void *adr);
void rtai_kfree(void *adr);
rtai_free is used to release a previously allocated shared memory in user space, and rtai_kfree is used to do the same thing in kernel space.
parameter
The unsigned long integer identifier used by Name when memory is allocated
Adr Address
Be careful
Similar to the operation of an allocation function, the release call only affects the cancellation of the mapped shared memory, which is finally released, when the allocated memory is really released.
4. Sample code( http://chrtai.sourceforge.net/)
/*
shm_task.c
Set up a periodic task that increments a heartbeat array in shared memory.
*/
#define MODULE
#define __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h> /* ENOMEM */
#include <stddef.h> /* sizeof() */
#include "rtai.h"
#include "rtai_sched.h"
#include "rtai_shm.h"
#include "common.h" /* SHM_KEY, SHM_HOWMANY */
MODULE_LICENSE("GPL");
RT_TASK shm_task;
static RTIME shm_period_ns = 100000;
static int * shm_array = 0;
static void shm_function(int arg)
{
int heartbeat = 0;
int t;
while (1) {
heartbeat++;
/* make sure the memory has been allocated before we write to it */
if (0 != shm_array) {
/* now write to it */
for (t = 0; t < SHM_HOWMANY; t++) {
shm_array[t] = heartbeat;
}
}
rt_task_wait_period();
}
return;
}
int init_module(void)
{
int retval;
RTIME shm_period_count;
shm_array = rtai_kmalloc(SHM_KEY, SHM_HOWMANY * sizeof(int));
if (0 == shm_array) {
return -ENOMEM;
}
rt_set_periodic_mode();
shm_period_count = nano2count(shm_period_ns);
start_rt_timer(shm_period_count);
retval = rt_task_init(&shm_task, shm_function, 0, 1024,
RT_LOWEST_PRIORITY, 0, 0);
if (0 != retval) {
return retval;
}
retval = rt_task_make_periodic(&shm_task,
rt_get_time() + shm_period_count,
shm_period_count);
if (0 != retval) {
return retval;
}
return 0;
}
void cleanup_module(void)
{
rt_task_delete(&shm_task);
rtai_kfree(SHM_KEY);
return;
}
/*--------------------------------------------*/
#include <stdio.h> /* printf() */
#include <stddef.h> /* sizeof() */
#include <signal.h> /* signal(), SIGINT */
#include <sys/mman.h> /* PROT_READ, needed for rtai_shm.h */
#include <sys/types.h> /* off_t, needed for rtai_shm.h */
#include <sys/fcntl.h> /* O_RDWR, needed for rtai_shm.h */
#include <rtai_shm.h> /* rtai_malloc,free() */
#include "common.h" /* SHM_KEY, SHM_HOWMANY */
/*
This signal handler just sets the 'done' flag, which we will loop
on when printing the shared memory. This lets us quit nicely.
*/
static int done = 0;
static void quit(int sig)
{
done = 1;
}
int main(void)
{
int * shm_array;
int head, tail;
shm_array = rtai_malloc(SHM_KEY, SHM_HOWMANY * sizeof(int));
if (0 == shm_array) {
fprintf(stderr, "can't allocate shared memory\n");
return 1;
}
/*
Attach our signal hander to SIGINT, the signal raised when we hit
Control-C.
*/
signal(SIGINT, quit);
while (! done) {
/*
Read the first and last element of the array. The should be
the same, but if we are interrupted by the RT code in between
these reads, the tail will be newer.
*/
head = shm_array[0];
/* we could get interrupted here */
tail = shm_array[SHM_HOWMANY - 1];
/*
Print out head and tail of shared memory, and an error if
they're different.
*/
printf("%10d\t%10d\r", head, tail);
if (head != tail) {
printf("\nsplit read\n");
}
}
/*
Control-C stopped us, so let's exit nicely by freeing up our connection
to shared memory.
*/
rtai_free(SHM_KEY, shm_array);
return 0;
}
Shared memory can be used between applications, such as a real-time task program, a linux program. The prerequisite for Malloc's success is that rtai_shm.ko is loaded