繁体   English   中英

如何将结构映射为共享匿名内存?

[英]How to mmap a struct as shared anonymous memory?

我试图将结构映射为匿名共享内存,以便可以在多个子进程之间共享它。 但是,每当我在创建该结构的函数之外访问该结构时,都会遇到段错误。 该代码是从Trinity Fuzzer派生的,可以在这里https://github.com/kernelslacker/trinity找到。

首先,我们摘录了一个标头,该标头声明并定义了我们将要使用的结构。 注意shm在struct声明下声明为全局变量。

struct shm_s {
struct childdata **children;

struct stats_s stats;

unsigned int running_childs;

/* rng related state */
unsigned int seed;

#ifdef ARCH_IS_BIARCH
/* Check that 32bit emulation is available. */
unsigned int syscalls32_succeeded;
unsigned int syscalls32_attempted;
#endif

/* pids */
pid_t mainpid;
pid_t last_reaped;

/* various flags. */
enum exit_reasons exit_reason;
bool dont_make_it_fail;
bool spawn_no_more;
bool ready;
bool postmortem_in_progress;

/* Use dispatch queue instead of locks. */

/* main<>watchdog serial queue, for reap_child()
 *  provides exclusion so they don't both try at the same time. */
dispatch_queue_t reaper_queue;

/* to protect from multiple child processes from
 * trying to disable the same syscall at the same time. */
dispatch_queue_t syscalltable_queue;

/* child<>child serial queue, used so only one child spews debug output */
dispatch_queue_t bugQueue;

/* global debug flag.
 * This is in the shm so we can do things like gdb to the main pid,
 * and have the children automatically take notice.
 * This can be useful if for some reason we don't want to gdb to the child.
 */
bool debug;

};

extern struct shm_s *shm;

在c文件中,我们具有该结构的create和init函数。

struct shm_s *shm;

#define SHM_PROT_PAGES 30

void create_shm(void)
{
    void *p;
    void *redbefore, *redafter;
    unsigned int shm_pages;
    unsigned int wholesize;

    /* round up shm to nearest page size */
    shm_pages = ((sizeof(struct shm_s) + page_size - 1) & PAGE_MASK) / page_size;
    wholesize = (SHM_PROT_PAGES + shm_pages + SHM_PROT_PAGES) * page_size;

    /* Waste some address space to set up some "protection" near the SHM location. */
    p = alloc_shared(wholesize);

    redbefore = p;
    redafter = p + (SHM_PROT_PAGES + shm_pages) * page_size;

    /* set the redzones. */
    memset(redbefore, 0x77, SHM_PROT_PAGES * page_size);
    memset(redafter, 0x88, SHM_PROT_PAGES * page_size);

    /* set the redzones to PROT_NONE */
    mprotect(redbefore, SHM_PROT_PAGES * page_size, PROT_NONE);
    mprotect(redafter, SHM_PROT_PAGES * page_size, PROT_NONE);

    /* clear the whole shm. */
    shm = p + (SHM_PROT_PAGES * page_size);
    memset(shm, 0, shm_pages * page_size);
    printf("shm: redzone:%p. shmdata:%p. redzone:%p end:%p.\n",
       redbefore, shm, redafter, p + wholesize);
 }

void init_shm(void)
{
    unsigned int i;

    printf("shm is at %p\n", shm);

    shm->stats.total_syscalls_done = 1;

    shm->children = zmalloc(max_children * sizeof(struct childdata *));

    shm->bugQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);

    shm->reaper_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);

    shm->syscalltable_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);

   for_each_child(i)
   {
       struct childdata *child;

       child = alloc_shared(sizeof(struct childdata));
       shm->children[i] = child;

       child->pid = EMPTY_PIDSLOT;

       child->logfile = NULL;
   }
}

这是alloc_shared函数,它实际上创建共享内存。

void * alloc_shared(unsigned int size)
{
    void *ret;

    ret = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if (ret == MAP_FAILED) {
        printf("mmap %u failure\n", size);
        exit(EXIT_FAILURE);
    }
    /* poison, to force users to set it to something sensible. */
    memset(ret, rand(), size);
    return ret;
}

然后,最后在一个单独的文件中这样调用函数create_shm和init_shm。

create_shm();

init_shm();

每当进入shm-> stats.total_syscalls_done = 1时,程序就会崩溃。 在init_shm里面。 我打印了shm的地址,在alloc_shared和init_shm中创建后,它的地址是相同的,因此我不认为指针已损坏。 无论哪种方式,我都不明白为什么我无法访问create_shm()之外的结构。

根据OP在评论中的回答,printf的输出为:

shm: redzone:0x10a0ad000. shmdata:0x10a0cb000. redzone:0x10a0cb000 end:0x10a0e9000

请注意, shmdata与( redafter )之后的redzone位于相同的地址,都位于0x10a0cb000 这意味着shm_pages为零。

这行很可能是问题所在:

shm_pages = ((sizeof(struct shm_s) + page_size - 1) & PAGE_MASK) / page_size;

我猜PAGE_MASK0xfff 如果是这样,则该表达式将始终评估为0。正如chmike所指出的,由于无论如何都要用page_size进行除法,因此根本不需要使用PAGE_MASK 在这种情况下,您的代码应为:

shm_pages = (sizeof(struct shm_s) + page_size - 1) / page_size;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM