C - Отправка данных туда и обратно между процессами

Я работаю по программе ниже. Предполагается, что он должен получить случайное целое от дочернего процесса и, в зависимости от переменной item_count, вернуть соответствующее сообщение дочернему процессу с помощью каналов. Проблема в том, что при выполнении я получаю много неожиданного поведения, см. ниже. myCatalog — это структура.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include <string.h>

struct catalog {
    char description[128];
    int price;
    int item_count;
};

int main() {
    int i, j, k, fd1[5][2], fd2[5][2];
    struct catalog myCatalog[3];
    pid_t pid;
    int itemNo;
    char message[24];
    char messageFailure[] = "Failure.", messageSuccess[] = "Success!";;        

 

    for(i = 0; i < 5; i++) {
        if (pipe(fd1[i]) == -1) {
                printf("Error opening pipe 1!\n");
                exit(1);
        }

        if (pipe(fd2[i]) == -1) {
            printf("Error opening pipe 2!\n");
            exit(1);
        }

        pid = fork();

        if (pid == 0) { //Child
            time_t t;
            srand((int)time(&t) % getpid());
            
            close(fd1[i][0]);  //Close reading end of fd1
            close(fd2[i][1]);  //Close writing end of fd2
            
            for(k = 0; k < 10; k++) {
                itemNo = rand() % 21;
                write(fd1[i][1], &itemNo, sizeof(int));
                sleep(1);
                read(fd2[i][0], message, sizeof(message));
                printf("%s\n", message);
            }
            printf("Hello from child process %d\n", getpid());
            close(fd1[i][1]);
            close(fd2[i][0]);
            exit(0);
        }
        else if (pid > 0) { //Parent
            int item;

            close(fd1[i][1]);  //Close writing end of fd1
            close(fd2[i][0]);  //Close reading end of fd2

            if (i == 0) {
                for(j = 0; j < 20; j++) {
                    snprintf(myCatalog[j].description, sizeof(myCatalog[j].description), "Item #%d", j);
                    myCatalog[j].price = (rand() % 10) + 1;
                    myCatalog[j].item_count = 2;
                }
                for(j = 0; j < 20; j++) {
                    printf("Description: %s\n", myCatalog[j].description);
                    printf("Price: %d\n", myCatalog[j].price);
                    printf("Count: %d\n", myCatalog[j].item_count);
                }   
            }
            for(j = 0; j < 10; j++) {
                read(fd1[i][0], &item, sizeof(int));
                printf("%d\n", item);
                myCatalog[item].item_count = myCatalog[item].item_count - 1;
                if (myCatalog[item].item_count <= 0) {
                    write(fd2[i][1], messageFailure, sizeof(messageFailure));
                }
                else {
                    write(fd2[i][1], messageSuccess, sizeof(messageSuccess));                
                }
                sleep(1);
            }
            printf("Hello from parent process %d\n", getpid());
            close(fd1[i][0]);
            close(fd2[i][1]);
            wait(NULL);
        }
        else {
            printf("Error forking!");
            exit(1);
        }

    }
    return 0;
}

Пример вывода для одного дочернего процесса выглядит следующим образом:

Hello from parent process 11868
Hello from child process 11890
6
Success!
4
Success!
3
Success!
4
3
16
Success!
14
3
6
3
18
3
20
3
18
3

Что он должен сделать, так это напечатать число, а затем либо успех, либо неудачу и т. д. Кроме того, иногда он выдает 13 чисел вместо 10. Вопрос в том, в чем проблема? Это мой трубопровод? Является ли мое использование цикла совершенно неправильным? Любая помощь будет принята с благодарностью.

printf("error..." неверно. Попробуйте fprintf(stderr, "error....");. Ошибки относятся к stderr.
William Pursell 18.12.2020 18:09

Я не вижу "Успех" нигде в вашем коде. Покажите полный пример. Включите функцию main и все #includes. Если бы я мог вырезать и вставить ваш код, я бы с удовольствием поиграл с ним. Я не хочу играть с ним в его нынешнем незавершенном состоянии.

William Pursell 18.12.2020 18:13

@WilliamPursell это не требование. Это не похоже на то, что компьютер угадывает, является ли то, что вы печатаете, сообщением об ошибке, и если да, то не печатает его, если вы не используете stderr.

user253751 18.12.2020 18:32

Приношу свои извинения за столь позднее обращение к вам, я обновил фрагмент, чтобы включить полную программу!

sntovas 18.12.2020 18:32

@user253751 user253751 Это, безусловно, правда, что компьютер не может догадаться, что сообщение является сообщением об ошибке, и отказаться печатать его на стандартный вывод. Это не меняет того факта, что неправильно выводить сообщения об ошибках на стандартный вывод. Во всяком случае, это делает более важным, чтобы программа работала правильно. Сообщения об ошибках принадлежат stderr.

William Pursell 18.12.2020 19:29
Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
5
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это определенно выглядит неправильно. Доступ к myCatalog[n] для n > 2 вызывает неопределенное поведение.

  struct catalog myCatalog[3];
  ...
  for(j = 0; j < 20; j++) {
          printf("Description: %s\n", myCatalog[j].description);

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

sntovas 18.12.2020 18:48

Хотя у меня есть продолжение. Теперь все печатается нормально, за исключением того, что иногда печатается сообщение об отказе для элемента, который не был вызван 2 раза. Является ли мой подход к этой части неправильным? Кажется, я неправильно вычитаю item_count. Еще раз большое спасибо и извините, если я был жадным со своим вторым вопросом!

sntovas 18.12.2020 18:53

@sntovas Я бы посоветовал проверить значение, возвращаемое read, чтобы убедиться, что вы действительно получили значение.

William Pursell 18.12.2020 19:10

Похоже, что поле item_price на самом деле не уменьшается, оно на самом деле принимает случайное значение, интересно, почему?

sntovas 18.12.2020 19:18

Другие вопросы по теме