Я работаю по программе ниже. Предполагается, что он должен получить случайное целое от дочернего процесса и, в зависимости от переменной 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. Вопрос в том, в чем проблема? Это мой трубопровод? Является ли мое использование цикла совершенно неправильным? Любая помощь будет принята с благодарностью.
Я не вижу "Успех" нигде в вашем коде. Покажите полный пример. Включите функцию main и все #includes. Если бы я мог вырезать и вставить ваш код, я бы с удовольствием поиграл с ним. Я не хочу играть с ним в его нынешнем незавершенном состоянии.
@WilliamPursell это не требование. Это не похоже на то, что компьютер угадывает, является ли то, что вы печатаете, сообщением об ошибке, и если да, то не печатает его, если вы не используете stderr.
Приношу свои извинения за столь позднее обращение к вам, я обновил фрагмент, чтобы включить полную программу!
@user253751 user253751 Это, безусловно, правда, что компьютер не может догадаться, что сообщение является сообщением об ошибке, и отказаться печатать его на стандартный вывод. Это не меняет того факта, что неправильно выводить сообщения об ошибках на стандартный вывод. Во всяком случае, это делает более важным, чтобы программа работала правильно. Сообщения об ошибках принадлежат stderr.
Это определенно выглядит неправильно. Доступ к myCatalog[n] для n > 2 вызывает неопределенное поведение.
struct catalog myCatalog[3];
...
for(j = 0; j < 20; j++) {
printf("Description: %s\n", myCatalog[j].description);
Боже мой, я тестировал меньшие размеры, я, должно быть, забыл изменить это. Большое спасибо за то, что заметили это, потому что я знаю, что никогда бы не посмотрел туда!
Хотя у меня есть продолжение. Теперь все печатается нормально, за исключением того, что иногда печатается сообщение об отказе для элемента, который не был вызван 2 раза. Является ли мой подход к этой части неправильным? Кажется, я неправильно вычитаю item_count. Еще раз большое спасибо и извините, если я был жадным со своим вторым вопросом!
@sntovas Я бы посоветовал проверить значение, возвращаемое read, чтобы убедиться, что вы действительно получили значение.
Похоже, что поле item_price на самом деле не уменьшается, оно на самом деле принимает случайное значение, интересно, почему?
printf("error..."
неверно. Попробуйтеfprintf(stderr, "error....");
. Ошибки относятся к stderr.