gpt4 book ai didi

c - 复制到共享内存中的结构时获取 "bus error"

转载 作者:太空宇宙 更新时间:2023-11-04 08:04:49 25 4
gpt4 key购买 nike

我的“主”函数中有这段代码。

...
int data_size1 = sizeof(dados);

int fdDados = shm_open("/dados", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (fdDados<0){
perror("shm_open failed");
exit(1);
}

dados* shared_data_dados=(dados*) mmap(NULL, data_size1, PROT_READ|PROT_WRITE, MAP_SHARED, fdDados, 0);
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
char auxMsg[91];
sprintf(auxMsg, "Pid=%d, time=%s", getpid(), asctime(timeinfo));
printf(auxMsg);
strcpy((shared_data_dados->msg), auxMsg);
...

它包括以下.h:

typedef struct {
char msg[101];
} dados;

问题是,当我对结构执行 strcpy 时,它给我一个总线错误。我已经尝试将结构更改为 char*,并将 char* 放在 strcpy 的原始部分,但我仍然遇到相同的错误。printf 打印出正确的“消息”,所以这不应该是问题所在...

感谢任何帮助。

提前致谢!

最佳答案

  1. 您需要调用ftruncate(fdDados, SIZE)定义共享内存对象的大小 (SIZE),如 man 3 shm_open 中所述手册页。

    默认情况下,共享内存对象的大小为零字节。因为您的映射不受共享内存对象的支持,所以对映射的所有访问都会导致生成 SIGBUS 信号。

    这与您对文件进行内存映射,然后尝试访问文件末尾之后的映射完全相同。

  2. mmap()调用,第二个参数,映射的长度,应该是页面大小的倍数。

    您可以通过调用 sysconf(_SC_PAGESIZE) 获取页面大小。不要依赖魔术常量或预处理器宏。

  3. 由于上面的 (1) 和 (2),最好通过将所需的共享内存量四舍五入为页面大小的下一个倍数来计算 SIZE。例如:

    static size_t full_pages(const size_t size)
    {
    size_t page = sysconf(_SC_PAGESIZE);
    if (size < page)
    return page;
    else
    if (size % page)
    return size + page - (size % page);
    else
    return size;
    }

    在你的代码中,

    int     shared_fd, len;
    size_t shared_size;
    dados *shared_dados;

    shared_size = full_pages(sizeof *shared_dados);
    shared_fd = shm_open("/dados", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
    if (shared_fd == -1) {
    fprintf(stderr, "Cannot create shared object '/dados': %s.\n", strerror(errno));
    exit(EXIT_FAILURE);
    }

    if (ftruncate(shared_fd, (off_t)shared_size) == -1) {
    fprintf(stderr, "Cannot resize shared object '/dados': %s.\n", strerror(errno));
    exit(EXIT_FAILURE);
    }

    shared_dados = mmap(NULL, shared_size, PROT_READ | PROT_WRITE,
    MAP_SHARED, shared_fd, 0);
    if (shared_dados == MAP_FAILED) {
    fprintf(stderr, "Cannot map shared object '/dados': %s.\n", strerror(errno));
    exit(EXIT_FAILURE);
    }

    if (close(shared_fd) == -1) {
    fprintf(stderr, "Error closing shared object '/dados': %s.\n", strerror(errno));
    exit(EXIT_FAILURE);
    } else
    shared_fd = -1;

    /* TODO: LOCKING! */

    memset(shared_dados->msg, '\0', sizeof shared_dados->msg);
    len = snprintf(shared_dados->msg, sizeof shared_dados->msg, "pid=%ld", (long)getpid());
    if (len < 0 || len >= (int)sizeof shared_dados->msg) {
    /* The string we tried to print was too long to
    fit into the shared_dados->msg field. Oops. */
    }

    请注意,我假设dados 结构中的msg 成员是一个char 数组。如果是指向char的指针,就不行了。 (它将指向某个随机位置。即使您将它设置为指向共享内存对象内在此进程中,它也会指向其他进程中的错误地址,因为映射本质上是在一个随机地址。)

    另请注意 TODO: LOCKING! 注释。为确保其他进程只会看到完整的消息,您应该使用例如访问 msg 成员的互斥体。

关于c - 复制到共享内存中的结构时获取 "bus error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43609779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com