Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8

Неименованные пайпы

18.10.2017, 17:37. Показов 982. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не совсем работают пайпы. Пайп для приёма данных от родителя в дочернюю не работает, а пайп приёма данных от дочерней в родительскую программы работает.

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

Родительская программа:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
 
int main(int argc, char *argv[]){
        int i, pid[5], status, stat, total;
        ssize_t ret;
        char buf[80];
        int ret1;
        total = 0;
        char arg1[3] = "";
        char arg2[3] = "";
        char arg[3] = "";
        printf("Begin\n");
        int fd[10][2];
        for(i = 0; i < 10; i++){
                pipe(fd[i]);
        }
        int n = 1;
        for (i = 0; i < n; i++){
                pid[i] = fork();
                if(pid[i] == 0){
                        close(fd[2 * i + 1][0]);
                        close(fd[2 * i][1]);
                        printf("%d close pipes!\n", getpid());
                        sprintf(arg1, "%d", fd[2 * i][0]); //toChild
                        printf("%d arg1 = %s sizeof = %lu\n", getpid(), arg1, strlen(arg1));
                        sprintf(arg2, "%d",fd[2 * i + 1][1]); //from child
                        printf("%d arg2 = %s sizeof = %lu\n", getpid(), arg2,strlen(arg1));
                        sprintf(arg, "%d", i + 1); //stroka
                        printf("%d arg = %s sizeof = %lu\n", getpid(), arg, strlen(arg));
 
                        if(execl("./lab41", "lab41", arg1, arg2, NULL) < 0){
                                printf("%d's errno = %s\n", i,  strerror(errno));
                                printf("Error to start %d process\n", i);
                                exit(-1);
                        }
                        else {
                                printf("Processing started (pid = %d)\n", pid[i]);
                        }
 
                }
                else {
                        close(fd[2 * i][0]);
                        close(fd[2 * i + 1][1]);
                        write(fd[2 * i][1], arg, strlen(arg) + 1);
                }
        }
        sleep(2 * i);
        for(i = 0; i < n; i++){
                while((ret = read(fd[2 * i + 1 ][0]/* fd2[0]*/, buf, sizeof(buf))) > 0){
                        ret1=atoi(buf);
                }
                status = waitpid(pid[i], &stat, 0);
                if(pid[i] == status) {
                        printf("Proc %d is done, result = %d\n", i, ret1);
                        total += ret1;
                }
        }
        printf("Total = %d\n", total);
        return (total);
}
Дочерняя программа:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
        int fd1;
        int fd2;
        FILE *hdl1;
        FILE *hdl2;
        int total = 0;
        int matr[3];
        int vect[3];
        int i = 0;
        char line[80];
        char *ln = line;
        int stren = 0;
        int num = 0;
 
        if (argc < 3 ) {
                printf("Need more arguments to process! ""\n");
                return (0);
        }
        fd1 = atoi(argv[1]);
        printf("(PID: %d)fd1 toRead = %d\n", getpid(),fd1);
        fd2 = atoi(argv[2]);
        printf("(PID: %d)fd2 toWrite = %d\n", getpid(), fd2);
        num = read(fd1, line, sizeof(ln) + 1);
        printf("(PID: %d)sizeof num = %d\n", getpid(),num);
        printf("(PID: %d)value num = '%s'\n", getpid(), line);
        printf("(PID: %d)num = %d\n", getpid(), num);
        if ((hdl1 = fopen("matrix.txt", "r")) != NULL){
                while (!feof(hdl1)) {
                        fscanf(hdl1, "%d %d %d", &matr[i], &matr[i + 1], &matr[i + 2]);
                        if ((char)fgetc(hdl1) == 0x0A) stren++;
                        if (stren == atoi(line)) break;
                }
                fclose(hdl1);
                if ((hdl2 = fopen("vector.txt", "r")) != NULL){
                        while (!feof(hdl2)) {
                                fscanf(hdl2, "%d\n%d\n%d\n", &vect[i], &vect[i + 1], &vect[i + 2]);
                        }
                        fclose(hdl2);
                }
                else {
                        printf("Can't open file 2!\n");
                        return (0);
                }
                total = 0;
                for (i = 0; i < 3; i++){
                        total += matr[i] * vect[i];
                }
                printf("(PlD: %d)Result = %d\n", getpid(), total);
        }
        else {
                printf("Can't open file 1!\n");
                return (0);
        }
        sprintf(ln, "%d\n", total);
        write(fd2, line, strlen(ln) - 1);
        return (total);
}
Вывод консоли:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
Begin
13802 close pipes!
13802 arg1 = 3 sizeof = 1
13802 arg2 = 6 sizeof = 1
13802 arg = 1 sizeof = 1
(PID: 13802)fd1 toRead = 3
(PID: 13802)fd2 toWrite = 6
(PID: 13802)sizeof num = 1
(PID: 13802)value num = ''
(PID: 13802)num = 1
(PlD: 13802)Result = 86
Proc 0 is done, result = 86
Total = 86
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.10.2017, 17:37
Ответы с готовыми решениями:

