#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h> // mmap and friends
#include <unistd.h>

int main(void) {
    /*
     * See: "man 3 sysconf" or
     * https://www.man7.org/linux/man-pages/man3/sysconf.3.html
     *
     * See: "man 3 getauxval" or
     * https://www.man7.org/linux/man-pages/man3/getauxval.3.html
     */
    long page_size =
        sysconf(_SC_PAGESIZE); // or _SC_PAGE_SIZE (POSIX allows both)
    if (page_size == -1) {
        perror("sysconf");
        return 1;
    }

    printf("Page size: %ld bytes\n", page_size);

    /*
     * sbrk():
     * Increase or decrease the end of accessible data space by DELTA bytes.
     * If successful, returns the address the previous end of data space
     * (i.e. the beginning of the new space, if DELTA > 0); returns (void \*) -1
     * for errors (with errno set).
     */
    void *first = sbrk(0);
    void *second = sbrk(4096);
    void *third = sbrk(0);

    printf("First: %p\n", first);
    printf("Second: %p\n", second);
    printf("Third: %p\n", third);

    /*
     * mmap, munmap - map or unmap files or devices into memory
     *
     * mmap()  creates a new mapping in the virtual address space of the
     * calling process.  The starting address for the new mapping is specified
     * in addr. The length argument specifies the  length  of  the  mapping
     * (which  must  be greater than 0).
     */

    uint8_t *first_mmap = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
                               MAP_PRIVATE | MAP_ANON, -1, 0);

    uint8_t *second_mmap = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
                                MAP_PRIVATE | MAP_ANON, -1, 0);

    printf("First mmap: %p\n", first_mmap);
    printf("Second mmap: %p\n", second_mmap);

    return 0;
}