mmap_peer(), mmap64_peer()

Updated: October 26, 2022

Create a virtual mapping in the address space of another process

Synopsis:

#include <sys/mman_peer.h>

void *mmap_peer( pid_t pid,
                 void *addr,
                 size_t len,
                 int prot,
                 int flags,
                 int fd,
                 off_t off );

void *mmap64_peer( pid_t pid,
                   void *addr,
                   size_t len,
                   int prot,
                   int flags,
                   int fd,
                   off64_t off );

Arguments:

pid
The ID of the process in which you want to map memory.
addr
NULL, or a pointer to where you want the object to be mapped in the specified process's address space.
len
The number of bytes to map into the specified process's address space. Note that this value can't be 0.
prot
The access capabilities that you want to use for the memory region being mapped. You can combine at least the following protection bits, as defined in <sys/mman.h>:
  • PROT_EXEC — the region can be executed.
    Note: To successfully use this flag:
    • The calling process must have the PROCMGR_AID_PROT_EXEC ability enabled. For more information, see procmgr_ability().
  • PROT_NOCACHE — disable caching of the region (e.g., so it can be used to access dual-ported memory).
    Note: On 32- and 64-bit ARM targets, PROT_NOCACHE causes RAM to be mapped as normal noncached, but non-RAM to be mapped as strongly ordered device memory. For finer control, see shm_ctl_special().
  • PROT_NONE — the region can't be accessed.
  • PROT_READ — the region can be read.
  • PROT_WRITE — the region can be written.
    Note: In order to simultaneously set PROT_EXEC and PROT_WRITE, the calling process must have the PROCMGR_AID_PROT_WRITE_AND_EXEC ability enabled (in addition to PROCMGR_AID_PROT_EXEC). For more information, see procmgr_ability().
flags
Flags that specify further information about handling the mapped region. For detailed information about the flags, see mmap().
fd
The file descriptor for a shared memory object, or NOFD if you're mapping physical memory.
off
The offset into shared memory of the location that you want to start mapping.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The mmap_peer() function maps a region within the object of the specified process ID beginning at off and continuing for len into the address space, and returns the location. The mmap64_peer() function is a large-file support version of mmap() and is useful only on 32-bit architectures.

Note: In QNX Neutrino 6.6 or later, the large-file support functions and data types appear in the name space only if you define _LARGEFILE64_SOURCE when you compile your code. For more information, see Classification in What's in a Function Description?

The address returned by mmap_peer() is valid only in the context of the process pid.

CAUTION:
We recommend that mmap_peer() and munmap_peer() be called only by a server on behalf of a client that's currently reply-blocked on the server and expects the message that it sent to result in a change to its address space. For example, the server can define a protocol that includes ALLOC_BUFFER and FREE_BUFFER messages, making it explicit that the message will result in memory mapping and unmapping, respectively. Otherwise the client's address space layout could unexpectedly change, leading to race conditions.

Consider using shm_create_handle() instead of mmap_peer().

The target process can:

Returns:

The address of the mapped-in object, or MAP_FAILED if an error occurred (errno is set).

Errors:

In addition to the errno codes set by mmap(), the following can be set:

ESRCH
The process pid doesn't exist, is loading, or is terminating.

Example:

The following example forks into parent and child process, and the parent process waits for the child process to terminate. The child process does the following:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <process.h>
#include <sys/mman.h>

int main(int argc, char *argv[])
{
   pid_t pid;
   pid_t parent_pid;
   char buff[256];
   const int mmap_len = 4096;

   parent_pid = getpid();
 
   pid = fork();
   assert( pid != -1);

   if( pid == 0 ) {
      /* This is the child process */

      void *ptr, *old_ptr;
      int ret;
      int failed;

      failed = 0;

      old_ptr = mmap_peer( parent_pid, 0, mmap_len, PROT_READ | PROT_WRITE,
                           MAP_SHARED, NOFD, 0);
      if (old_ptr == MAP_FAILED) {
         SPRNT( buff, sizeof(buff), "mmap_peer failed (errno %d)", errno);
         failed++;
      }
  
      if (!failed) {
         ret = munmap_peer(parent_pid, old_ptr, mmap_len);

         if ( ret == -1 ) {
             SPRNT( buff, sizeof(buff), "munmap_peer failed (errno %d)", errno);
             failed++;
         }
      }
   } else {
      /* This is the parent process */
      wait(NULL);
   }
     
   return EXIT_SUCCESS;
}

Classification:

mmap_peer() is QNX Neutrino; mmap64_peer() is Large-file support

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes