#c #pipe #fork #ipc
#c #канал #форк #ipc
Вопрос:
Я работаю над приведенной ниже программой. Предполагается, что он получает случайное значение int из дочернего процесса и, в зависимости от переменной 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(amp;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], amp;itemNo, sizeof(int));
sleep(1);
read(fd2[i][0], message, sizeof(message));
printf("%sn", message);
}
printf("Hello from child process %dn", 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: %sn", myCatalog[j].description);
printf("Price: %dn", myCatalog[j].price);
printf("Count: %dn", myCatalog[j].item_count);
}
}
for(j = 0; j < 10; j ) {
read(fd1[i][0], amp;item, sizeof(int));
printf("%dn", 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 %dn", 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
Что он должен сделать, это напечатать число, затем либо успех, либо сбой и т.д. Кроме того, иногда вместо 10 он выдает 13 чисел. Вопрос в том, в чем проблема? Это мой конвейер? Является ли мое использование цикла полностью неправильным?
Любая помощь будет принята с благодарностью.
Комментарии:
1.
printf("error..."
неверно. Попробуйтеfprintf(stderr, "error....");
. Ошибки относятся к stderr.2. Я не вижу «Успеха» нигде в вашем коде. Покажите полный пример. Включить
main
функцию и все #includes . Если бы я мог вырезать и вставить ваш код, я бы с удовольствием поиграл с ним. Я не хочу играть с ним в его текущем незавершенном состоянии.3. @WilliamPursell это не является обязательным требованием. Это не похоже на то, что компьютер угадывает, является ли то, что вы печатаете, сообщением об ошибке, и если да, то не печатает его, если вы не используете stderr.
4. Приношу свои извинения за то, что добрался до вас так поздно, я обновил фрагмент, включив в него полную программу!
5. @user253751 Безусловно, верно, что компьютер не может догадаться, что сообщение является сообщением об ошибке, и отказывается печатать его в стандартный вывод. Это не меняет того факта, что печатать сообщения об ошибках в стандартный вывод некорректно. Во всяком случае, это делает более важным, чтобы программа поступала правильно. Сообщения об ошибках принадлежат stderr.
Ответ №1:
Это, конечно, выглядит неправильно. Доступ myCatalog[n]
для n> 2 вызывает неопределенное поведение.
struct catalog myCatalog[3];
...
for(j = 0; j < 20; j ) {
printf("Description: %sn", myCatalog[j].description);
Комментарии:
1. О боже, я тестировал меньшие размеры, должно быть, я забыл его изменить. Большое вам спасибо за то, что заметили это, потому что я знаю, что никогда бы туда не заглянул!
2. Однако у меня есть продолжение. Теперь все печатается нормально, за исключением того, что иногда выводится ошибка для элемента, который не вызывался 2 раза. Является ли мой подход к этой части неправильным? Кажется, я неправильно вычитаю item_count. Еще раз большое вам спасибо и извините, если я жадничаю со своим вторым вопросом!
3. @sntovas Я бы предложил проверить значение, возвращаемое,
read
чтобы убедиться, что вы действительно получили значение.4. Похоже, что поле item_price на самом деле не уменьшается, оно фактически принимает случайное значение, интересно, почему?