All pastes #971513 Raw Edit

test_shmseg_mmap

public c v1 · immutable
·published 2008-04-04 20:09 UTC
rendered paste body
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/mman.h>#include <fcntl.h>#include <errno.h>extern int errno;static key_t key = -1;const char* device = "/dev/mem";static const char* program_name = "test_shm_mmap";static size_t shm_size = 0;static void print_action(const char* device, size_t shm_size, size_t size, off_t offset);static void usage(void);static void pause_for_ipcs(int shmid);static int os_create_shm_region(void);static void* os_attach_shm_region(int shmid);static int os_destroy_shm_region(caddr_t addr);static void* mmap_shm_region(caddr_t addr, size_t size, off_t offset, int* fd);static int munmap_shm_region(caddr_t addr, size_t size);extern char* optarg;extern int optind, opterr, optopt;intmain(int argc, char* argv[]){    size_t size = 0;    int fd = -1;    off_t offset = 0x0;    int c;    int err = 0;    caddr_t addr = NULL;    int shmid = -1;    if (shm_size == 0)        size = shm_size = sysconf(_SC_PAGESIZE) * 1024; /* 4MB */    while ((c = getopt(argc, argv, "d:s:o:")) != -1)    {        switch(c)        {            case 'd':                device = strdup(optarg);                break;            case 's':                size = (size_t) atoi(optarg);                break;            case 'o':                offset = (off_t) atoi(optarg);                break;            default:                (void) fprintf(stderr, "Unknonwn option -%c\n",                        optopt);                ++err;                break;        }    }    if (err)        usage();    print_action(device, shm_size, size, offset);    if ((shmid = os_create_shm_region()) < 0)        return -1;    if ((addr = os_attach_shm_region(shmid)) == (caddr_t) -1)        return -1;    if ((addr = mmap_shm_region(addr, size, offset, &fd)) == (caddr_t) -1)        return -1;    pause_for_ipcs(shmid);    if ((munmap_shm_region(addr, size)) != 0)        return -1;    if ((os_destroy_shm_region(addr)) != 0)        return -1;    return 0;}voidprint_action(const char* device, size_t shm_size, size_t size, off_t offset){    (void) fprintf(stderr,            "Attempting to mmap(2) device \"%s\" onto a shared memory segment of size %u bytes with size %u bytes at offset 0x%x\n",            device, shm_size, size, offset);}voidusage(void){    (void) fprintf(stderr, "Usage: %s -s <size> -o <mmap offset>\n",            program_name);    exit(0);}void pause_for_ipcs(int shmid){    char c;    (void) fprintf(stderr, "If you now do '%> ipcs -a' in a different terminal, you should see a shared memory segment with id 0x%x owned by uid %u\n",            shmid, getuid());    (void) fprintf(stderr, "Press any key to continue.\n");    c = fgetc(stdin);    (void) fprintf(stderr, "cleaning up\n");}intmunmap_shm_region(caddr_t addr, size_t size){    int ret;    if ((ret = munmap(addr, size)) != 0)    {        (void) fprintf(stderr, "%s: munmap(2) failed: %s\n",                __func__, strerror(errno));    }    return ret;}void*mmap_shm_region(caddr_t addr, size_t size, off_t offset, int* fd){    void* ret = (void *) -1;    if (fd == NULL)     {        (void) fprintf(stderr, "%s: bad fd pointer\n", __func__);        goto mmap_fail;    }    if (size % sysconf(_SC_PAGESIZE))    {        (void) fprintf(stderr, "%s: mmap'ed size must be a multple of %u\n",                __func__, sysconf(_SC_PAGESIZE));        goto mmap_fail;    }    if (size > shm_size)    {        (void) fprintf(stderr,                "%s: mmap'ed size cannot exceed shmseg size %u\n",                __func__, shm_size);        goto mmap_fail;    }    if (offset && (offset % sysconf(_SC_PAGESIZE)))    {        (void) fprintf(stderr,                "%s: offset 0x%x is not 0 and is not a multiple of %u\n",                __func__, offset, sysconf(_SC_PAGESIZE));        goto mmap_fail;    }    *fd = open(device, O_RDONLY, (mode_t) 0444);    if (*fd == -1)    {        (void) fprintf(stderr, "%s: open(2) failed: %s\n",                __func__, strerror(errno));        goto mmap_fail;    }    if ((ret = mmap(addr, size, PROT_READ, MAP_SHARED|MAP_FIXED|MAP_NORESERVE, *fd, offset)) == MAP_FAILED)    {        (void) fprintf(stderr, "%s: mmap(2) failed: %s\n",                __func__, strerror(errno));        goto mmap_fail;    }    (void) fprintf(stderr,            "%s: mmap(2)'ed shmseg at address 0x%x [0x%x] with flags (MAP_SHARED|MAP_FIXED|MAP_NORESERVE) size %u\n", __func__,            ret, addr, size);mmap_fail:    return ret;}intos_destroy_shm_region(caddr_t addr){    int ret;    if ((ret = shmdt(addr)) != 0)        (void) fprintf(stderr, "%s: shmdt(2) failed: %s\n",                __func__, strerror(errno));    else        (void) fprintf(stderr, "%s: detached shm seg at address 0x%p\n",                __func__, addr);    return ret;}void*os_attach_shm_region(int shmid){    void* ret = NULL;    struct shmid_ds ds;    if ((ret = shmat(shmid, (void *) 0, 0)) == (void *) -1)        (void) fprintf(stderr, "%s: shmat(2) failed: %s\n",                __func__, strerror(errno));    else        (void) fprintf(stderr, "%s: attached shmseg 0x%x at address 0x%p\n",                __func__, shmid, ret);    (void) memset(&ds, '\0', sizeof(ds));    if ((shmctl(shmid, IPC_STAT, &ds) != 0))        (void) fprintf(stderr, "%s: shmctl(2) IPC_STAT failed: %s\n",                __func__, strerror(errno));    ds.shm_perm.mode = 0666;    if ((shmctl(shmid, IPC_SET, &ds) != 0))        (void) fprintf(stderr, "%s: shmctl(2) IPC_SET failed: %s\n",                __func__, strerror(errno));    return ret;}intos_create_shm_region(void){    int shmid = -1;    if (key == -1)        key = ftok(".", rand());    if ((shmid = shmget(key, shm_size, IPC_CREAT)) == -1)        (void) fprintf(stderr, "%s: shmget(2) failed: %s\n",                __func__, strerror(errno));    else        (void) fprintf(stderr,                "%s: created a %u bytes shared memory segment for key 0x%x with id 0x%x\n",                __func__, shm_size, key, shmid);    return shmid;}