powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / pipe
4 сообщений из 4, страница 1 из 1
pipe
    #35021941
olmas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот есть программа с коментами,а как работает она так и не ясно. Что-то не понятно,что куда записывается,отсылается и для чего нужно продублировать.И возник вопрос с функцией: wait(&s); Откуда взялось s? Помогите разобраться,пожалуйста:
Код: plaintext
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.
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

int main()
{
int cd[ 2 ],pid,s;//переменные типа int,  cd дескриптор процесса
char b[ 10 ];//буфер для чтения  из межпроцессного канала 
pipe(cd);

if (((pid=fork()))< 0 ) 
	{
	perror("fork");"); //Если произошла ошибка, то выводим причину ошибки
	return -1;// Аварийное завершение программы	
        }
else
{
if (!pid)
	{
	//Процесс-потомок
close(1);//Закрываем стандартный вывод
	close(cd[0]);//Закрываем канал на чтение
	dup2(cd[1],1);//Дублируем канал (на запись) на стандартный вывод
	close(cd[1]);//Удаление копии
		
	printf("Hello word\n");//Посылка в межпроцессный канал строчки текста
	}
	else
	{
      // Процесс  - родитель
	wait(&s);//Ожидаем завершения процесса потомка
      close(cd[ 1 ]); //Закрытие межпроцессного канала на запись
	close( 0 );// Закрытие стандартного вывода
dup2(cd[ 0 ], 0 );// Дублирование дескриптора межпроцессного канала (чтение) //на стандартный ввод
	close(cd[ 0 ]);//Удаление копии
read( 0 ,b, 10 );//Чтение  из стандартного ввода  10  байт в  буфер b
write( 1 ,b, 10 );//Запись  из стандартного ввода  10  байт из буфера b
	}
}
 return  0 ;
}
Очень нужна ваша помощь,а то совсем запуталась в программе. В Си не секу почти никак,поэтому обращаюсь к вам за помощью.
...
Рейтинг: 0 / 0
pipe
    #35022061
--null--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как же без Си разбираться в таких программах? и главное - зачем?
Наверное, то, что я напишу - будет Вам непонятно.

в wait взялась s правильно - это переменная int, куда запишется статус завершённого процесса,
но вот объявить её - забыли.

int s;

Вкратце что тут делается: из родительского процесса создаётся дочерний процесс, он выводит стандартной библиотекой
строку на stdout, а у родительского процесса к этому stdout-у присоединён stdin, потому
получается, что он эту строку может прочитать (read). Он ждёт завершения дочки и потом читает и сам уже выводит.

Как известно, у процесса есть дескриптор ввода (0) и вывода(1), с ними и будут манипуляции.

Надо понять, что оба процесса имеют очень узкоочерченные задачи:

Дочерний - только отдать строку в поток (записать) и больше ничего не делать
Родительский - только прочитать строку и потом вывести её в свой stdout.

Потому дочке нужна будет только часть пайпа для вывода cd[1], а родителю - только для ввода cd[0].



Самый важный вызов тут - pipe(cd)


После него массив cd заполняется двумя дескрипторами: для ввода cd[0] и для вывода cd[1]
Это и есть пайп. Это совершенно новые дескрипторы, никакого отношения пока что к стандартным не имеющие, они привязаны к пайпу - дают возможность записать в него что-то и затем считать из него соответственно.


После fork создаётся дочерний процесс.
при этом после ветвления оба процесса будут разделять дескрипторы пайпа cd[0] и cd[1].
Совершенно равноправно. Это важно.

Дальше в каждом процессе обрисовывается узкая задача.

В ПОТОМКЕ:

close(1);//Закрываем стандартный вывод -
-мы его всё равно перенаправим в пайп. Но вообще-то это лишний вызов - dup2
потом всё равно закроет, это документировано.

close(cd[0]);//Закрываем канал на чтение
- читать из пайпа мы не будем вообще ничего

dup2(cd[1],1);//Дублируем канал (на запись) на стандартный вывод

-вот важный вызов. Второй параметр станет копией первого. То есть что в один попадёт- то и в другой. Потому в будущем всё записанное в stdout (дескриптор 1) пойдёт на самом деле в пайп -
используется cd[1], так как он для вывода.
Если второй параметр - открытый дескриптор - то перед копированием вызов его закроет,
так что close(1) вначале -излишество.

close(cd[1]);//Удаление копии
-мы и так сделали, что всё записывается в stdout(1) пойдёт в пайп - поэтому эта копия дескриптора не нужна.

printf("Hello word\n");//Посылка в межпроцессный канал строчки текста

Теперь всё, то стандартная библиотека и вызовы посылают на stdout(1) - будет уходить в пайп.

В итоге мы получили процесс-потомок, который не может ничего прочитать из канала (пайп ввода закрыт),
но зато всё, что печатается им на stdout - уйдёт в пайп.


В РОДИТЕЛЕ:

wait(&s);//Ожидаем завершения процесса потомка
-процесс заблокируется, пока не завершится дочка и не пришлёт SIGCHLD - так
как нам надо дождаться, чтобы она записала что-то в пайп, что мы потом будем читать.
Хотя дочка завершится, данные всё равно будут оставаться в пайпе (как будто они в файле).
Потому что он общий для обоих процессов.

close(cd[1]); //Закрытие межпроцессного канала на запись
-мы не собирались писать в пайп в этом процессе.
close(0);// Закрытие стандартного ВВОДА (ошибка в родном комментарии!)
- опять это лишний вызов - dup2 потом всё равно закроет.
суть опять же в том, что читать мы будем только из пайпа.

dup2(cd[0],0);// Дублирование дескриптора межпроцессного канала (чтение) //на стандартный ввод

- тоже вызов dup для копирования,
Второй параметр станет копией первого. То есть читать из одного - то же, что и читать из другого. Потому в будущем всё якобы читаемое из stdin (дескриптор 0) на самом деле будет читаться из пайпа - используется cd[0], так как он для ввода.
Если второй параметр - открытый дескриптор - то перед копированием вызов его закроет,
так что close(0) вначале -излишество.

close(cd[0]);//Удаление копии
-мы и так сделали, что всё читается из stdin(1) - на самом деле читается из пайпа - поэтому эта копия не нужна.

read(0,b,10);//Чтение из стандартного ввода 10 байт в буфер b
-прочитали вроде бы из stdin - а на самом деле из пайпа!
write(1,b,10);//Запись из стандартного ввода 10 байт из буфера b
- просто вывели на свой stdout
...
Рейтинг: 0 / 0
pipe
    #35022069
--null--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторint cd[2],pid,s;

просмотрел - s объявлена.
...
Рейтинг: 0 / 0
pipe
    #35022091
olmas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо большое. Все так понятно объяснил,просто супер. Терь можно со спокойной душой идти и сдавать это))) Я очень тебе благодарна
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Unix-системы [игнор отключен] [закрыт для гостей] / pipe
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]