执行后使用信号量和共享内存在C中进行同步

时间:2019-01-09 11:23:28

标签: c exec semaphore shared-memory

我想在我的主程序中使用exec,并与我启动的所有子程序共享内存。到目前为止,这是我想出的: 使用fork的过程:

#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "manager.h"
#include <stdbool.h>

#define SHM_NAME "my_memory"

int main() {
void *mapped_mem;
int fd_memory = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED;
int n_and_m[2];
n_and_m[0] = 4;
n_and_m[1] = 4;
size_t memory_size = sizeof(sem_t) + sizeof(int)*n_and_m[0];
int *players_sum;
sem_t *manager;
size_t taken_memory = 0;
ftruncate(fd_memory, memory_size);
mapped_mem = mmap(NULL, memory_size, prot, flags, fd_memory, 0);
players_sum = (int *)(mapped_mem + taken_memory);
taken_memory += sizeof(int)*n_and_m[0];
manager = (sem_t *)(mapped_mem + taken_memory);
taken_memory += sizeof(sem_t);
for (int i = 0; i < n_and_m[0]; i++) {
    players_sum[i] = 0;
}
sem_init(manager, 1, 0);
char args[2];
for (int i = 0; i < n_and_m[0]; i++) {

   switch(fork()) {
       case 0:
        args[0] = i+48;
        args[1] = '\0';
        execl("./player", "player", args, (char *)NULL);
   }
}
for (int i = 0; i < n_and_m[0]; i++) {
    wait(0);
}
//sleep(3);
/*  for (int i = 0; i < n_and_m[0]; i++) {
    printf("started waiting with %d\n", i);
    if (sem_wait(manager)) {
       fprintf(stderr, "error while waiting on manager semaphore\n");
        exit(1);
    }
}*/
for (int i = 0; i < n_and_m[0]; i++) {
    printf("%d\n", players_sum[i]);
}
close(fd_memory);
shm_unlink(SHM_NAME);
sem_destroy(manager);
return 0;
}

播放器进程,由主进程启动:

#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <stdbool.h>

#define SHM_NAME "my_memory"
int main(int argc, char **argv) {
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED; // nie ma pliku, fd winno być -1
int n_and_m[2];
n_and_m[0] = 4;
n_and_m[1] = 4;
int fd_memory = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
size_t memory_size =  sizeof(sem_t) + sizeof(int)*n_and_m[0];
ftruncate(fd_memory, memory_size);
int *players_sum;
sem_t *manager;
size_t taken_memory = 0;
void *mapped_mem = mmap(NULL, memory_size, prot, flags, fd_memory, 0);
players_sum = (int *)(mapped_mem + taken_memory);
taken_memory += sizeof(int)*n_and_m[0];
manager = (sem_t *)(mapped_mem + taken_memory);
taken_memory += sizeof(sem_t);
int i = atoi(argv[1]);
//sleep(2);
printf("I am %d\n", i);
players_sum[i] = i;
/* if (sem_post(manager)) {
    fprintf(stderr, "error on post");
    exit(1);
}*/
close(fd_memory);
shm_unlink(SHM_NAME);
return 0;
}

如您所见,我在每个进程中都使用名为descryptor和mmap的内存进行分配。我认为此后每个进程应该具有相同的内存,但是在主进程中player_sum仍为0。我也尝试使用信号量(带注释的部分)对其进行同步,但是存在死锁。在主要过程中使用睡眠也无济于事。

但是,最让我感到困惑的是,如果我在播放器进程中进入睡眠状态(也已评论),则主进程出于某种原因等待其子进程完成,然后产生正确的输出(players_sum等于其输出索引)我想念什么?

编辑: 好的,我想我已经弄明白了,如果我在流程播放器的末尾删除close和shm_unlink,它将按预期工作。我仍然不知道为什么它可以在播放器过程中与睡眠一起使用。

0 个答案:

没有答案