繁体   English   中英

使用信号量与POSIX共享内存时的分段错误

[英]Segmentation fault when using semaphores with POSIX shared memory

我有一些简单的代码问题,我正在写自己的信号量和POSIX共享内存。

这个想法是一个程序,即服务器,打开共享内存并将结构(包含信号量和数组)写入其中。 然后它等待输入并在输入后递增信号量。

同时,客户端打开共享内存,等待信号量,并在服务器递增后读取结构。

服务器似乎工作正常,但是我在sem_wait函数中遇到了客户端的段sem_wait (甚至在服务器递增之前)。 我无法弄清楚出了什么问题。

服务器代码:

#define _XOPEN_SOURCE 500

#include <stdio.h>

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

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

#include <semaphore.h>

#include <stdbool.h>

#define ARRAY_MAX 1024

typedef struct {
    sem_t inDataReady;
    float array[ARRAY_MAX];
    unsigned arrayLen;
} OsInputData;

int main() {

    int shm_fd;
    OsInputData *shm_ptr;

    if((shm_fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666)) == -1) {
        printf("shm_open failure\n");
        return 1;
    }

    if(ftruncate(shm_fd, sizeof(OsInputData)) == -1) {
        printf("ftruncate failure\n");
        return 1;
    }

    if((shm_ptr = (OsInputData*)mmap(0, sizeof(OsInputData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
        printf("mmap failure\n");
        return 1;
    }

    sem_init(&(shm_ptr->inDataReady), true, 0);

    shm_ptr->array[0] = 3.0;
    shm_ptr->array[1] = 1.0;
    shm_ptr->array[2] = 2.0;
    shm_ptr->array[3] = 5.0;
    shm_ptr->array[4] = 4.0;

    shm_ptr->arrayLen = 5;

    getchar();
    sem_post(&(shm_ptr->inDataReady));

    sem_destroy(&(shm_ptr->inDataReady));

    munmap(shm_ptr, sizeof(OsInputData));
    close(shm_fd);

    return 0;
}

客户代码:

#define _XOPEN_SOURCE 500

#include <stdio.h>

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

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

#include <semaphore.h>

#include <stdbool.h>

#define ARRAY_MAX 1024

typedef struct {
    sem_t inDataReady;
    float array[ARRAY_MAX];
    unsigned arrayLen;
} OsInputData;

int main() {

    int shm_fd;
    OsInputData *shm_ptr;

    if((shm_fd = shm_open("/my_shm", O_RDONLY, 0666)) == -1) {
        printf("shm_open failure\n");
        return 1;
    }

    if((shm_ptr = (OsInputData*)mmap(0, sizeof(OsInputData), PROT_READ, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
        printf("mmap failure\n");
        return 1;
    }

    sem_wait(&(shm_ptr->inDataReady));

    printf("%u\n", shm_ptr->arrayLen);

    munmap(shm_ptr, sizeof(OsInputData));
    close(shm_fd);

    return 0;
}

实际结果取决于您的系统,但通常您的程序包含错误。 您不能销毁另一个进程/线程可以访问的信号量。 仅仅因为你执行了sem_post并不意味着你的系统已经切换到等待它的进程。 当你摧毁它时,另一个人可能仍在使用它。

在这种情况下,SIGSEGV是一种善意。 很少有程序员检查sem_wait的返回值,这可能导致程序认为它们不同步时会同步。

事实证明,我必须使用读取和写入权限打开客户端中的共享内存,并在mmap相应地更新保护。

相当愚蠢的错误,因为很明显客户端需要写权限才能实际修改信号量。

因此,在客户端代码中,以下更改解决了它

...
shm_fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0755)
...
shm_ptr = (OsInputData*)mmap(0, sizeof(OsInputData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0)
...

暂无
暂无

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

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