当前位置: 首页 > 知识库问答 >
问题:

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

苏俊友
2023-03-14

我在编写一些简单的代码来自学信号量和POSIX共享内存时遇到了问题。

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

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

服务器似乎工作正常,但是我在客户端的sem_wait函数处立即遇到了一个segfault(甚至在服务器增加它之前)。我想不出哪里出了问题。

服务器代码:

#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;
}

共有1个答案

阚正真
2023-03-14

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

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

 类似资料:
  • 它编译得很好,但是当我试图运行它时,当它到达部分时,我得到了一个分段错误。我在其他地方读到过,不应该创建指向信号量的指针,但是当我没有创建并尝试时,我遇到了一个关于需要lvalue的错误。任何帮助都将不胜感激。

  • 我有两个使用System V共享内存进行通信的程序。 这两个程序都正常工作,但我想添加命名信号量以避免竞争条件。 我尝试了以下方法: 没有信号量,程序可以工作,但有了信号量,共享内存中不会写入任何内容。我做错了什么?当我使用System V共享内存时,是否可能使用这些信号量?

  • 我需要编写一个程序,它正在创建N个数量的子进程,每一个进程都将一个添加到共享内存变量中。我的想法是使用信号量和共享内存,但进程之间并没有相互等待,共享内存变量也没有像我希望的那样工作。 MyDefs.H Main.C 奴隶Proc.c

  • 我想创建一个共享内存和信号量的C程序。应该有两个子进程。两个孩子都有一个不同的int数。然后有一个目标号码,应该写在共享内存中。现在两个孩子都应该从进球数中减去他们的数字,直到进球数低于或等于0。我不希望出现比赛条件。这就是为什么我尝试使用信号量。但对我没用。下面是我的代码: