Я хочу использовать 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 в конце проигрывателя процесса, он работает как задумано. Я до сих пор не понимаю, почему это работает со сном в процессе проигрывателя.