简体   繁体   English

在 POSIX 中使用未命名信号量和共享 memory 时出现信号量死锁

[英]Semaphore deadlock when using unnamed semaphores in POSIX with shared memory

I have 2 semaphores.我有 2 个信号量。 I have a shared memory segment.我有一个共享的 memory 段。 I am trying to synchronize processes so that they wait for each other until a certain task is finished but when sem_post_util( sem_sync ) is used in the other processes just stop and the last processes continues and exits.我正在尝试同步进程,以便它们相互等待直到某个任务完成,但是当在其他进程中使用sem_post_util( sem_sync )时,它就会停止并且最后一个进程继续并退出。 Why doesn't it increment the unnamed semaphore in the shared memory?为什么它不增加共享 memory 中的未命名信号量?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../utils.h"
#include <signal.h>

#define SHARED_MEM "/shmm115"
#define SEM "nammed_sem115"
#define SEM_SYNC "unnamed_sem115"
#define SIZE 256
#define n_proc 3

sem_t *sem, sem_sync;
void* addr;

void cleanup(){
    sem_close( sem );
    sem_close( &sem_sync );
    munmap_util( addr, SIZE );
    shm_unlink( SHARED_MEM );
}

int main(){
    sem = sem_open( SEM, O_CREAT, 0666, 1 );/*opent the named semaphore we got*/

    /*Open shared memory segment and put a shared variable inside of it*/
    struct sigaction handler;
    handler.sa_handler = cleanup;

    sigaction( SIGINT, &handler, NULL);

    int fd;
    short count = 0;
    fd  = shm_open_util(SHARED_MEM, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IRWXU);

    struct stat stat_buf;
    fstat( fd, &stat_buf );
    if( stat_buf.st_size == 0){/*if it is the first one to write to it*/
        ftruncate_util(fd, SIZE);
        addr = mmap_util(0, SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
        memcpy( addr, &count, sizeof(short) );
        memcpy( addr+sizeof(short), &sem_sync, sizeof(sem_t) );
    }
    else
        addr = mmap_util(0, SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);

    close(fd);
    
    sem_init_util( &sem_sync, 1, 0 );

    sem_wait_util( sem );
    printf("Reading count\n");
    memcpy(&count, addr, sizeof(short));
    printf("Incrementing and writing the count: %d\n", count);
    count++;
    memcpy(addr, &count, sizeof(short));
    sem_post_util( sem );

    if( count == n_proc ){
        printf("%d unblocks all the processes\n", getpid());
        for( int i = 0 ; i<n_proc-1; ++i )
            sem_post_util( addr + sizeof(short) );
    }
    else{
        printf("%d pauses\n", getpid());
        sem_wait_util( &sem_sync );
    }

    printf("%d continues\n", getpid());
    sem_close( sem );
    sem_close( &sem_sync );
    munmap_util( addr, SIZE );
    shm_unlink( SHARED_MEM );
}

I am running it with ./a.out &./a.out &./a.out我用./a.out &./a.out &./a.out运行它

This is the output这是 output

[70] 19882
[71] 19883
Reading count
Incrementing and writing the count: 0
19882 pauses
Reading count
Incrementing and writing the count: 1
19883 pauses
Reading count
Incrementing and writing the count: 2
19884 unblocks all the processes
19884 continues

As you can see only the last process continued and processes 19882 and 19883 didn't continue and hanged there waiting.如您所见,只有最后一个进程在继续,进程 19882 和 19883 没有继续并挂在那里等待。 What am I doing wrong?我究竟做错了什么?

I want the semaphore to be in a shared memory along with some other data inside there.我希望信号量与其中的一些其他数据一起位于共享的 memory 中。

You didn't put up the source to util.h, but it seems you are acquiring the semaphore via sem_wait_util( &sem_sync );您没有将源代码提供给 util.h,但您似乎正在通过sem_wait_util( &sem_sync ); , but releasing it via sem_post_util( addr + sizeof(short) ); ,但通过sem_post_util( addr + sizeof(short) ); . .

I would have expected it to be released via sem_post_util(&sem_sync);我原以为它会通过sem_post_util(&sem_sync);发布。

Operations on copies of POSIX semaphores are undefined.对 POSIX 信号量副本的操作是未定义的。 You must post and wait on the very memory that was initialized by sem_init or sem_open .您必须在由sem_initsem_open初始化的 memory 上发布等待

So, the memcpy of your sem_sync , initialized in ordinary process memory, to shared memory won't make that memory a viable semaphore.因此,在普通进程 memory 中初始化的sem_syncmemcpy到共享 memory 不会使 memory 成为可行的。

Instead, try something like this:相反,尝试这样的事情:

struct shared_items {
  sem_t sem;
  short count;
} *shmem;

....

*shmem = mmap(0, sizeof(*shared_bundle), ..., shm_opened_fd, 0);

if (i_am_the_first_to_open_this_shared_memory) {
  sem_init(&shmem->sem, 1, 0);
}

....

sem_post(&shmem->sem);

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

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