SHM_MAP(9)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

πŸ‘‘ SHM_MAP(9) β€” kernel dev manual, but make it make sense

okay so bestie, welcome to shm_map(9), a page from the Kernel Developer's Manual. it's got two functions, a whole lot of opinions about unmapping, and a genuinely adorable little history note at the bottom. let's get into it πŸ’…


✨ NAME ✨

shm_map, shm_unmap β€” map shared memory objects into the kernel's address space πŸ—ΊοΈ


✨ SYNOPSIS ✨

#include <sys/types.h>
#include <sys/mman.h>

int
shm_map(struct file *fp, size_t size, off_t offset, void **memp);

int
shm_unmap(struct file *fp, void *mem, size_t size);

✨ DESCRIPTION ✨

so the shm_map() and shm_unmap() functions are literally the API for mapping shared memory objects into the kernel. where do those objects come from? shm_open(2), bestie. that's the origin story. and then you can pass them into the kernel via file descriptors πŸŽ€

the big rule: a shared memory object cannot be shrunk while it's mapped into the kernel. not allowed. no. this is specifically so nothing invalidates pages that might be wired into the kernel's address space. growing it while mapped, though? totally fine, go off πŸ”₯

and because the accounting for that rule needs to stay simple, callers of this API are required to unmap the entire region that shm_map() mapped when they call shm_unmap(). unmapping only part of the region is not permitted. periodt πŸ™…β€β™€οΈ

shm_map() finds the shared memory object that belongs to the open file fp, then maps the region of that object described by offset and size into the kernel's address space. if it succeeds, *memp gets set to the start of the mapping, and all the pages for that range are wired into memory by the time it returns 🫢

shm_unmap() unmaps a region that shm_map() mapped earlier. the mem argument should match the value previously returned in *memp, and the size argument should match the value you passed to shm_map(). matchy matchy, or it's not gonna go well πŸ’€

heads up: shm_map() will not hold an extra reference on the open file fp for the lifetime of the mapping. nope. if the calling code wants to be able to use shm_unmap() on that region later, the calling code has to hold that reference itself. it's giving "you're on your own, bestie" πŸ™ˆ

✨ RETURN VALUES ✨

shm_map() and shm_unmap() return zero on success, or an error on failure. that's it, that's the whole vibe check ⭐


✨ EXAMPLES ✨

okay so here's a function that takes a file descriptor for a shared memory object. it maps the first sixteen kilobytes of that object into the kernel, does some work on that address, then unmaps it before returning. iconic behavior 🌸

int
shm_example(int fd)
{
        struct file *fp;
        void *mem;
        int error;

        error = fget(curthread, fd, CAP_MMAP, &fp);
        if (error)
                return (error);
        error = shm_map(fp, 16384, 0, &mem);
        if (error) {
                fdrop(fp, curthread);
                return (error);
        }

        /* Do something with 'mem'. */

        error = shm_unmap(fp, mem, 16384);
        fdrop(fp, curthread);
        return (error);
}

✨ ERRORS ✨

shm_map() β€” the failure flavors 😭

  • [EINVAL] β€” the open file fp is not a shared memory object. wrong vibe entirely.
  • [EINVAL] β€” the requested region described by offset and size extends beyond the end of the shared memory object. you asked for too much, babe.
  • [ENOMEM] β€” insufficient address space was available. no room at the inn.
  • [EACCES] β€” the shared memory object could not be mapped due to a protection error. 🚫
  • [EINVAL] β€” the shared memory object could not be mapped due to some other VM error.

shm_unmap() β€” the failure flavors, part two πŸ’€

  • [EINVAL] β€” the open file fp is not a shared memory object.
  • [EINVAL] β€” the address range described by mem and size is not a valid address range.
  • [EINVAL] β€” the address range described by mem and size is not backed by the shared memory object associated with the open file fp, or the address range does not cover the entire mapping of the object. remember the whole-region rule? yeah. that one.

✨ SEE ALSO ✨

  • shm_open(2) β€” the origin story, linked above πŸ¦‹

✨ HISTORY ✨

this API was first introduced in FreeBSD 10.0. a classic, honestly πŸ‘‘


and that's the page!! 🧚 this little treasure comes to you from the Debian crew, dated December 14, 2011 β€” go forth and map responsibly, bestie πŸ’–πŸŽ€

πŸ“¦ where this page comes from