簡體   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