Синхронизация в C после exec с использованием семафоров и разделяемой памяти - PullRequest
0 голосов
/ 09 января 2019

Я хочу использовать 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;
}

Как вы можете видеть, я выделяю память, используя именованные дескрипторы и mmap в каждом процессе. Я думал, что после этого у каждого процесса должна быть одна и та же память, но в основном процессе Players_sum по-прежнему равен 0. Я также пытался синхронизировать его с помощью семафоров (прокомментированная часть), но есть тупик. Использование сна в основном процессе также ничего не дает.

Однако, что меня больше всего озадачивает, так это то, что если я помещаю сон в процесс проигрывателя (также прокомментированный), то основной процесс по какой-то причине ждет, пока его дочерние элементы завершат работу, а затем произведет корректный вывод продукта (Players_sum равен его index) Что мне не хватает?

EDIT: Ладно, думаю, я понял это, если я удаляю close и shm_unlink в конце проигрывателя процесса, он работает как задумано. Я до сих пор не понимаю, почему это работает со сном в процессе проигрывателя.

...