|
|
|
pipe
|
|||
|---|---|---|---|
|
#18+
Вот есть программа с коментами,а как работает она так и не ясно. Что-то не понятно,что куда записывается,отсылается и для чего нужно продублировать.И возник вопрос с функцией: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.12.2007, 23:11:01 |
|
||
|
pipe
|
|||
|---|---|---|---|
|
#18+
Как же без Си разбираться в таких программах? и главное - зачем? Наверное, то, что я напишу - будет Вам непонятно. в 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 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2007, 01:05:05 |
|
||
|
pipe
|
|||
|---|---|---|---|
|
#18+
авторint cd[2],pid,s; просмотрел - s объявлена. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2007, 01:13:45 |
|
||
|
|

start [/forum/topic.php?fid=25&fpage=162&tid=1487325]: |
0ms |
get settings: |
7ms |
get forum list: |
17ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
23ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
25ms |
get tp. blocked users: |
1ms |
| others: | 284ms |
| total: | 371ms |

| 0 / 0 |