Неименованные каналы POSIX
Всем привет, делаю лабу по операционным системам. Не понимаю один момент. Задание: Родительский процесс создаёт два дочерних...

Пайпы
как в делфи создать именованные пайпы. вроде много что прочитал но так и не понятно что и как делать, может кто объяснить что и как надо...

Пайпы и WaitForMultipleObjects
Добрый день. Имеется несколько пайпов, созданных через CreatePipe. В каждый из них перенаправляется вывод консоли дочерних процессов....

15
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
18.10.2017, 21:30
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
C
1
2
3
4
5
if(pid[i] == 0){
* * * * * * * * * * * * close(fd[2 * i + 1][0]);
* * * * * * * * * * * * close(fd[2 * i][1]);
* * * * * * * * * * * * printf("%d close pipes!\n", getpid());
* * * * * * * * * * * * sprintf(arg1, "%d", fd[2 * i][0]); //toChild
Чёт я недопонял. Закрываем у потомка каналы, а затем пытаемся в них что-то писать...
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
18.10.2017, 22:56  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Чёт я недопонял. Закрываем у потомка каналы, а затем пытаемся в них что-то писать...
Нет, не так.
В этом ветвлении мы находимся в дочернем процессе и закрываем адреса каналов для записи Родительский->Дочерний (потому что в дочерней программы мы должны считывать из этого пайпа) и чтения Дочерний->Родительский (в дочерней программе мы должны записывать в этот пайп).
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 19:58
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
C
1
2
if(pid[i] == 0){
* * * * * * * * * * * * close(fd[2 * i + 1][0]);
А тут закрываем канал следующего потомка?
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 21:08  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
А тут закрываем канал следующего потомка?
Конкретно этого потока.
Пайп, первый индекс которого четен, для записи из родительского в дочерний.
Пайп, первый индекс которого нечетен, для записи из дочернего в родительский.
В close мы закрываем адреса, которые дочернему/родительскому процессу не нужны. (Насколько я понял из лекций и материалов в сети).
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 21:35
Цитата Сообщение от drfaust Посмотреть сообщение
2 * i + 1
Но это же следующая пара дескрипторов, а не текущая, или я вообще не могу въехать в логику...
Т.е. потомок тут
Цитата Сообщение от drfaust Посмотреть сообщение
fd[2 * i][1]
закрывает свой "нечётный", а тут
Цитата Сообщение от drfaust Посмотреть сообщение
fd[2 * i + 1][0]
закрывает "чужой", точнее следующий, "чётный"

И зачем делать вдвое больше пар дескрипторов для каналов, нежели у нас потоков. Т.е. при 5 детях мы создаём 20 дескрипторов(10 пар)
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 22:13  [ТС]
i идет с нуля же.

i = 0
close(fd[0][1]);
close(fd[1][0]);

Они относятся к одной паре дескрипторов для общения первого дочернего процесса с родителем

i = 1
close(fd[2][1]);
close(fd[3][0]);

А вот эти два относятся к другой паре дескрипторов для общения второй дочерней программы с родителем и так далее.

Надеюсь, логика программы стала понятней. Т.к. процессов дочерних 5, следовательно нужно 10 каналов для взаимного общения всех дочерних процессов с родителем, а поскольку канал имеет два дескриптора для чтения и записи, получается массив fd имеет 20 ячеек.
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 22:37
Нет.
Первая пара: fd[0][0] и fd[0][1]; вторая fd[1][0] и fd[1][1]
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
следовательно нужно 10 каналов для взаимного общения всех дочерних процессов
5 каналов, каждый состоит из двух файлов(можно сказать дескрипторов), один на чтение, второй на запись, т.е. 10 дескрипторов, а не 20

Простейший пример тут https://studopedia.org/3-107577.html смотрим второй - там у родителя только один потомок, и как видим только один канал, а не два. А вот сам канал состоит из двух файловых дескрипторов.
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 22:43  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Нет.
Первая пара: fd[0][0] и fd[0][1]; вторая fd[1][0] и fd[1][1]

5 каналов, каждый состоит из двух файлов(можно сказать дескрипторов), один на чтение, второй на запись, т.е. 10 дескрипторов, а не 20

Простейший пример тут https://studopedia.org/3-107577.html смотрим второй - там у родителя только один потомок, и как видим только один канал, а не два. А вот сам канал состоит из двух файловых дескрипторов.
Не вижу противоречий. Пайпов 10: fd[0], fd[1], fd[2], fd[3], fd[4], fd[5], fd[6], fd[7], fd[8], fd[9]. Прошу, посмотрите внимательней на инициализацию пайпов.

Цитата Сообщение от WillfordRockwel Посмотреть сообщение
C
1
2
3
for(i = 0; i < 10; i++){
 pipe(fd[i]);
 }
При помощи второго индекса мы получаем адреса. В приведённом выше Вами примере close() закрывает адрес для программы.

upd: я не спорю с тем, что могу неверно пользоваться терминологией.
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 22:46
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
Не вижу противоречий. Пайпов 10:
достаточно 5
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 22:51  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
достаточно 5
Как? Пайп однонаправленный же. А нам нужно помимо того, что получать из родительского процесса значение по пайпу в дочернее, так и передавать значение из дочернего процесса в родительский по пайпу. Таким образом получаем, что на одну пару родитель-дочь имеем 2 пайпа. А поскольку таких пар 5, имеем 10 пайпов.

Если я не прав, укажите на это пожалуйста, где ошибка в моих рассуждениях.
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 23:09
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
Пайп для приёма данных от родителя в дочернюю не работает, а пайп приёма данных от дочерней в родительскую программы работает.
Так, стоп.
Теперь я вообще ничего не понял.

Задание:
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
На вход дочерней программы приходят адреса пайпов для общения с родителем. По самому пайпу приходит целочисленное число в дочернюю программу, возвращается тоже целочисленное в родительскую.
Это задание какое дали, или это пересказ "как я понял".

Надо различать программу и процесс. fork() создаёт процесс - точную копию исходного с почти всем наследием, выполнение которого начинается с самого вызова fork();
exec***() выполняет внешнюю программу

Если в лабе нужны именно программы, а не процессы, то тут именованые каналы mkfifo() - для создания головной программой и open() - для открытия дочерней
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 23:17  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Так, стоп.
Теперь я вообще ничего не понял.

Задание:

Это задание какое дали, или это пересказ "как я понял".

Надо различать программу и процесс. fork() создаёт процесс - точную копию исходного с почти всем наследием, выполнение которого начинается с самого вызова fork();
exec***() выполняет внешнюю программу

Если в лабе нужны именно программы, а не процессы, то тут именованые каналы mkfifo() - для создания головной программой и open() - для открытия дочерней
Вот формализованное задание из методического указания. Но я не думаю, что это кардинально изменит ситуацию.

Для обмена данными между неродственными процессами рекомендуется использовать именованные каналы. Для обмена информацией между родительскими и порождёнными процессами рекомендуется использовать неименованные каналы.

В соответствии с особенностями реализации варианта задания выбрать средство реализации межзадачных коммуникаций.
Модифицировать и отладить в соответствии с вариантом и выбранным средством коммуникации программу из лабораторной работы №3, реализующую порождённый процесс. При необходимости модифицировать её в отдельную программу-сервер.
Модифицировать и отладить в соответствии с вариантом и выбранным средством коммуникации программу из лабораторной работы №3, реализующую родительский процесс. При необходимости модифицировать её в отдельную программу-клиент.
Поскольку процессы здесь родственные, нужно использовать неименованные каналы.
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 23:23
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
Поскольку процессы здесь родственные, нужно использовать неименованные каналы.
И какая родственная связь между
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
Родительская программа:
и
Цитата Сообщение от WillfordRockwel Посмотреть сообщение
Дочерняя программа:
?
Это два отдельных экзешника, никак между собой не связанных. Потому каналы именованные.
0
0 / 0 / 0
Регистрация: 18.10.2017
Сообщений: 8
19.10.2017, 23:26  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
Надо различать программу и процесс. fork() создаёт процесс - точную копию исходного с почти всем наследием, выполнение которого начинается с самого вызова fork();
exec***() выполняет внешнюю программу
Вы же сами указали, что процесс выполняет внешнюю программу.
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
19.10.2017, 23:40
"внешняя программа" - это и есть "неродственный процесс", т.е. последовательность кода, никак не связанная с родителем(нет, есть конечно getppid() и прочее). У них изначально нет общей памяти, нет общего кода, нет общих открытых дескрипторов и п.р. Всё это надо создавать.

Зачем плодить толпу родственных_процессов (посредством fork()), и затем налаживать к-то обмен с родителем, что бы потом из них только запускать неродственный_процесс?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.10.2017, 23:40
Помогаю со студенческими работами здесь

Неименованные каналы
Привет всем! Подскажите, пожалуйста, как работать с неименованными каналами. Может есть какие-то примеры? Как использовать...

Именованные и неименованные каналы
Доброго времени суток. Возникла проблема с заданиями нужно срочно сдавать а я не имею ни малейшего понятия как его делать. Может кто...

Именованные и неименованные константы
Друзья, здравствуйте! Не понимаю, что из себя представляют неименованные константы. Именованные - это const тип переменная =...

Создание дочерних процессов. Пайпы
Здравствуйте, подскажите, пожалуйста, что не так. Есть программа, сортирующая файл: sort.cpp #include &lt;stdio.h&gt; #include...

Как использовать неименованные объекты?
Не очень понятно, как можно использовать не именованные объекты в С++, или Си, ведь это же вызывает ошибки, или существуют, какие-нибудь...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru