Give special attributes to a shared memory object
#include <sys/mman.h> int shm_ctl( int fd, int flags, uint64_t paddr, uint64_t size ); int shm_ctl_special( int fd, int flags, uint64_t paddr, uint64_t size, unsigned special );
If you create anonymous shared memory objects (by calling mmap() with MAP_ANON | MAP_SHARED and a file descriptor of -1), a MAP_LAZY flag implicitly sets the SHMCTL_LAZY flag on the object.
shm_ctl( fd, SHMCTL_PHYS, baseaddr, vstride ); shm_ctl( fd, SHMCTL_REPEAT, pstride, count );
The value of this argument must be an even multiple of the page size (sysconf(_SC_PAGESIZE)).
For SHMCTL_REPEAT, this argument is the length, which is used to increment the offset within the object. The value must be an even multiple of the page size.
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
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 shm_ctl_special() function is similar to shm_ctl(), but has an additional, processor-specific argument.
Your process might need some abilities enabled (see procmgr_ability()):
In order to use: | You need: |
---|---|
SHMCTL_GLOBAL | PROCMGR_AID_MEM_GLOBAL |
SHMCTL_PHYS | PROCMGR_AID_MEM_PHYS |
shm_ctl_special() | PROCMGR_AID_MEM_SPECIAL |
Bits in the flags argument for ARM processors
For ARMv7 processors:
Bits in the flags argument for x86 processors
For x86 processors:
Bits in the special argument for ARM processors
For ARM platforms, the special argument specifies the page table entry (PTE) bits to be set when the object is mapped.
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_PAGESIZE)). * * 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_PAGESIZE ); /* 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 overlaid 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 |