以下程序由命名信号量控制,并且应该执行此操作:
N_PROC
个孩子,并为每个孩子分配一个ID(对于已创建的第一个孩子, 0 ;对于第二个孩子, 1 一个等等)。pause()
等待父亲的信号。SIGUSR1
信号。SIGTERM
,等待他们完成,然后删除信号灯。我的问题是,无论我重新编译或重新运行该程序多少次,父级始终会打印相同的内容,因此2号子级始终是赢家。
谢谢。
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define SEM3 "/example_sem3"
#define FFILE "ejercicio9.txt"
#define N_PROC 3
int valor_semaforo(sem_t *sem) {
int sval;
if (sem_getvalue(sem, &sval) == -1) {
perror("sem_getvalue");
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
exit(EXIT_FAILURE);
}
return sval;
}
int main(void) {
sem_t *sem_write = NULL, *sem_read = NULL, *sem_count = NULL;
pid_t pid[N_PROC];
int i, numero, num[N_PROC], t;
struct sigaction act;
FILE *fp;
srand(time(NULL) + getpid());
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);
}
if ((sem_count = sem_open(SEM3, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == 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);
}
for (i = 0; i < N_PROC; i++) {
num[i] = 0;
pid[i] = fork();
if (pid[i] < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid[i] == 0) {
pause();
while (1) {
sem_wait(sem_write);
fp = fopen(FFILE, "a+");
fprintf(fp, "%d ", i);
fclose(fp);
sem_post(sem_write);
usleep(1 + (rand() % 100));
}
}
}
kill(0, SIGUSR1);
while (1) {
sleep(1);
sem_wait(sem_read);
sem_post(sem_count);
if (valor_semaforo(sem_count) == 1)
sem_wait(sem_write);
sem_post(sem_read);
fp = fopen(FFILE, "r");
while (fscanf(fp, "%d", &numero) > 0) {
printf("%d ", numero);
fflush(stdout);
for (i = 0; i < N_PROC; i++) {
if (numero == i)
(num[i])++;
if (num[i] == 20) {
printf("\nHa finalizado la carrera: el ganador es el proceso %d\n", i);
fflush(stdout);
act.sa_handler = SIG_IGN;
if (sigaction(SIGTERM, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
kill(0, SIGTERM);
while (wait(NULL) > 0);
sem_close(sem_write);
sem_close(sem_read);
sem_close(sem_count);
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
fclose(fp);
exit(EXIT_SUCCESS);
}
}
}
}
printf("\n");
fflush(stdout);
fp = fopen(FFILE, "w+");
fclose(fp);
sem_wait(sem_read);
sem_wait(sem_count);
if (valor_semaforo(sem_count) == 0)
sem_post(sem_write);
sem_post(sem_read);
}
答案 0 :(得分:1)
在扫描文件之前,请勿重置num
阵列。碰巧在您的系统上,第三个孩子首先写入了文件。
在使用以下方法解析文件之前,应清除此数组:
memset(num, 0, sizeof num);
或
for (i = 0; i < N_PROC; i++)
num[i] = 0;