Я пытаюсь выполнить упражнение, которое требует, чтобы: «процесс запуска должен быть разветвлен два раза. Отец и дети должны синхронизироваться, чтобы записывать одну за другой в первую позицию временного файла, читая написанные символы в трех разных файлах (по одному для каждого процесса). Программа должна использовать сигналы для реализации механизма синхронизации. "
До сих пор я пытался решить эту проблему следующим образом:
- P1 (отец) начинает читать / писать первым. Перед тем как остановиться (посредством вызова функции рейза), он посылает сигнал SIGCONT, чтобы разбудить F2 (второго ребенка)
- F2 читает из своего файла и пишет во временный файл. Затем он тоже останавливается и посылает сигнал SIGCONT, чтобы разбудить F1 (первого ребенка)
- F1 делает то же самое, что и F2, но активирует P1 и т. Д. *
Однако я не могу заставить работать код (в некоторых случаях после изменения порядка чтения и записи я получал большую часть последних в выводе, но поведение программы всегда было ошибочным и никогда не прерывалось).
Вот мой код:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#define TEMP_PATH "/tmp/mytempfile"
int main(int argc, char *argv[]){
FILE *writeFp;
FILE *rfpF1;
FILE *rfpF2;
FILE *rfpP1;
pid_t pid1, pid2;
char car;
char sizeOfChar = sizeof(char);
if (argc != 4 || !strcmp(argv[1], "--help")){
fprintf(stderr, "Usage : %s filePath1 filePath2 filePath3\n", argv[0]);
exit(EXIT_FAILURE);
}
if (access(argv[1], F_OK)==-1){
perror("access 1 error");
exit(EXIT_FAILURE);
}
if (access(argv[2], F_OK)==-1){
perror("access 2 error");
exit(EXIT_FAILURE);
}
if (access(argv[3], F_OK)==-1){
perror("access 3 error");
exit(EXIT_FAILURE);
}
if((writeFp = fopen(TEMP_PATH, "w")) == NULL){
fprintf(stderr, "Can't open temp file on writing.\n");
exit(EXIT_FAILURE);
}
if ((rfpP1 = fopen(argv[3], "r")) == NULL){
fprintf(stderr, "Can't open %s on reading.\n", argv[3]);
exit(EXIT_FAILURE);
}
switch(pid1 = fork()){
case -1:
perror("fork error");
exit(EXIT_FAILURE);
case 0:
/* F1 : first child */
if ((rfpF1 = fopen(argv[1], "r")) == NULL){
fprintf(stderr, "Can't open %s on reading.\n", argv[1]);
exit(EXIT_FAILURE);
}
raise(SIGSTOP);
while(fscanf(rfpF1, "%c", &car) != EOF){
if(fseek(writeFp, 0L, SEEK_SET) == -1){
perror("fseek error");
exit(EXIT_FAILURE);
}
if(fprintf(writeFp, "%c", car) != 1){
fprintf(stderr, "fprintf error. Terminating...\n");
exit(EXIT_FAILURE);
}
if(kill(getppid(), SIGCONT) == -1){
perror("F1 kill error");
exit(EXIT_FAILURE);
}
printf("F1 : i've written '%c'\n", car); fflush(stdout);
// If with the next read EOF is reached, the process doesn't have to stop...
if(fscanf(rfpF1, "%c", &car) == EOF)
break;
else{
if(fseek(rfpF1, -sizeOfChar, SEEK_CUR)){
perror("fseek error");
exit(EXIT_FAILURE);
}
raise(SIGSTOP);
}
}
fclose(rfpF1);
exit(EXIT_SUCCESS);
default :
break;
}
switch(pid2 = fork()){
case -1:
perror("fork 2 error");
exit(EXIT_FAILURE);
case 0:
/* F2 : second child */
if ((rfpF2 = fopen(argv[2], "r")) == NULL){
fprintf(stderr, "Can't open %s on reading.\n", argv[2]);
exit(EXIT_FAILURE);
}
raise(SIGSTOP);
while(fscanf(rfpF2, "%c", &car) != EOF){
if(fseek(writeFp, 0L, SEEK_SET) == -1){
perror("fseek error");
exit(EXIT_FAILURE);
}
if(fprintf(writeFp, "%c", car) != 1){
fprintf(stderr, "fprintf error. Terminating...\n");
exit(EXIT_FAILURE);
}
if(kill(pid1, SIGCONT) == -1){
perror("F2 kill error");
exit(EXIT_FAILURE);
}
printf("F2 : i've written '%c'\n", car); fflush(stdout);
if(fscanf(rfpF2, "%c", &car) == EOF)
break;
else{
if(fseek(rfpF2, -sizeOfChar, SEEK_CUR)){
perror("fseek error");
exit(EXIT_FAILURE);
}
raise(SIGSTOP);
}
}
fclose(rfpF2);
exit(EXIT_SUCCESS);
default:
/* P1 : Father */
// Wait for the children to be interrupted by SIGSTOP (which changes their states)
if(wait(NULL) == -1){
perror("wait 1 error");
exit(EXIT_FAILURE);
}
if(wait(NULL) == -1){
perror("wait 2 error");
exit(EXIT_FAILURE);
}
// P1 is the first to be reading and writing...
while(fscanf(rfpP1, "%c", &car) != EOF){
if(fseek(writeFp, 0L, SEEK_SET) == -1){
perror("fseek error");
exit(EXIT_FAILURE);
}
if(fprintf(writeFp, "%c", car) != 1){
fprintf(stderr, "fprintf error. Terminating...\n");
exit(EXIT_FAILURE);
}
if(kill(pid2, SIGCONT) == -1){
perror("P kill error");
exit(EXIT_FAILURE);
}
printf("P1 : i've written '%c'\n", car); fflush(stdout);
if(fscanf(rfpP1, "%c", &car) == EOF)
break;
else{
if(fseek(rfpP1, -sizeOfChar, SEEK_CUR)){
perror("fseek error");
exit(EXIT_FAILURE);
}
raise(SIGSTOP);
}
}
fclose(rfpP1);
break;
}
// Wait for the children...
if(wait(NULL) == -1){
perror("wait 1 error");
exit(EXIT_FAILURE);
}
if(wait(NULL) == -1){
perror("wait 2 error");
exit(EXIT_FAILURE);
}
fclose(writeFp);
exit(EXIT_SUCCESS);
}