У меня есть программа, которая должна сделать это:
- Основная программа создает кусок общей памяти (чтобы поделиться со своими будущими детьми) размером структуры с именем ClientInfo, которая содержит 2 целых числа и строку. Затем программа запрашивает у пользователя номер, который хранится в переменной n
- Основная программа создает n детей. Затем дети ждут сигнала SIGUSR1 от своего отца.
- Основная программа посылает сигнал SIGUSR1 всем своим детям.
- Каждый дочерний элемент читает строку из терминала, записывает ее в общую память, а также увеличивает на одну единицу оба общих целых числа. Затем он посылает SIGUSR1 своему отцу, спит от 1 до 10 секунд, а затем заканчивается.
- Каждый раз, когда отец получает SIGUSR1, он печатает содержимое общей памяти, а затем заканчивается только тогда, когда заканчиваются все его дети.
«Подвох» заключается в том, что это домашняя работа колледжа, и нам сказали, что отец должен иметь возможность распечатывать содержимое общей памяти один раз для каждого ребенка, то есть всего n раз . Также мы не можем использовать sigwait () или глобальные переменные (если только глобальные переменные не являются единственным способом).
Также каждый раз, когда я запускаю программу, она просто зависает на неопределенный срок, запрашивая n
Я знаю, что должно быть какое-то состояние гонки, но я действительно плох в этом и не могу понять, что не так.
Заранее спасибо.
Вот код:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define SHM_NAME "/shm_example"
#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define NAME_MAX 100
typedef struct{
int previous_id; //!< Id of the previous client.
int id; //!< Id of the current client.
char name[NAME_MAX]; //!< Name of the client.
} ClientInfo;
int main(void) {
int i,n,*pids;
int fd_shm;
int error;
struct sigaction act;
ClientInfo *example_struct;
sigset_t mask, oldmask;
sem_t *sem_write = NULL,*sem_read = NULL;
sigemptyset(&mask);
sigemptyset(&oldmask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
printf("Introduzca un numero:\n");
scanf("%d",&n);
if(!(pids = malloc(n*sizeof(int))))
exit(EXIT_FAILURE);
if ((sem_write = sem_open(SEM1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_read = sem_open(SEM2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
fd_shm = shm_open(SHM_NAME,O_RDWR | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR);
if(fd_shm == -1) {
fprintf (stderr, "Error creating the shared memory segment \n");
return EXIT_FAILURE;
}
error = ftruncate(fd_shm, sizeof(ClientInfo));
if(error == -1) {
fprintf (stderr, "Error resizing the shared memory segment \n");
shm_unlink(SHM_NAME);
return EXIT_FAILURE;
}
/* Map the memory segment */
example_struct = (ClientInfo *)mmap(NULL, sizeof(*example_struct), PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
if(example_struct == MAP_FAILED) {
fprintf (stderr, "Error mapping the shared memory segment \n");
shm_unlink(SHM_NAME);
return EXIT_FAILURE;
}
(example_struct->previous_id)=-1;
(example_struct->id)=0;
for(i=0;i<n;i++){
pids[i] = fork();
if (pids[i] < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pids[i] == 0) {
char nombre[NAME_MAX];
srand(getpid() ^ (i * 1091));
sigsuspend(&oldmask);
sem_wait(sem_write);
(example_struct->previous_id)++;
printf("Introduzca un nombre:\n");
scanf("%s",nombre);
memcpy(example_struct->name, nombre, sizeof(nombre));
(example_struct->id)++;
kill(getppid(),SIGUSR1);
sem_post(sem_write);
sleep(1 + (rand()%10));
exit(EXIT_SUCCESS);
}
}
sigprocmask(SIG_UNBLOCK, &mask, &oldmask);
kill(0,SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
while(1){
sigsuspend(&oldmask);
/*if(wait(NULL)<0){
sem_close(sem_write);
sem_close(sem_read);
sem_unlink(SEM1);
sem_unlink(SEM2);
munmap(example_struct, sizeof(*example_struct));
shm_unlink(SHM_NAME);
exit(EXIT_SUCCESS);
}*/
sem_wait(sem_read);
sem_wait(sem_write);
sem_post(sem_read);
printf("El cliente es %s con id %d y el previo es %d\n",example_struct->name,example_struct->id,example_struct->previous_id);
fflush(stdout);
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
sem_wait(sem_read);
sem_post(sem_write);
sem_post(sem_read);}
}