Give special attributes to a shared memory object
#include <sys/mman.h>
int shm_ctl( int fd,
int flags,
_uint64 paddr,
_uint64 size );
libc
The shm_ctl() function modifies the attributes of the shared memory object identified by the handle, fd. This handle is the value returned by shm_open().
The flags argument is a one or more of the following bits, defined in <sys/mman.h>:
| The combination SHMCTL_ANON | SHMCTL_PHYS has the same behavior as for mmap(): it indicates that you want physically contiguous RAM to be allocated for the object. |
The following examples go together. Run sharephyscreator, followed by sharephysuser.
The sharephyscreator process maps in an area of physical memory and then overlays it with a shared memory object. The sharephysuser process opens that shared memory object in order to access the physical memory.
/*
* sharephyscreator.c
*
* This maps in an area of physical memory and then
* overlays it with a shared memory object. This way, another process
* can open that shared memory object in order to access the physical
* memory. The other process in this case is sharephysuser.
*
* Note that the size and address that you pass to shm_ctl() must be
* even multiples of the page size (sysconf(_SC_PAGE_SIZE)).
*
* For VGA color text mode video memory:
* sharephyscreator /wally b8000
* Note that for VGA color text mode video memory, each character
* is followed by an attribute byte. Here we just use a space.
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>
char *progname = "sharephyscreator";
main( int argc, char *argv[] )
{
char *text = "H e l l o w o r l d ! ";
int fd, memsize;
char *ptr, *name;
uint64_t physaddr;
if ( argc != 3 ) {
printf( "use: sharephyscreator shared_memory_object_name physical_address_in_hex\n" );
printf( "Example: sharephyscreator wally b8000\n" );
exit( EXIT_FAILURE );
}
name = argv[1];
physaddr = atoh(argv[2]);
memsize = sysconf( _SC_PAGE_SIZE ); /* this should be enough
for our string */
/* map in the physical memory */
ptr = mmap_device_memory( 0, memsize, PROT_READ|PROT_WRITE, 0, physaddr );
if ( ptr == MAP_FAILED ) {
printf( "%s: mmap_device_memory for physical address %llx failed: %s\n",
progname, physaddr, strerror(errno) );
exit( EXIT_FAILURE );
}
/* open the shared memory object, create it if it doesn't exist */
fd = shm_open( name, O_RDWR | O_CREAT, 0 );
if ( fd == -1 ) {
printf( "%s: error creating the shared memory object '%s': %s\n",
progname, name, strerror(errno) );
exit( EXIT_FAILURE );
}
/* overlay the shared memory object onto the physical memory */
if ( shm_ctl( fd, SHMCTL_PHYS, physaddr, memsize ) == -1 ) {
printf( "%s: shm_ctl failed: %s\n", progname, strerror(errno) );
close( fd );
munmap( ptr, memsize );
shm_unlink( name );
exit( EXIT_FAILURE );
}
strcpy( ptr, text ); /* write to the shared memory */
printf( "\n%s: Physical memory mapped in, shared memory overlayed onto it.\n"
"%s: Wrote '%s' to physical memory.\n"
"%s: Sleeping for 20 seconds. While this program is sleeping\n"
"%s: run 'sharephysuser %s %d'.\n",
progname, progname, ptr, progname, progname, name,
strlen(text)+1 );
sleep( 20 );
printf( "%s: Woke up. Cleaning up and exiting ...\n", progname );
close( fd );
munmap( ptr, memsize );
shm_unlink( name );
}
The following is meant to be run with sharephyscreator.
/*
* sharephysuser.c
*
* This one is meant to be run in tandem with sharephyscreator.
*
* Run it as: sharephysuser shared_memory_object_name length
* Example: sharephysuser wally 49
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>
char *progname = "sharephysuser";
main( int argc, char *argv[] )
{
int fd, len, i;
char *ptr, *name;
if ( argc != 3 ) {
fprintf( stderr, "use: sharephysuser shared_memory_object_name length\n" );
fprintf( stderr, "Example: sharephysuser wally 49\n" );
exit( EXIT_FAILURE );
}
name = argv[1];
len = atoi( argv[2] );
/* open the shared memory object */
fd = shm_open( name, O_RDWR, 0 );
if ( fd == -1 ) {
fprintf( stderr, "%s: error opening the shared memory object '%s': %s\n",
progname, name, strerror(errno) );
exit( EXIT_FAILURE );
}
/* get a pointer to a piece of the shared memory, note that we
only map in the amount we need to */
ptr = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
if ( ptr == MAP_FAILED ) {
fprintf( stderr, "%s: mmap failed: %s\n", progname, strerror(errno) );
exit( EXIT_FAILURE );
}
printf( "%s: reading the text: ", progname );
for ( i = 0; i < len; i++ )
printf( "%c", ptr[i] );
printf( "\n" );
close( fd );
munmap( ptr, len );
}
| Safety: | |
|---|---|
| Cancellation point | Yes |
| Interrupt handler | No |
| Signal handler | Yes |
| Thread | Yes |
mmap(), munmap(), mprotect(), shm_open(), shm_unlink()