Как синхронизировать дочерние процессы? Доброго времени суток!
Лазил я по форумам и наткнулся на задачку. Необходимо при помощи двух дочерних процессов читать и выводить в терминал содержимое файла. Сначала первый процесс считывает 10 байт, потом второй - следующие 10 байт. И так до конца. В программирование не особо силен, но при помощи System V семафоров, вроде как написал что-то работающее. Но возникает проблема, файл иногда печатается не совсем корректно, некоторые фрагменты документа теряются. Если считывать файл побайтово, то все корректно. При изменении размера буфера, в который считывается фрагмент файла, иногда возникают выше описанные проблемы. Хотелось бы понять в чем причина. Код под спойлером.Код#include
#include
#include

#include
#include
#include
#include
#include
#include

#define SIZE 10

union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
#if defined(__linux__)
struct seminfo *__buf;
#endif
};

int main(void)
{
int fd;
int ch;
int pid[2];
int status[2];
int semaphore;
int semval;
int len;
union semun arg;
char buff[SIZE + 1];

setbuf(stdout, NULL);
memset(buff, 0, SIZE + 1);

fd = open("data", O_RDONLY);

semaphore = semget(IPC_PRIVATE, 1, 0);
if(semaphore == -1) {
perror("semget");
exit(EXIT_FAILURE);
}

arg.val = 1;
if(semctl(semaphore, 0, SETVAL, arg) == -1) {
perror("semctl");
exit(EXIT_FAILURE);
}

pid[0] = fork();
if(!pid[0]) {
while(1) {
semval = semctl(semaphore, 0, GETVAL);
if(semval != 1)
continue;

memset(buff, 0, SIZE + 1);
len = read(fd, buff, SIZE);
if(!len) {
arg.val = 2;
semctl(semaphore, 0, SETVAL, arg);
break;
}
else if(len > 0) {
printf("%s", buff);
arg.val = 1;
semctl(semaphore, 0, SETVAL, arg);
}
else if(len == -1) {
perror("read");
break;
}
}

exit(EXIT_SUCCESS);
}
else if(pid[0] == -1) {
perror("fork");
exit(EXIT_FAILURE);
}

pid[1] = fork();
if(!pid[1]) {
while(1) {
semval = semctl(semaphore, 0, GETVAL);
if(semval != 2)
continue;

memset(buff, 0, SIZE + 1);
len = read(fd, buff, SIZE);
if(!len) {
arg.val = 2;
semctl(semaphore, 0, SETVAL, arg);
break;
}
else if(len > 0) {
printf("%s", buff);
arg.val = 2;
semctl(semaphore, 0, SETVAL, arg);
}
else if(len == -1) {
perror("read");
break;
}
}

exit(EXIT_SUCCESS);
}
else if(pid[1] == -1) {
perror("fork");
exit(EXIT_FAILURE);
}

while(1) {
waitpid(pid[0], &status[0], 0);
waitpid(pid[1], &status[1], 0);

if(WIFEXITED(status[0]) && WIFEXITED(status[1]))
break;
}

exit(EXIT_SUCCESS);
}
Буду благодарен за любую помощь и критику :)
UPD. Проблема была в мусоре, который находился в буфере. Код обновил.

21 Авг 2019 в 06:22
204 +1
0
Ответы
1

Давайте проанализируем вашу программу. В вашем коде есть несколько потенциальных проблем, которые могут привести к некорректной работе программы:

Использование глобального файлового дескриптора fd. Один и тот же файловый дескриптор используется в обоих дочерних процессах для чтения данных из файла. Это может вызвать проблемы синхронизации между процессами. Рекомендуется использовать разные файловые дескрипторы для каждого процесса.

Обнуление буфера buff после каждого считывания. Поскольку вы обнуляете буфер после каждого чтения, вы теряете данные предыдущего процесса перед передачей его следующему. Вместо этого вам нужно сохранять данные в буфере и передавать его следующему процессу.

Необходимость правильной синхронизации с использованием семафоров. В вашем коде семафоры используются не совсем корректно. Например, значение семафора semval проверяется в цикле, что может вызвать зацикливание процессов.

Отсутствие обработки случаев ошибок. В вашем коде не обрабатываются все возможные ошибки, такие как ошибки при открытии файла, чтении данных и т.д.

Рекомендации для улучшения вашей программы:

Используйте отдельный файловый дескриптор для каждого дочернего процесса.Измените логику считывания данных из файла, чтобы сохранять данные в буфере и передавать его следующему процессу.Пересмотрите логику использования семафоров для правильной синхронизации между процессами.Добавьте обработку ошибок для всех операций ввода/вывода и системных вызовов.

Надеюсь, эти рекомендации помогут вам улучшить вашу программу и избежать проблем синхронизации дочерних процессов. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать. Удачи!

20 Апр в 13:19
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 84 622 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир